summaryrefslogtreecommitdiffstats
path: root/kalzium/src/solver
diff options
context:
space:
mode:
Diffstat (limited to 'kalzium/src/solver')
-rw-r--r--kalzium/src/solver/Makefile92
-rw-r--r--kalzium/src/solver/README19
-rw-r--r--kalzium/src/solver/calc.ml53
-rw-r--r--kalzium/src/solver/calc.mli3
-rw-r--r--kalzium/src/solver/chem.ml60
-rw-r--r--kalzium/src/solver/chem.mli2
-rw-r--r--kalzium/src/solver/chemset.ml82
-rw-r--r--kalzium/src/solver/chemset.mli10
-rw-r--r--kalzium/src/solver/datastruct.ml141
-rw-r--r--kalzium/src/solver/datastruct.mli23
-rw-r--r--kalzium/src/solver/lexer.ml189
-rw-r--r--kalzium/src/solver/lexer.mll41
-rw-r--r--kalzium/src/solver/main.c46
-rw-r--r--kalzium/src/solver/main.ml46
-rw-r--r--kalzium/src/solver/modwrap.c37
-rw-r--r--kalzium/src/solver/parser.ml317
-rw-r--r--kalzium/src/solver/parser.mli15
-rw-r--r--kalzium/src/solver/parser.mly83
18 files changed, 1259 insertions, 0 deletions
diff --git a/kalzium/src/solver/Makefile b/kalzium/src/solver/Makefile
new file mode 100644
index 00000000..4b96fdb7
--- /dev/null
+++ b/kalzium/src/solver/Makefile
@@ -0,0 +1,92 @@
+
+OCAMLC = ocamlc -g
+OCAMLMLI = ocamlc
+OCAMLOPT = ocamlopt
+OCAMLDEP = ocamldep
+INCLUDES = -I +facile
+OPTOPT =
+OCAMLLIB := `ocamlc -where`
+FACILELIB = $(OCAMLLIB)/facile
+
+
+# link to these libraries
+LIBADD_CMX = $(OCAMLLIB)/facile/facile.cmxa #$(OCAMLLIB)/str.cmxa
+LIBADD_CMO = $(OCAMLLIB)/facile/facile.cma #$(OCAMLLIB)/str.cma
+
+# our sources
+SOURCES_CHEM = chemset.ml parser.ml lexer.ml datastruct.ml chem.ml calc.ml
+SOURCES_WRAP = modwrap.c
+
+# the targets
+CHEM_CMO = $(SOURCES_CHEM:.ml=.cmo)
+CHEM_CMX = $(SOURCES_CHEM:.ml=.cmx)
+CHEM_O = $(SOURCES_WRAP:.c=.o)
+
+# default target : the object files for eqchem
+all : solver.o
+
+# shows how to build a program that embeds the solver
+# in compiled ocaml, bytecode ocaml and compiled program using compiled caml code
+test: atestprog.opt btestprog.out testcprog
+
+atestprog.opt: $(CHEM_CMX) main.cmx
+ $(OCAMLOPT) -o $@ $(LIBADD_CMX) $(CHEM_CMX) main.cmx
+
+btestprog.out: $(CHEM_CMO) main.cmo
+ $(OCAMLMLI) -o $@ $(LIBADD_CMO) $(CHEM_CMO) main.cmo
+
+solver.o: $(CHEM_CMX) $(CHEM_O)
+ $(OCAMLOPT) -output-obj -o solver.o $(LIBADD_CMX) $(CHEM_CMX)
+ cp -f solver.o modwrap.o ../
+
+testcprog: $(CHEM_CMX) $(CHEM_O)
+ $(OCAMLOPT) -output-obj -o solver.o $(LIBADD_CMX) $(CHEM_CMX) modwrap.o
+ gcc -c -o main.o main.c -L $(OCAMLLIB)
+ gcc -o $@ main.o solver.o -L $(OCAMLLIB) \
+ -L $(OCAMLLIB)/facile -lasmrun -lstr -lnums -lm -ldl modwrap.o
+
+.SUFFIXES:
+.SUFFIXES: .ml .mli .mly .mll .cmi .cmo .cmx .p.cmx .c
+
+.ml.cmo :
+ $(OCAMLC) $(INCLUDES) $(INCLUDES) -c $<
+
+.mli.cmi :
+ $(OCAMLMLI) $(INCLUDES) -c $<
+
+.ml.cmx :
+ $(OCAMLOPT) $(OPTOPT) $(INCLUDES) -c $<
+
+.mly.ml :
+ ocamlyacc $<
+
+.mll.ml :
+ ocamllex $<
+
+%.o : %.c
+ $(OCAMLOPT) $(OPTOPT) $(INCLUDES) -c $<
+
+clean:
+ \rm -f *.cm[iox] *.o *~ .depend *testprog.* testcprog
+
+cleanall : clean
+ \rm -f *.cmxa *.a *.cma
+
+distclean : clean
+
+interfaces:
+ ocamlc -i datastruct.ml > datastruct.mli
+ ocamlc -I +facile -i chem.ml > chem.mli
+ ocamlc -I +facile -i calc.ml > calc.mli
+
+maintainer-clean : clean
+
+uninstall : clean
+
+install :
+ echo "done"
+
+.depend: parser.ml lexer.ml
+ $(OCAMLDEP) $(INCLUDES) *.mli *.ml > $@
+
+include .depend
diff --git a/kalzium/src/solver/README b/kalzium/src/solver/README
new file mode 100644
index 00000000..c2501bf5
--- /dev/null
+++ b/kalzium/src/solver/README
@@ -0,0 +1,19 @@
+You will need a working objective caml installation and
+the FaCiLe library properly configured and installed
+to compile eqchem.
+
+In practice, one would only run make in this directory (src/solver)
+"make"
+"make clean", etc
+
+To assemble with a c++ or a kde program, the object files
+solver.o and modwrap.o must be added and linked with :
+-L/usr/lib/ocaml -L/usr/lib/ocaml/facile -lasmrun -lstr -lnums -lm -ldl solver.o modwrap.o
+
+The program built can then be run without the objective caml tools.
+
+Console examples can also be generated (try "make test")
+
+
+Thomas Nagy
+
diff --git a/kalzium/src/solver/calc.ml b/kalzium/src/solver/calc.ml
new file mode 100644
index 00000000..745f7c14
--- /dev/null
+++ b/kalzium/src/solver/calc.ml
@@ -0,0 +1,53 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+open Printf;;
+open Chemset;;
+open Datastruct;;
+open Chem;;
+open Hashtbl;;
+
+let create_equation str =
+ let lexbuf = Lexing.from_string str in
+ let result = Parser.main Lexer.token lexbuf in
+ result
+;;
+
+exception Not_found;;
+
+let solve_equation (str:string) =
+ let eq = new eqtable in
+ try
+ eq#build (create_equation str);
+ try
+(* eq#print_all (); *)
+ solve eq;
+ eq#get_eq_sol ();
+
+ with | _ -> begin
+ let str = (eq#get_eq_orig ())^" : No solution found" in
+ (*cleanup eq;*)
+ str
+ end
+ with | _ -> str^" : Parse Error";
+;;
+
+let _ = Callback.register "solve_equation" solve_equation;;
+
diff --git a/kalzium/src/solver/calc.mli b/kalzium/src/solver/calc.mli
new file mode 100644
index 00000000..32bd5518
--- /dev/null
+++ b/kalzium/src/solver/calc.mli
@@ -0,0 +1,3 @@
+val create_equation : string -> Chemset.listitems
+exception Not_found
+val solve_equation : string -> string
diff --git a/kalzium/src/solver/chem.ml b/kalzium/src/solver/chem.ml
new file mode 100644
index 00000000..2e0dd96d
--- /dev/null
+++ b/kalzium/src/solver/chem.ml
@@ -0,0 +1,60 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+open Facile;;
+open Easy;;
+open Datastruct;;
+
+let solve (eq : eqtable) =
+ let nb_molecules = eq#getsize_j () and nb_elements = eq#getsize_i () in
+ let dist = Fd.array nb_molecules 1 900 in
+
+ (* trivial constraints on domains *)
+ for j = 0 to nb_molecules -1 do
+ let num = try int_of_string (eq#getvar j) with _ -> -1 in
+ if num > -1 then dist.(j) <- Fd.int num
+ done;
+
+ (* raises an exception if the problem is not solvable *)
+ for i = 0 to nb_elements - 1 do
+ Cstr.post (Arith.scalprod_fd (eq#getline i) dist =~ i2e 0)
+ done;
+
+ let goal = Goals.GlArray.labeling dist in
+ if (Goals.solve goal) then Array.iteri (fun cnt i -> eq#setsol cnt (Fd.min i)) dist
+ else failwith "no solution found"
+;;
+
+(* workaround for (probably) a bug in the facile library 1.0 (fixed in 1.1?) :
+ * when the constraints make a problem
+ * unsolvable, an exception is raised
+ *
+ * unfortunately the next problem
+ * solved afterwards is not handled properly *)
+
+let cleanup (eq : eqtable) =
+(* Printf.printf "cleaning up"; *)
+ let nb_molecules = eq#getsize_j () and nb_elements = eq#getsize_i () in
+ let dist = Fd.array nb_molecules 0 2 in
+ let goal = Goals.GlArray.labeling dist in
+ if not (Goals.solve goal) then failwith "fatal error"
+;;
+
+
diff --git a/kalzium/src/solver/chem.mli b/kalzium/src/solver/chem.mli
new file mode 100644
index 00000000..0e607b2b
--- /dev/null
+++ b/kalzium/src/solver/chem.mli
@@ -0,0 +1,2 @@
+val solve : Datastruct.eqtable -> unit
+val cleanup : Datastruct.eqtable -> unit
diff --git a/kalzium/src/solver/chemset.ml b/kalzium/src/solver/chemset.ml
new file mode 100644
index 00000000..d8136846
--- /dev/null
+++ b/kalzium/src/solver/chemset.ml
@@ -0,0 +1,82 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+open Printf;;
+open Hashtbl;;
+open List;;
+open String;;
+
+type chemtbl = (string, int) Hashtbl.t;;
+type chemrecord = {mutable hashtbl:chemtbl; mutable formula:string};;
+type item = {ikey:string; itbl:chemrecord; mutable sign:int};;
+type listitems = (item) list;;
+
+
+(* add a symbol to a molecule *)
+let chem_addsym (tbl:chemtbl) (sym:string) (qte:int) =
+ let prev_qte = ref 0 in
+ if Hashtbl.mem tbl sym then prev_qte := Hashtbl.find tbl sym;
+ Hashtbl.replace tbl sym (!prev_qte+qte)
+;;
+
+(* add merge two sub_molecules *)
+let chem_add (tbl1:chemrecord) (tbl2:chemrecord) =
+ Hashtbl.iter (fun sym qte -> chem_addsym tbl1.hashtbl sym qte) tbl2.hashtbl;
+ tbl1.formula <- tbl1.formula^tbl2.formula;
+ tbl1
+;;
+
+(* multiply a sub-molecule (amount of atoms) by an integer value *)
+let chem_mult (tbl:chemrecord) (qte:int) =
+ Hashtbl.iter (fun sym old_qte-> Hashtbl.replace tbl.hashtbl sym (old_qte*qte) ) tbl.hashtbl;
+ tbl.formula <- "("^tbl.formula^")"^string_of_int(qte);
+ tbl
+;;
+
+(* creates a small molecule *)
+let createchem (sym:string) (qte:int) =
+
+ let prettyformula () =
+ if String.contains sym '+' || String.contains sym '-' then begin
+ if qte == 1 then "<b><sup>"^sym^"</sup></b>"
+ else "<b><sup>"^string_of_int(qte)^sym^"</sup></b>" end
+ else begin
+ if qte == 1 then sym
+ else sym^"<b><sub>"^string_of_int(qte)^"</sub></b>"
+ end
+ in
+
+ let table = Hashtbl.create 10 in
+ Hashtbl.add table sym qte;
+ { hashtbl=table ; formula=prettyformula() }
+ (*if (qte!=1) then { hashtbl=table ; formula=prettyformula() }
+ else { hashtbl=table ; formula=sym }*)
+;;
+
+let chem_negate (l:listitems) =
+ List.iter (fun i -> i.sign <- -1) l
+;;
+
+(* outputs a molecule *)
+let chem_printitem (i:item) =
+ Printf.printf "item : %s %s %d \n" i.ikey (i.itbl).formula i.sign;
+ Hashtbl.iter (fun sym qte -> Printf.printf " * %s %d\n" sym qte) i.itbl.hashtbl
+;;
+
diff --git a/kalzium/src/solver/chemset.mli b/kalzium/src/solver/chemset.mli
new file mode 100644
index 00000000..64c64bcf
--- /dev/null
+++ b/kalzium/src/solver/chemset.mli
@@ -0,0 +1,10 @@
+type chemtbl = (string, int) Hashtbl.t
+and chemrecord = { mutable hashtbl : chemtbl; mutable formula : string; }
+and item = { ikey : string; itbl : chemrecord; mutable sign : int; }
+and listitems = item list
+val chem_addsym : chemtbl -> string -> int -> unit
+val chem_add : chemrecord -> chemrecord -> chemrecord
+val chem_mult : chemrecord -> int -> chemrecord
+val createchem : string -> int -> chemrecord
+val chem_negate : listitems -> unit
+val chem_printitem : item -> unit
diff --git a/kalzium/src/solver/datastruct.ml b/kalzium/src/solver/datastruct.ml
new file mode 100644
index 00000000..541ed8cd
--- /dev/null
+++ b/kalzium/src/solver/datastruct.ml
@@ -0,0 +1,141 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+open List;;
+open Chemset;;
+open Hashtbl;;
+open Array;;
+
+class eqtable =
+object (self)
+
+(* columns : vars + formula | lines : chemical elements *)
+val mutable numtbl = Array.make_matrix 0 0 0
+val mutable strtbl = Array.make 0 ""
+val mutable vartbl = Array.make 0 ""
+val mutable soltbl = Array.make 0 0
+val mutable m_solved = false
+val mutable m_middle = 0
+
+(* val mutable (table:int array array) = [||] *)
+
+(* lines : i : chem element *)
+(* columns : vars j *)
+method getsize_i () = Array.length numtbl
+method getsize_j () = if (self#getsize_i () > 0) then Array.length numtbl.(0) else 0
+
+method getline j = numtbl.(j)
+
+method getformula k = strtbl.(k)
+method getvar k = vartbl.(k)
+method getsol k = soltbl.(k)
+
+method setsol k v = soltbl.(k) <- v
+method isSolved () = m_solved
+
+method get_eq_sol () =
+ let str = ref "" in
+ for j=0 to (self#getsize_j () -1) do
+ if (j == m_middle) then str := (!str)^" -&gt; "
+ else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
+
+ str := (!str)^"<b>"^string_of_int(self#getsol j)^"</b> "^(self#getformula j);
+ done;
+ !str
+
+method get_eq_orig () =
+ let str = ref "" in
+ for j=0 to (self#getsize_j () -1) do
+ if (j == m_middle) then str := (!str)^" -&gt; "
+ else if (j>0 && j<self#getsize_j ()) then str := (!str)^" + ";
+
+ str := (!str)^"<b>"^(self#getvar j)^"</b> "^(self#getformula j);
+ done;
+ !str
+
+method private init i j = numtbl <- Array.make_matrix i j 0;
+ strtbl <- Array.make j "";
+ vartbl <- Array.make j "";
+ soltbl <- Array.make j 0
+
+method clear () =
+ self#init 0 0;
+
+method print_all () =
+ Printf.printf "--- start print_all ---\n";
+ for i = 0 to (self#getsize_i ())-1 do
+ for j = 0 to (self#getsize_j ())-1 do
+ Printf.printf "%d " (numtbl.(i).(j));
+ done;
+ Printf.printf "\n";
+ done;
+ Printf.printf "--- end print_all ---\n";
+ flush_all ()
+
+(* build the matrix to solve *)
+method build (lst:listitems) =
+ let nb_symbols = ref 0 in
+ let item_array = Array.of_list lst in
+ let record:(string, int) Hashtbl.t = Hashtbl.create 10 in
+ let nb_items = ref (Array.length item_array) in
+ for i=0 to !nb_items-1 do
+ Hashtbl.iter (fun sym _ ->
+ (* take all chemical elements but simplify ions (+ or -) into + *)
+ let symprocessed = if String.contains sym '+' || String.contains sym '-'
+ then "+" else sym in
+
+ if not (Hashtbl.mem record symprocessed) then begin
+ Hashtbl.add record symprocessed !nb_symbols;
+ nb_symbols := !nb_symbols+1
+ end
+ ) item_array.(i).itbl.hashtbl
+ done;
+
+ (* initialize the matrix *)
+ self#init (!nb_symbols) (!nb_items);
+
+ (* process each atom*)
+ for i=0 to !nb_items-1 do
+ (* find the middle (->) - nothing to do with the others things in this loop *)
+ if (item_array.(i).sign<0 && i>0) then (if (item_array.(i-1).sign>0) then m_middle<-i);
+
+ (* store the molecule formula *)
+ vartbl.(i) <- item_array.(i).ikey;
+ strtbl.(i) <- item_array.(i).itbl.formula;
+
+ (* for each molecule, process the atoms *)
+ Hashtbl.iter (fun sym qte ->
+
+ if String.contains sym '+' || String.contains sym '-' then begin
+ (* it is an electric charge *)
+ let chargesign = if String.contains sym '-' then -1 else 1 in
+ let line_idx = (Hashtbl.find record "+") in
+ numtbl.(line_idx).(i) <- qte * item_array.(i).sign * chargesign
+ end
+ else begin
+ (* check if the atom is already there *)
+ let line_idx = (Hashtbl.find record sym) in
+ numtbl.(line_idx).(i) <- (qte * item_array.(i).sign)
+ end
+ ) item_array.(i).itbl.hashtbl
+ done
+
+end;;
+
diff --git a/kalzium/src/solver/datastruct.mli b/kalzium/src/solver/datastruct.mli
new file mode 100644
index 00000000..f2daeb3b
--- /dev/null
+++ b/kalzium/src/solver/datastruct.mli
@@ -0,0 +1,23 @@
+class eqtable :
+ object
+ val mutable m_middle : int
+ val mutable m_solved : bool
+ val mutable numtbl : int array array
+ val mutable soltbl : int array
+ val mutable strtbl : string array
+ val mutable vartbl : string array
+ method build : Chemset.listitems -> unit
+ method clear : unit -> unit
+ method get_eq_orig : unit -> string
+ method get_eq_sol : unit -> string
+ method getformula : int -> string
+ method getline : int -> int array
+ method getsize_i : unit -> int
+ method getsize_j : unit -> int
+ method getsol : int -> int
+ method getvar : int -> string
+ method private init : int -> int -> unit
+ method isSolved : unit -> bool
+ method print_all : unit -> unit
+ method setsol : int -> int -> unit
+ end
diff --git a/kalzium/src/solver/lexer.ml b/kalzium/src/solver/lexer.ml
new file mode 100644
index 00000000..e82d6804
--- /dev/null
+++ b/kalzium/src/solver/lexer.ml
@@ -0,0 +1,189 @@
+# 22 "lexer.mll"
+
+ open Parser;;
+ exception IllegalChar
+
+# 7 "lexer.ml"
+let __ocaml_lex_tables = {
+ Lexing.lex_base =
+ "\000\000\244\255\255\255\075\000\253\255\036\000\251\255\249\255\
+ \248\255\247\255\246\255\000\000\243\255\245\255";
+ Lexing.lex_backtrk =
+ "\255\255\255\255\255\255\001\000\255\255\003\000\255\255\255\255\
+ \255\255\255\255\255\255\005\000\255\255\255\255";
+ Lexing.lex_default =
+ "\001\000\000\000\000\000\255\255\000\000\255\255\000\000\000\000\
+ \000\000\000\000\000\000\255\255\000\000\000\000";
+ Lexing.lex_trans =
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\002\000\002\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \007\000\008\000\000\000\006\000\000\000\011\000\000\000\000\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\000\000\000\000\000\000\000\000\013\000\000\000\
+ \000\000\004\000\004\000\004\000\004\000\004\000\004\000\004\000\
+ \004\000\004\000\004\000\004\000\004\000\004\000\004\000\004\000\
+ \004\000\004\000\004\000\004\000\004\000\004\000\004\000\004\000\
+ \004\000\004\000\004\000\009\000\000\000\010\000\000\000\000\000\
+ \000\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000";
+ Lexing.lex_check =
+ "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\000\000\000\000\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \000\000\000\000\255\255\000\000\255\255\000\000\255\255\255\255\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\255\255\255\255\255\255\255\255\011\000\255\255\
+ \255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\255\255\000\000\255\255\255\255\
+ \255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255";
+ Lexing.lex_base_code =
+ "";
+ Lexing.lex_backtrk_code =
+ "";
+ Lexing.lex_default_code =
+ "";
+ Lexing.lex_trans_code =
+ "";
+ Lexing.lex_check_code =
+ "";
+ Lexing.lex_code =
+ "";
+}
+
+let rec token lexbuf =
+ __ocaml_lex_token_rec lexbuf 0
+and __ocaml_lex_token_rec lexbuf __ocaml_lex_state =
+ match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with
+ | 0 ->
+# 28 "lexer.mll"
+ (token lexbuf)
+# 125 "lexer.ml"
+
+ | 1 ->
+# 29 "lexer.mll"
+ ( INT(int_of_string(Lexing.lexeme lexbuf)) )
+# 130 "lexer.ml"
+
+ | 2 ->
+# 30 "lexer.mll"
+ ( CAPITAL(Lexing.lexeme lexbuf) )
+# 135 "lexer.ml"
+
+ | 3 ->
+# 31 "lexer.mll"
+ ( MINOR(Lexing.lexeme lexbuf) )
+# 140 "lexer.ml"
+
+ | 4 ->
+# 32 "lexer.mll"
+ ( PLUS )
+# 145 "lexer.ml"
+
+ | 5 ->
+# 33 "lexer.mll"
+ ( MINUS )
+# 150 "lexer.ml"
+
+ | 6 ->
+# 34 "lexer.mll"
+ ( LPAREN )
+# 155 "lexer.ml"
+
+ | 7 ->
+# 35 "lexer.mll"
+ ( RPAREN )
+# 160 "lexer.ml"
+
+ | 8 ->
+# 36 "lexer.mll"
+ ( LBRACKET )
+# 165 "lexer.ml"
+
+ | 9 ->
+# 37 "lexer.mll"
+ ( RBRACKET )
+# 170 "lexer.ml"
+
+ | 10 ->
+# 38 "lexer.mll"
+ ( ARROW )
+# 175 "lexer.ml"
+
+ | 11 ->
+# 39 "lexer.mll"
+ ( raise IllegalChar; )
+# 180 "lexer.ml"
+
+ | 12 ->
+# 40 "lexer.mll"
+ ( EOF )
+# 185 "lexer.ml"
+
+ | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state
+
+;;
+
diff --git a/kalzium/src/solver/lexer.mll b/kalzium/src/solver/lexer.mll
new file mode 100644
index 00000000..a6a4ab49
--- /dev/null
+++ b/kalzium/src/solver/lexer.mll
@@ -0,0 +1,41 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+(* File lexer.mll*)
+{
+ open Parser;;
+ exception IllegalChar
+}
+
+rule token = parse
+[' ' '\t' '\n'] {token lexbuf} (* ignore whitespaces *)
+| ['0'-'9']+ { INT(int_of_string(Lexing.lexeme lexbuf)) }
+| ['A'-'Z'] { CAPITAL(Lexing.lexeme lexbuf) }
+| ['a'-'z']+ { MINOR(Lexing.lexeme lexbuf) }
+| '+' { PLUS }
+| '-' { MINUS }
+| '(' { LPAREN }
+| ')' { RPAREN }
+| '[' { LBRACKET }
+| ']' { RBRACKET }
+| "->" { ARROW }
+| _ { raise IllegalChar; }
+| eof { EOF }
+
diff --git a/kalzium/src/solver/main.c b/kalzium/src/solver/main.c
new file mode 100644
index 00000000..d8e5e1bc
--- /dev/null
+++ b/kalzium/src/solver/main.c
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char ** argv)
+{
+ caml_startup(argv);
+
+ char * eq = " a CH3(CH2)3COOH + b O2 -> c H2O + d CO2";
+ char * eq2= " a CH3(CH2)3COOH + b O2 -> c H2O + d CO";
+ char * result = solve_equation(eq);
+ char * result2 = solve_equation(eq2);
+
+ printf("solution : %s\n", result);
+
+ printf("solution : %s\n", result2);
+ free(result2);
+
+ result2 = solve_equation(eq);
+ printf("solution : %s\n", result2);
+
+ free(result);
+ free(result2);
+
+ return 0;
+}
+
diff --git a/kalzium/src/solver/main.ml b/kalzium/src/solver/main.ml
new file mode 100644
index 00000000..f940f1de
--- /dev/null
+++ b/kalzium/src/solver/main.ml
@@ -0,0 +1,46 @@
+(***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************)
+
+open Printf;;
+open Calc;;
+
+
+let myeq1 = " a CH3(CH2)3COOH + b O2 -> c H2O + d CO2";;
+let myeq2 = " a CH3COOH + b O2 -> c H2O + d CO2";;
+let myeq3 = " a CH3(CH2)3COOH + b O2 -> invalid equation ";;
+let myeq4 = "2CH4+aC2H6+cO2->eH2O+5CO2";;
+let myeq5 = "a NaNO2 + b NH3 -> b NaN3 + e NaNO3";;
+let myeq6 = "a HNO2 + b NH3 -> b HN3 + e HNO3";;
+let myeq7 = "a H3O[+] + dCO2 + eO2 -> fH2O + dCO3[2+]";;
+
+(* Printf.printf "%s \n" (solve_equation myeq1);;
+Printf.printf "%s \n" (solve_equation myeq2);;
+Printf.printf "%s \n" (solve_equation myeq3);; *)
+(*
+Printf.printf "%s \n" (solve_equation myeq5);;
+Printf.printf "%s \n" (solve_equation myeq6);;
+Printf.printf "%s \n" (solve_equation myeq6);;
+
+Printf.printf "%s \n" (solve_equation myeq6);;*)
+Printf.printf "%s \n" (solve_equation myeq7);;
+
+
+
+
diff --git a/kalzium/src/solver/modwrap.c b/kalzium/src/solver/modwrap.c
new file mode 100644
index 00000000..0ab5359e
--- /dev/null
+++ b/kalzium/src/solver/modwrap.c
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <caml/mlvalues.h>
+#include <caml/callback.h>
+
+char* solve_equation(const char * eq)
+{
+ static value * solve_equation_closure = NULL;
+ if (solve_equation_closure == NULL)
+ {
+ solve_equation_closure = caml_named_value("solve_equation");
+ }
+
+ return strdup(String_val(callback(*solve_equation_closure, copy_string(eq)) ));
+}
+
diff --git a/kalzium/src/solver/parser.ml b/kalzium/src/solver/parser.ml
new file mode 100644
index 00000000..8d7cc3c6
--- /dev/null
+++ b/kalzium/src/solver/parser.ml
@@ -0,0 +1,317 @@
+type token =
+ | INT of (int)
+ | PLUS
+ | MINUS
+ | LPAREN
+ | RPAREN
+ | LBRACKET
+ | RBRACKET
+ | EOF
+ | CAPITAL of (string)
+ | MINOR of (string)
+ | ARROW
+
+open Parsing;;
+# 26 "parser.mly"
+ open Chemset
+
+ (*let parse_error somestring = Printf.printf "%s \n" somestring;;
+ *)
+# 21 "parser.ml"
+let yytransl_const = [|
+ 258 (* PLUS *);
+ 259 (* MINUS *);
+ 260 (* LPAREN *);
+ 261 (* RPAREN *);
+ 262 (* LBRACKET *);
+ 263 (* RBRACKET *);
+ 0 (* EOF *);
+ 266 (* ARROW *);
+ 0|]
+
+let yytransl_block = [|
+ 257 (* INT *);
+ 264 (* CAPITAL *);
+ 265 (* MINOR *);
+ 0|]
+
+let yylhs = "\255\255\
+\001\000\002\000\003\000\003\000\004\000\004\000\005\000\005\000\
+\006\000\006\000\006\000\006\000\006\000\006\000\006\000\007\000\
+\007\000\000\000"
+
+let yylen = "\002\000\
+\002\000\003\000\001\000\003\000\002\000\002\000\001\000\002\000\
+\002\000\001\000\004\000\004\000\004\000\003\000\003\000\002\000\
+\001\000\002\000"
+
+let yydefred = "\000\000\
+\000\000\000\000\000\000\000\000\018\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\006\000\000\000\000\000\005\000\001\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\016\000\008\000\
+\009\000\002\000\004\000\000\000\000\000\000\000\014\000\015\000\
+\011\000\012\000\013\000"
+
+let yydgoto = "\002\000\
+\005\000\006\000\007\000\008\000\012\000\013\000\014\000"
+
+let yysindex = "\255\255\
+\003\255\000\000\010\255\010\255\000\000\003\000\252\254\011\255\
+\010\255\018\255\008\255\000\000\010\255\021\255\000\000\000\000\
+\003\255\003\255\020\255\007\255\019\255\022\255\000\000\000\000\
+\000\000\000\000\000\000\026\255\023\255\024\255\000\000\000\000\
+\000\000\000\000\000\000"
+
+let yyrindex = "\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\000\
+\000\000\000\000\001\000\000\000\015\000\008\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000"
+
+let yygindex = "\000\000\
+\000\000\000\000\006\000\000\000\254\255\000\000\000\000"
+
+let yytablesize = 281
+let yytable = "\001\000\
+\017\000\015\000\016\000\003\000\003\000\017\000\019\000\010\000\
+\029\000\030\000\024\000\004\000\018\000\009\000\007\000\010\000\
+\023\000\011\000\020\000\021\000\022\000\025\000\026\000\027\000\
+\028\000\031\000\033\000\000\000\032\000\034\000\035\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\017\000\017\000\000\000\017\000\017\000\017\000\000\000\
+\017\000\010\000\017\000\010\000\010\000\010\000\003\000\010\000\
+\007\000\010\000\000\000\007\000\000\000\000\000\000\000\000\000\
+\007\000"
+
+let yycheck = "\001\000\
+\000\000\004\000\000\000\001\001\000\000\010\001\009\000\000\000\
+\002\001\003\001\013\000\009\001\002\001\004\001\000\000\006\001\
+\009\001\008\001\001\001\002\001\003\001\001\001\017\000\018\000\
+\005\001\007\001\001\001\255\255\007\001\007\001\007\001\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+\255\255\001\001\002\001\255\255\004\001\005\001\006\001\255\255\
+\008\001\002\001\010\001\004\001\005\001\006\001\010\001\008\001\
+\002\001\010\001\255\255\005\001\255\255\255\255\255\255\255\255\
+\010\001"
+
+let yynames_const = "\
+ PLUS\000\
+ MINUS\000\
+ LPAREN\000\
+ RPAREN\000\
+ LBRACKET\000\
+ RBRACKET\000\
+ EOF\000\
+ ARROW\000\
+ "
+
+let yynames_block = "\
+ INT\000\
+ CAPITAL\000\
+ MINOR\000\
+ "
+
+let yyact = [|
+ (fun _ -> failwith "parser")
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 1 : 'equation) in
+ Obj.repr(
+# 44 "parser.mly"
+ ( _1 )
+# 177 "parser.ml"
+ : Chemset.listitems))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 2 : 'expr) in
+ let _3 = (peek_val parser_env 0 : 'expr) in
+ Obj.repr(
+# 49 "parser.mly"
+ ( chem_negate _3; List.append _1 _3 )
+# 185 "parser.ml"
+ : 'equation))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 0 : 'item) in
+ Obj.repr(
+# 53 "parser.mly"
+ ( _1::[] )
+# 192 "parser.ml"
+ : 'expr))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 2 : 'item) in
+ let _3 = (peek_val parser_env 0 : 'expr) in
+ Obj.repr(
+# 54 "parser.mly"
+ ( _1::_3 )
+# 200 "parser.ml"
+ : 'expr))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 1 : string) in
+ let _2 = (peek_val parser_env 0 : 'symbols) in
+ Obj.repr(
+# 58 "parser.mly"
+ ( {ikey=_1; itbl=_2; sign=1} )
+# 208 "parser.ml"
+ : 'item))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 1 : int) in
+ let _2 = (peek_val parser_env 0 : 'symbols) in
+ Obj.repr(
+# 59 "parser.mly"
+ ( {ikey=string_of_int(_1); itbl=_2; sign=1} )
+# 216 "parser.ml"
+ : 'item))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 0 : 'qte) in
+ Obj.repr(
+# 63 "parser.mly"
+ ( _1 )
+# 223 "parser.ml"
+ : 'symbols))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 1 : 'qte) in
+ let _2 = (peek_val parser_env 0 : 'symbols) in
+ Obj.repr(
+# 64 "parser.mly"
+ ( chem_add _1 _2 )
+# 231 "parser.ml"
+ : 'symbols))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 1 : 'element) in
+ let _2 = (peek_val parser_env 0 : int) in
+ Obj.repr(
+# 68 "parser.mly"
+ ( createchem _1 _2 )
+# 239 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 0 : 'element) in
+ Obj.repr(
+# 69 "parser.mly"
+ ( createchem _1 1 )
+# 246 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ let _2 = (peek_val parser_env 2 : 'symbols) in
+ let _4 = (peek_val parser_env 0 : int) in
+ Obj.repr(
+# 70 "parser.mly"
+ ( chem_mult _2 _4 )
+# 254 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ let _2 = (peek_val parser_env 2 : int) in
+ Obj.repr(
+# 71 "parser.mly"
+ ( createchem "+" _2 )
+# 261 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ let _2 = (peek_val parser_env 2 : int) in
+ Obj.repr(
+# 72 "parser.mly"
+ ( createchem "-" _2 )
+# 268 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ Obj.repr(
+# 73 "parser.mly"
+ ( createchem "+" 1 )
+# 274 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ Obj.repr(
+# 74 "parser.mly"
+ ( createchem "-" 1 )
+# 280 "parser.ml"
+ : 'qte))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 1 : string) in
+ let _2 = (peek_val parser_env 0 : string) in
+ Obj.repr(
+# 78 "parser.mly"
+ ( _1 ^ _2 )
+# 288 "parser.ml"
+ : 'element))
+; (fun parser_env ->
+ let _1 = (peek_val parser_env 0 : string) in
+ Obj.repr(
+# 79 "parser.mly"
+ ( _1 )
+# 295 "parser.ml"
+ : 'element))
+(* Entry main *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+|]
+let yytables =
+ { actions=yyact;
+ transl_const=yytransl_const;
+ transl_block=yytransl_block;
+ lhs=yylhs;
+ len=yylen;
+ defred=yydefred;
+ dgoto=yydgoto;
+ sindex=yysindex;
+ rindex=yyrindex;
+ gindex=yygindex;
+ tablesize=yytablesize;
+ table=yytable;
+ check=yycheck;
+ error_function=parse_error;
+ names_const=yynames_const;
+ names_block=yynames_block }
+let main (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) =
+ (yyparse yytables 1 lexfun lexbuf : Chemset.listitems)
diff --git a/kalzium/src/solver/parser.mli b/kalzium/src/solver/parser.mli
new file mode 100644
index 00000000..63d8dece
--- /dev/null
+++ b/kalzium/src/solver/parser.mli
@@ -0,0 +1,15 @@
+type token =
+ | INT of (int)
+ | PLUS
+ | MINUS
+ | LPAREN
+ | RPAREN
+ | LBRACKET
+ | RBRACKET
+ | EOF
+ | CAPITAL of (string)
+ | MINOR of (string)
+ | ARROW
+
+val main :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> Chemset.listitems
diff --git a/kalzium/src/solver/parser.mly b/kalzium/src/solver/parser.mly
new file mode 100644
index 00000000..5aa83cc1
--- /dev/null
+++ b/kalzium/src/solver/parser.mly
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Thomas Nagy *
+ * tnagy2^8@yahoo.fr *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+/* File parser.mly */
+
+
+
+%{
+ open Chemset
+
+ (*let parse_error somestring = Printf.printf "%s \n" somestring;;
+ *)
+%}
+
+%token <int> INT
+%token PLUS MINUS
+%token LPAREN RPAREN LBRACKET RBRACKET
+%token EOF
+%token <string> CAPITAL
+%token <string> MINOR
+%token ARROW
+%start main
+%type <Chemset.listitems> main
+%%
+
+main:
+ equation EOF { $1 }
+;
+
+
+equation:
+ expr ARROW expr { chem_negate $3; List.append $1 $3 }
+;
+
+expr:
+ item { $1::[] }
+ | item PLUS expr { $1::$3 }
+;
+
+item:
+ MINOR symbols { {ikey=$1; itbl=$2; sign=1} }
+ | INT symbols { {ikey=string_of_int($1); itbl=$2; sign=1} }
+;
+
+symbols:
+ qte { $1 }
+ | qte symbols { chem_add $1 $2 }
+;
+
+qte:
+ element INT { createchem $1 $2 }
+ | element { createchem $1 1 }
+ | LPAREN symbols RPAREN INT { chem_mult $2 $4 }
+ | LBRACKET INT PLUS RBRACKET { createchem "+" $2 }
+ | LBRACKET INT MINUS RBRACKET { createchem "-" $2 }
+ | LBRACKET PLUS RBRACKET { createchem "+" 1 }
+ | LBRACKET MINUS RBRACKET { createchem "-" 1 }
+;
+
+element:
+ CAPITAL MINOR { $1 ^ $2 }
+ | CAPITAL { $1 }
+;
+
+
+