diff options
Diffstat (limited to 'kalzium/src/solver')
-rw-r--r-- | kalzium/src/solver/Makefile | 92 | ||||
-rw-r--r-- | kalzium/src/solver/README | 19 | ||||
-rw-r--r-- | kalzium/src/solver/calc.ml | 53 | ||||
-rw-r--r-- | kalzium/src/solver/calc.mli | 3 | ||||
-rw-r--r-- | kalzium/src/solver/chem.ml | 60 | ||||
-rw-r--r-- | kalzium/src/solver/chem.mli | 2 | ||||
-rw-r--r-- | kalzium/src/solver/chemset.ml | 82 | ||||
-rw-r--r-- | kalzium/src/solver/chemset.mli | 10 | ||||
-rw-r--r-- | kalzium/src/solver/datastruct.ml | 141 | ||||
-rw-r--r-- | kalzium/src/solver/datastruct.mli | 23 | ||||
-rw-r--r-- | kalzium/src/solver/lexer.ml | 189 | ||||
-rw-r--r-- | kalzium/src/solver/lexer.mll | 41 | ||||
-rw-r--r-- | kalzium/src/solver/main.c | 46 | ||||
-rw-r--r-- | kalzium/src/solver/main.ml | 46 | ||||
-rw-r--r-- | kalzium/src/solver/modwrap.c | 37 | ||||
-rw-r--r-- | kalzium/src/solver/parser.ml | 317 | ||||
-rw-r--r-- | kalzium/src/solver/parser.mli | 15 | ||||
-rw-r--r-- | kalzium/src/solver/parser.mly | 83 |
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)^" -> " + 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)^" -> " + 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 } +; + + + |