diff --git a/.gitignore b/.gitignore index ab4de4e..5bbeeb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,59 +1,66 @@ # Compiled Object files *.slo *.lo *.o *.obj # Compiled Dynamic libraries *.so *.so.* *.dylib *.dll # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app *.class # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.ear # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* # Qt-es /.qmake.cache /.qmake.stash *.pro.user *.pro.user.* *.moc moc_*.cpp qrc_*.cpp ui_*.h Makefile* *-build-* # QtCreator *.autosave coco/*.old coco/*~ +*~ +cpp/build-debug/* cpp/xreate-debug/* cpp/xreate-release/* +cpp/.idea +cpp/CMakeLists.txt.user* hs/* +project/* +nb*.xml +target/* diff --git a/books/dependency-solver/potassco/clingo4.pdf b/books/dependency-solver/potassco/clingo4.pdf new file mode 100644 index 0000000..df5c820 Binary files /dev/null and b/books/dependency-solver/potassco/clingo4.pdf differ diff --git a/books/dependency-solver/guide.pdf b/books/dependency-solver/potassco/guide.pdf similarity index 100% rename from books/dependency-solver/guide.pdf rename to books/dependency-solver/potassco/guide.pdf diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/abstract.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/abstract.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/abstract.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/abstract.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/background.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/background.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/background.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/background.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/comments.sty b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/comments.sty similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/comments.sty rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/comments.sty diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/errors.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/errors.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/errors.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/errors.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/aggr.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/aggr.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/aggr.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/aggr.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/arithc.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/arithc.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/arithc.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/arithc.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/arithf.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/arithf.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/arithf.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/arithf.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/assign.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/assign.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/assign.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/assign.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/bird.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/bird.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/bird.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/bird.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/blocks.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/blocks.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/blocks.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/blocks.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/color.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/color.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/color.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/color.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/cond.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/cond.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/cond.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/cond.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/costs.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/costs.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/costs.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/costs.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/enc_toh.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/enc_toh.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/enc_toh.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/enc_toh.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/flycn.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/flycn.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/flycn.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/flycn.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/graph.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/graph.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/graph.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/graph.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/ham.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/ham.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/ham.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/ham.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/inc.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/inc.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/inc.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/inc.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/inst_toh.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/inst_toh.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/inst_toh.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/inst_toh.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/int.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/int.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/int.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/int.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/luaf.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/luaf.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/luaf.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/luaf.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/luav.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/luav.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/luav.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/luav.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/meta.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/meta.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/meta.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/meta.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/min.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/min.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/min.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/min.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/opt.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/opt.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/opt.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/opt.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/pool.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/pool.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/pool.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/pool.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/sep.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/sep.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/sep.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/sep.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/sql.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/sql.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/sql.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/sql.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/symbc.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/symbc.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/symbc.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/symbc.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/twocond.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/twocond.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/twocond.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/twocond.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/unify.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/unify.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/unify.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/unify.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/world0.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world0.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/world0.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world0.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/world1.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world1.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/world1.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world1.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/world2.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world2.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/world2.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world2.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/world3.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world3.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/world3.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world3.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/examples/world4.lp b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world4.lp similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/examples/world4.lp rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/examples/world4.lp diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/figures/color.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/color.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/figures/color.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/color.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/figures/costs.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/costs.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/figures/costs.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/costs.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/figures/graph.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/graph.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/figures/graph.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/graph.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/figures/hanoi.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/hanoi.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/figures/hanoi.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/hanoi.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/figures/tsp.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/tsp.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/figures/tsp.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/figures/tsp.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/future.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/future.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/future.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/future.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/guide.bib b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.bib similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/guide.bib rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.bib diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/guide.ind b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.ind similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/guide.ind rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.ind diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/guide.rao b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.rao similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/guide.rao rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.rao diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/guide.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/guide.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/guide.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/introduction.log b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/introduction.log similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/introduction.log rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/introduction.log diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/introduction.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/introduction.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/introduction.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/introduction.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/language.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/language.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/language.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/language.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/lparse.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/lparse.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/lparse.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/lparse.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/macro.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/macro.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/macro.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/macro.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/options.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/options.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/options.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/options.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/quickstart.tex b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/quickstart.tex similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/quickstart.tex rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/quickstart.tex diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source/rail.sty b/books/dependency-solver/potassco/potassco_guide-2010-10-04-source/rail.sty similarity index 100% rename from books/dependency-solver/potassco_guide-2010-10-04-source/rail.sty rename to books/dependency-solver/potassco/potassco_guide-2010-10-04-source/rail.sty diff --git a/books/dependency-solver/potassco_guide-2010-10-04-source.tar.gz b/books/dependency-solver/potassco_guide-2010-10-04-source.tar.gz deleted file mode 100644 index 55653e4..0000000 Binary files a/books/dependency-solver/potassco_guide-2010-10-04-source.tar.gz and /dev/null differ diff --git a/coco/Parser.cpp b/coco/Parser.cpp index b41dbee..fe5a29f 100644 --- a/coco/Parser.cpp +++ b/coco/Parser.cpp @@ -1,496 +1,664 @@ /*---------------------------------------------------------------------- Compiler Generator Coco/R, Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz extended by M. Loeberbauer & A. Woess, Univ. of Linz ported to C++ by Csaba Balazs, University of Szeged with improvements by Pat Terry, Rhodes University 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As an exception, it is allowed to write an extension of Coco/R that is used as a plugin in non-free software. If not otherwise stated, any source code generated by Coco/R (other than Coco/R itself) does not fall under the GNU General Public License. -----------------------------------------------------------------------*/ #include #include "Parser.h" #include "Scanner.h" void Parser::SynErr(int n) { if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n); errDist = 0; } void Parser::SemErr(const wchar_t* msg) { if (errDist >= minErrDist) errors->Error(t->line, t->col, msg); errDist = 0; } void Parser::Get() { for (;;) { t = la; la = scanner->Scan(); if (la->kind <= maxT) { ++errDist; break; } if (dummyToken != t) { dummyToken->kind = t->kind; dummyToken->pos = t->pos; dummyToken->col = t->col; dummyToken->line = t->line; dummyToken->next = NULL; coco_string_delete(dummyToken->val); dummyToken->val = coco_string_create(t->val); t = dummyToken; } la = t; } } void Parser::Expect(int n) { if (la->kind==n) Get(); else { SynErr(n); } } void Parser::ExpectWeak(int n, int follow) { if (la->kind == n) Get(); else { SynErr(n); while (!StartOf(follow)) Get(); } } bool Parser::WeakSeparator(int n, int syFol, int repFol) { if (la->kind == n) {Get(); return true;} else if (StartOf(repFol)) {return false;} else { SynErr(n); while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) { Get(); } return StartOf(syFol); } } void Parser::Xreate() { - while (la->kind == 1) { - FDecl(); + while (la->kind == _ident || la->kind == 24 /* "rule" */) { + if (la->kind == _ident) { + FDecl(); + } else { + RuleDecl(); + } } } void Parser::FDecl() { std::wstring fname; Expression fbody; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut; Ident(fname); - Expect(4); - Expect(5); - Expect(6); + Expect(6 /* "=" */); + Expect(7 /* "function" */); + Expect(8 /* ":" */); Function f = Function(fname); if (StartOf(1)) { Type(typOut); f.setReturnType(typOut); - } else if (la->kind == 7) { + } else if (la->kind == _lparen) { Get(); Ident(varname); - Expect(6); + Expect(8 /* ":" */); Type(typIn); f.addArg(varname, typIn); - while (la->kind == 8) { + while (la->kind == 9 /* "," */) { Get(); Ident(varname); - Expect(6); + Expect(8 /* ":" */); Type(typIn); f.addArg(varname, typIn); } - Expect(9); - } else SynErr(28); - Expect(10); - while (la->kind == 1) { + Expect(_rparen); + Expect(10 /* "->" */); + Type(typOut); + f.setReturnType(typOut); + while (la->kind == 9 /* "," */) { + Get(); + FnTag(f); + } + } else SynErr(35); + Expect(11 /* "{" */); + while (la->kind == _ident) { VDecl(f); - Expect(11); + Expect(12 /* ";" */); } Expr(fbody); - Expect(12); - f.setBody(fbody); + Expect(12 /* ";" */); + Expect(13 /* "}" */); + f.setBody(fbody); root.add(f); +} + +void Parser::RuleDecl() { + Expect(24 /* "rule" */); + Expect(8 /* ":" */); + RuleArguments args; RuleGuards guards; RuleBody body; DomainAnnotation typ; + Expect(_lparen); + Ident(arg); + Expect(8 /* ":" */); + Domain(typ); + args.add(arg, typ); + while (la->kind == 9 /* "," */) { + Get(); + Ident(arg); + Expect(8 /* ":" */); + Domain(typ); + args.add(arg, typ); + } + Expect(_rparen); + if (la->kind == 25 /* "case" */) { + Get(); + RGuard(guards); + while (la->kind == 9 /* "," */) { + Get(); + RGuard(guards); + } + } + + Expect(11 /* "{" */); + RBody(args, guards); + Expect(13 /* "}" */); } void Parser::Ident(std::wstring& name) { - Expect(1); + Expect(_ident); name = t->val; } void Parser::Type(TypeAnnotation& typ) { TypeAnnotation typ2; TypeAtom typ3; - if (la->kind == 18) { + if (la->kind == 19 /* "[" */) { Get(); Type(typ2); - Expect(19); + Expect(20 /* "]" */); typ = TypeAnnotation(TypeOperator::LIST, typ2); } else if (StartOf(2)) { TypeTerm(typ3); typ = TypeAnnotation(typ3); - } else SynErr(29); + } else SynErr(36); +} + +void Parser::FnTag(Function& f) { + std::wstring tag; TagModifier mod = TagModifier::NONE; + Ident(tag); + if (la->kind == 21 /* "-" */) { + Get(); + TagMod(mod); + } + f.addTag(tag, mod); } void Parser::VDecl(Function& f) { std::wstring vname; Expression e; TypeAnnotation typ; Ident(vname); - Expect(4); - if (la->kind == 1 || la->kind == 2 || la->kind == 20) { + Expect(6 /* "=" */); + if (StartOf(3)) { Expr(e); - Expect(6); + Expect(8 /* ":" */); Type(typ); f.addDeclaration(vname, typ, e); - } else if (la->kind == 18) { + } else if (la->kind == 19 /* "[" */) { ListLiteral(e); - Expect(6); + Expect(8 /* ":" */); Type(typ); f.addListDeclaration(vname, typ, e); - } else SynErr(30); - Expect(11); + } else SynErr(37); } void Parser::Expr(Expression& e) { Operator op; Expression e2; SimExpr(e); - if (la->kind == 24 || la->kind == 25 || la->kind == 26) { + if (la->kind == 6 /* "=" */ || la->kind == 29 /* ">" */ || la->kind == 33 /* "<" */) { RelOp(op); SimExpr(e2); - Expression e (op, e); - e.addArg(e2); - + e = Expression(op, e); e.addArg(e2); } } void Parser::TypeTerm(TypeAtom& typ) { - if (la->kind == 13) { + if (la->kind == 14 /* "string" */) { Get(); - } else if (la->kind == 14) { + } else if (la->kind == 15 /* "int" */) { Get(); - } else if (la->kind == 15) { + } else if (la->kind == 16 /* "num" */) { Get(); - } else if (la->kind == 16) { + } else if (la->kind == 17 /* "float" */) { Get(); - } else if (la->kind == 17) { + } else if (la->kind == 18 /* "bool" */) { Get(); - } else SynErr(31); + } else SynErr(38); typ = Atom(t->val); } void Parser::ListLiteral(Expression& e) { Expression e2; - Expect(18); - if (la->kind == 19) { - Get(); - Expect(11); - e = Expression(Operator::LIST, Expression()); - } else if (la->kind == 1 || la->kind == 2 || la->kind == 20) { + Expect(19 /* "[" */); + e = Expression(Operator::LIST, Expression()); + if (StartOf(3)) { Expr(e2); - e = Expression(Operator::LIST, e2); - while (la->kind == 8) { + e.addArg(e2); + while (la->kind == 9 /* "," */) { Get(); Expr(e2); e.addArg(e2); } - Expect(19); - Expect(11); - } else SynErr(32); + } + Expect(20 /* "]" */); +} + +void Parser::TagMod(TagModifier& mod) { + if (la->kind == 22 /* "assert" */) { + Get(); + mod = TagModifier::ASSERT; + } else if (la->kind == 23 /* "require" */) { + Get(); + mod = TagModifier::REQUIRE; + } else SynErr(39); +} + +void Parser::Domain(DomainAnnotation& dom) { + if (la->kind == 7 /* "function" */) { + Get(); + dom = DomainAnnotation::FUNCTION; + } else if (la->kind == 26 /* "variable" */) { + Get(); + dom = DomainAnnotation::VARIABLE; + } else SynErr(40); +} + +void Parser::RGuard(RuleGuards& guards) { + MetaExpression e; + MetaExpr(e); + guards.add(e); +} + +void Parser::RBody(RuleBody& body) { + MetaExpr e; + Expect(27 /* "warning" */); + MetaExpr(e); + if (la->kind == 28 /* "message" */) { + Get(); + Expect(_string); + } +} + +void Parser::MetaExpr(MetaExpression& e) { + MetaExpr2(e); + if (la->kind == 21 /* "-" */) { + MetaOp(op); + MetaExpr2(e2); + MetaParameters params; + params.add(e); + params.add(e2); + e = MetaExpression(op, params); + } +} + +void Parser::MetaExpr2(MetaExpression& e) { + std::wstring i1, i2, infix; MetaParameters params; + if (checkParametersList()) { + Ident(i1); + Expect(_lparen); + if (la->kind == _ident || la->kind == _lparen) { + MetaParams(params); + } + Expect(_rparen); + e = MetaExpression(Operator::CALL, i1, params); + } else if (checkInfix()) { + Ident(i1); + Ident(infix); + Ident(i2); + params.add(Expression(Atom(i1->val))); + params.add(Expression(Atom(i2->val))); + e = MetaExpression(Operator::CALL, Atom(infix->val), params); + } else if (la->kind == _ident) { + Ident(i1); + e = MetaExpression(Atom(i1->val)); + } else if (la->kind == _lparen) { + Get(); + MetaExpr(e); + Expect(_rparen); + } else SynErr(41); +} + +void Parser::MetaOp(Operator& op) { + Expect(21 /* "-" */); + Expect(29 /* ">" */); + op = OPERATOR::IMPL; +} + +void Parser::MetaParams(MetaParameters& params) { + MetaExpr e; + MetaExpr(e); + params.add(e); + while (la->kind == 9 /* "," */) { + Get(); + MetaExpr(e); + params.add(e) + } } void Parser::SimExpr(Expression& e) { Operator op; Expression e2; Term(e); - while (la->kind == 20 || la->kind == 21) { + while (la->kind == 21 /* "-" */ || la->kind == 30 /* "+" */) { AddOp(op); Term(e2); - e = Expression(op, e); - e.addArg(e2); - + e = Expression(op, e); e.addArg(e2); } } void Parser::RelOp(Operator& op) { op = Operator::EQU; - if (la->kind == 24) { + if (la->kind == 6 /* "=" */) { Get(); - } else if (la->kind == 25) { + Expect(6 /* "=" */); + } else if (la->kind == 33 /* "<" */) { Get(); op = Operator::LSS; - } else if (la->kind == 26) { + } else if (la->kind == 29 /* ">" */) { Get(); op = Operator::GTR; - } else SynErr(33); + } else SynErr(42); } void Parser::Term(Expression& e) { Operator op; Expression e2; Factor(e); - while (la->kind == 22 || la->kind == 23) { + while (la->kind == 31 /* "*" */ || la->kind == 32 /* "/" */) { MulOp(op); Factor(e2); - e = Expression(op, e); - e.addArg(e2); - + e = Expression(op, e); e.addArg(e2); } } void Parser::AddOp(Operator& op) { op = Operator::ADD; - if (la->kind == 21) { + if (la->kind == 30 /* "+" */) { Get(); - } else if (la->kind == 20) { + } else if (la->kind == 21 /* "-" */) { Get(); op = Operator::SUB; - } else SynErr(34); + } else SynErr(43); } void Parser::Factor(Expression& e) { - std::wstring name; - if (la->kind == 1) { + std::wstring name; + if (checkParametersList()) { + Ident(name); + e = Expression(Operator::CALL, Atom(name)); + Expect(_lparen); + if (StartOf(3)) { + CalleeParams(e); + } + Expect(_rparen); + } else if (la->kind == _ident) { Ident(name); e = Expression(Atom(name)); - } else if (la->kind == 2) { + } else if (la->kind == _number) { Get(); e = Expression(Atom(t->val)); - } else if (la->kind == 20) { + } else if (la->kind == 21 /* "-" */) { Get(); Factor(e); e = Expression(Operator::NEG, e); - } else SynErr(35); + } else if (la->kind == _lparen) { + Get(); + Expr(e); + Expect(_rparen); + } else SynErr(44); } void Parser::MulOp(Operator& op) { op = Operator::MUL; - if (la->kind == 22) { + if (la->kind == 31 /* "*" */) { Get(); - } else if (la->kind == 23) { + } else if (la->kind == 32 /* "/" */) { Get(); op = Operator::DIV; - } else SynErr(36); + } else SynErr(45); +} + +void Parser::CalleeParams(Expression& e) { + Expression e2; + Expr(e2); + e.addArg(e2); + while (la->kind == 9 /* "," */) { + Get(); + Expr(e2); + e.addArg(e2); + } } // If the user declared a method Init and a mehtod Destroy they should // be called in the contructur and the destructor respctively. // // The following templates are used to recognize if the user declared // the methods Init and Destroy. template struct ParserInitExistsRecognizer { template struct ExistsIfInitIsDefinedMarker{}; struct InitIsMissingType { char dummy1; }; struct InitExistsType { char dummy1; char dummy2; }; // exists always template static InitIsMissingType is_here(...); // exist only if ExistsIfInitIsDefinedMarker is defined template static InitExistsType is_here(ExistsIfInitIsDefinedMarker*); enum { InitExists = (sizeof(is_here(NULL)) == sizeof(InitExistsType)) }; }; template struct ParserDestroyExistsRecognizer { template struct ExistsIfDestroyIsDefinedMarker{}; struct DestroyIsMissingType { char dummy1; }; struct DestroyExistsType { char dummy1; char dummy2; }; // exists always template static DestroyIsMissingType is_here(...); // exist only if ExistsIfDestroyIsDefinedMarker is defined template static DestroyExistsType is_here(ExistsIfDestroyIsDefinedMarker*); enum { DestroyExists = (sizeof(is_here(NULL)) == sizeof(DestroyExistsType)) }; }; // The folloing templates are used to call the Init and Destroy methods if they exist. // Generic case of the ParserInitCaller, gets used if the Init method is missing template::InitExists> struct ParserInitCaller { static void CallInit(T *t) { // nothing to do } }; // True case of the ParserInitCaller, gets used if the Init method exists template struct ParserInitCaller { static void CallInit(T *t) { t->Init(); } }; // Generic case of the ParserDestroyCaller, gets used if the Destroy method is missing template::DestroyExists> struct ParserDestroyCaller { static void CallDestroy(T *t) { // nothing to do } }; // True case of the ParserDestroyCaller, gets used if the Destroy method exists template struct ParserDestroyCaller { static void CallDestroy(T *t) { t->Destroy(); } }; void Parser::Parse() { t = NULL; la = dummyToken = new Token(); la->val = coco_string_create(L"Dummy Token"); Get(); Xreate(); Expect(0); } Parser::Parser(Scanner *scanner) { - maxT = 27; + maxT = 34; ParserInitCaller::CallInit(this); dummyToken = NULL; t = la = NULL; minErrDist = 2; errDist = minErrDist; this->scanner = scanner; errors = new Errors(); } bool Parser::StartOf(int s) { const bool T = true; const bool x = false; - static bool set[3][29] = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x} + static bool set[4][36] = { + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, + {x,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x} }; return set[s][la->kind]; } Parser::~Parser() { ParserDestroyCaller::CallDestroy(this); delete errors; delete dummyToken; } Errors::Errors() { count = 0; } void Errors::SynErr(int line, int col, int n) { wchar_t* s; switch (n) { case 0: s = coco_string_create(L"EOF expected"); break; case 1: s = coco_string_create(L"ident expected"); break; case 2: s = coco_string_create(L"number expected"); break; case 3: s = coco_string_create(L"string expected"); break; - case 4: s = coco_string_create(L"\"=\" expected"); break; - case 5: s = coco_string_create(L"\"function\" expected"); break; - case 6: s = coco_string_create(L"\":\" expected"); break; - case 7: s = coco_string_create(L"\"(\" expected"); break; - case 8: s = coco_string_create(L"\",\" expected"); break; - case 9: s = coco_string_create(L"\")\" expected"); break; - case 10: s = coco_string_create(L"\"{\" expected"); break; - case 11: s = coco_string_create(L"\";\" expected"); break; - case 12: s = coco_string_create(L"\"}\" expected"); break; - case 13: s = coco_string_create(L"\"string\" expected"); break; - case 14: s = coco_string_create(L"\"int\" expected"); break; - case 15: s = coco_string_create(L"\"num\" expected"); break; - case 16: s = coco_string_create(L"\"float\" expected"); break; - case 17: s = coco_string_create(L"\"bool\" expected"); break; - case 18: s = coco_string_create(L"\"[\" expected"); break; - case 19: s = coco_string_create(L"\"]\" expected"); break; - case 20: s = coco_string_create(L"\"-\" expected"); break; - case 21: s = coco_string_create(L"\"+\" expected"); break; - case 22: s = coco_string_create(L"\"*\" expected"); break; - case 23: s = coco_string_create(L"\"/\" expected"); break; - case 24: s = coco_string_create(L"\"==\" expected"); break; - case 25: s = coco_string_create(L"\"<\" expected"); break; - case 26: s = coco_string_create(L"\">\" expected"); break; - case 27: s = coco_string_create(L"??? expected"); break; - case 28: s = coco_string_create(L"invalid FDecl"); break; - case 29: s = coco_string_create(L"invalid Type"); break; - case 30: s = coco_string_create(L"invalid VDecl"); break; - case 31: s = coco_string_create(L"invalid TypeTerm"); break; - case 32: s = coco_string_create(L"invalid ListLiteral"); break; - case 33: s = coco_string_create(L"invalid RelOp"); break; - case 34: s = coco_string_create(L"invalid AddOp"); break; - case 35: s = coco_string_create(L"invalid Factor"); break; - case 36: s = coco_string_create(L"invalid MulOp"); break; + case 4: s = coco_string_create(L"lparen expected"); break; + case 5: s = coco_string_create(L"rparen expected"); break; + case 6: s = coco_string_create(L"\"=\" expected"); break; + case 7: s = coco_string_create(L"\"function\" expected"); break; + case 8: s = coco_string_create(L"\":\" expected"); break; + case 9: s = coco_string_create(L"\",\" expected"); break; + case 10: s = coco_string_create(L"\"->\" expected"); break; + case 11: s = coco_string_create(L"\"{\" expected"); break; + case 12: s = coco_string_create(L"\";\" expected"); break; + case 13: s = coco_string_create(L"\"}\" expected"); break; + case 14: s = coco_string_create(L"\"string\" expected"); break; + case 15: s = coco_string_create(L"\"int\" expected"); break; + case 16: s = coco_string_create(L"\"num\" expected"); break; + case 17: s = coco_string_create(L"\"float\" expected"); break; + case 18: s = coco_string_create(L"\"bool\" expected"); break; + case 19: s = coco_string_create(L"\"[\" expected"); break; + case 20: s = coco_string_create(L"\"]\" expected"); break; + case 21: s = coco_string_create(L"\"-\" expected"); break; + case 22: s = coco_string_create(L"\"assert\" expected"); break; + case 23: s = coco_string_create(L"\"require\" expected"); break; + case 24: s = coco_string_create(L"\"rule\" expected"); break; + case 25: s = coco_string_create(L"\"case\" expected"); break; + case 26: s = coco_string_create(L"\"variable\" expected"); break; + case 27: s = coco_string_create(L"\"warning\" expected"); break; + case 28: s = coco_string_create(L"\"message\" expected"); break; + case 29: s = coco_string_create(L"\">\" expected"); break; + case 30: s = coco_string_create(L"\"+\" expected"); break; + case 31: s = coco_string_create(L"\"*\" expected"); break; + case 32: s = coco_string_create(L"\"/\" expected"); break; + case 33: s = coco_string_create(L"\"<\" expected"); break; + case 34: s = coco_string_create(L"??? expected"); break; + case 35: s = coco_string_create(L"invalid FDecl"); break; + case 36: s = coco_string_create(L"invalid Type"); break; + case 37: s = coco_string_create(L"invalid VDecl"); break; + case 38: s = coco_string_create(L"invalid TypeTerm"); break; + case 39: s = coco_string_create(L"invalid TagMod"); break; + case 40: s = coco_string_create(L"invalid Domain"); break; + case 41: s = coco_string_create(L"invalid MetaExpr2"); break; + case 42: s = coco_string_create(L"invalid RelOp"); break; + case 43: s = coco_string_create(L"invalid AddOp"); break; + case 44: s = coco_string_create(L"invalid Factor"); break; + case 45: s = coco_string_create(L"invalid MulOp"); break; default: { wchar_t format[20]; coco_swprintf(format, 20, L"error %d", n); s = coco_string_create(format); } break; } wprintf(L"-- line %d col %d: %ls\n", line, col, s); coco_string_delete(s); count++; } void Errors::Error(int line, int col, const wchar_t *s) { wprintf(L"-- line %d col %d: %ls\n", line, col, s); count++; } void Errors::Warning(int line, int col, const wchar_t *s) { wprintf(L"-- line %d col %d: %ls\n", line, col, s); } void Errors::Warning(const wchar_t *s) { wprintf(L"%ls\n", s); } void Errors::Exception(const wchar_t* s) { wprintf(L"%ls", s); exit(1); } diff --git a/coco/Parser.h b/coco/Parser.h index b0cb7da..8501f6d 100644 --- a/coco/Parser.h +++ b/coco/Parser.h @@ -1,112 +1,141 @@ /*---------------------------------------------------------------------- Compiler Generator Coco/R, Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz extended by M. Loeberbauer & A. Woess, Univ. of Linz ported to C++ by Csaba Balazs, University of Szeged with improvements by Pat Terry, Rhodes University 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As an exception, it is allowed to write an extension of Coco/R that is used as a plugin in non-free software. If not otherwise stated, any source code generated by Coco/R (other than Coco/R itself) does not fall under the GNU General Public License. -----------------------------------------------------------------------*/ #if !defined(COCO_PARSER_H__) #define COCO_PARSER_H__ #include "ast.h" #include #include "Scanner.h" class Errors { public: int count; // number of errors detected Errors(); void SynErr(int line, int col, int n); void Error(int line, int col, const wchar_t *s); void Warning(int line, int col, const wchar_t *s); void Warning(const wchar_t *s); void Exception(const wchar_t *s); }; // Errors class Parser { private: enum { _EOF=0, _ident=1, _number=2, - _string=3 + _string=3, + _lparen=4, + _rparen=5 }; int maxT; Token *dummyToken; int errDist; int minErrDist; void SynErr(int n); void Get(); void Expect(int n); bool StartOf(int s); void ExpectWeak(int n, int follow); bool WeakSeparator(int n, int syFol, int repFol); public: Scanner *scanner; Errors *errors; Token *t; // last recognized token Token *la; // lookahead token AST root; // current program unit (procedure or main program) +bool checkParametersList() +{ + scanner.ResetPeek(); + Token x = scanner->Peek(); + return la->kind == _ident && x->kind == _lparen; +} + +bool checkInfix() +{ + scanner.ResetPeek(); + Token x = scanner->Peek(); + return la->kind == _ident && x->kind == _ident; +} + +bool check + Parser(Scanner *scanner); ~Parser(); void SemErr(const wchar_t* msg); void Xreate(); void FDecl(); + void RuleDecl(); void Ident(std::wstring& name); void Type(TypeAnnotation& typ); + void FnTag(Function& f); void VDecl(Function& f); void Expr(Expression& e); void TypeTerm(TypeAtom& typ); void ListLiteral(Expression& e); + void TagMod(TagModifier& mod); + void Domain(DomainAnnotation& dom); + void RGuard(RuleGuards& guards); + void RBody(RuleBody& body); + void MetaExpr(MetaExpression& e); + void MetaExpr2(MetaExpression& e); + void MetaOp(Operator& op); + void MetaParams(MetaParameters& params); void SimExpr(Expression& e); void RelOp(Operator& op); void Term(Expression& e); void AddOp(Operator& op); void Factor(Expression& e); void MulOp(Operator& op); + void CalleeParams(Expression& e); void Parse(); }; // end Parser #endif diff --git a/coco/Scanner.cpp b/coco/Scanner.cpp index c16b3f3..f19591f 100644 --- a/coco/Scanner.cpp +++ b/coco/Scanner.cpp @@ -1,756 +1,764 @@ /*---------------------------------------------------------------------- Compiler Generator Coco/R, Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz extended by M. Loeberbauer & A. Woess, Univ. of Linz ported to C++ by Csaba Balazs, University of Szeged with improvements by Pat Terry, Rhodes University 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As an exception, it is allowed to write an extension of Coco/R that is used as a plugin in non-free software. If not otherwise stated, any source code generated by Coco/R (other than Coco/R itself) does not fall under the GNU General Public License. -----------------------------------------------------------------------*/ #include #include #include "Scanner.h" + + + // string handling, wide character wchar_t* coco_string_create(const wchar_t* value) { return coco_string_create(value, 0); } wchar_t* coco_string_create(const wchar_t *value, int startIndex) { int valueLen = 0; int len = 0; if (value) { valueLen = wcslen(value); len = valueLen - startIndex; } return coco_string_create(value, startIndex, len); } wchar_t* coco_string_create(const wchar_t *value, int startIndex, int length) { int len = 0; wchar_t* data; if (value) { len = length; } data = new wchar_t[len + 1]; wcsncpy(data, &(value[startIndex]), len); data[len] = 0; return data; } wchar_t* coco_string_create_upper(const wchar_t* data) { if (!data) { return NULL; } int dataLen = 0; if (data) { dataLen = wcslen(data); } wchar_t *newData = new wchar_t[dataLen + 1]; for (int i = 0; i <= dataLen; i++) { if ((L'a' <= data[i]) && (data[i] <= L'z')) { newData[i] = data[i] + (L'A' - L'a'); } else { newData[i] = data[i]; } } newData[dataLen] = L'\0'; return newData; } wchar_t* coco_string_create_lower(const wchar_t* data) { if (!data) { return NULL; } int dataLen = wcslen(data); return coco_string_create_lower(data, 0, dataLen); } wchar_t* coco_string_create_lower(const wchar_t* data, int startIndex, int dataLen) { if (!data) { return NULL; } wchar_t* newData = new wchar_t[dataLen + 1]; for (int i = 0; i <= dataLen; i++) { wchar_t ch = data[startIndex + i]; if ((L'A' <= ch) && (ch <= L'Z')) { newData[i] = ch - (L'A' - L'a'); } else { newData[i] = ch; } } newData[dataLen] = L'\0'; return newData; } wchar_t* coco_string_create_append(const wchar_t* data1, const wchar_t* data2) { wchar_t* data; int data1Len = 0; int data2Len = 0; if (data1) { data1Len = wcslen(data1); } if (data2) {data2Len = wcslen(data2); } data = new wchar_t[data1Len + data2Len + 1]; if (data1) { wcscpy(data, data1); } if (data2) { wcscpy(data + data1Len, data2); } data[data1Len + data2Len] = 0; return data; } wchar_t* coco_string_create_append(const wchar_t *target, const wchar_t appendix) { int targetLen = coco_string_length(target); wchar_t* data = new wchar_t[targetLen + 2]; wcsncpy(data, target, targetLen); data[targetLen] = appendix; data[targetLen + 1] = 0; return data; } void coco_string_delete(wchar_t* &data) { delete [] data; data = NULL; } int coco_string_length(const wchar_t* data) { if (data) { return wcslen(data); } return 0; } bool coco_string_endswith(const wchar_t* data, const wchar_t *end) { int dataLen = wcslen(data); int endLen = wcslen(end); return (endLen <= dataLen) && (wcscmp(data + dataLen - endLen, end) == 0); } int coco_string_indexof(const wchar_t* data, const wchar_t value) { const wchar_t* chr = wcschr(data, value); if (chr) { return (chr-data); } return -1; } int coco_string_lastindexof(const wchar_t* data, const wchar_t value) { const wchar_t* chr = wcsrchr(data, value); if (chr) { return (chr-data); } return -1; } void coco_string_merge(wchar_t* &target, const wchar_t* appendix) { if (!appendix) { return; } wchar_t* data = coco_string_create_append(target, appendix); delete [] target; target = data; } bool coco_string_equal(const wchar_t* data1, const wchar_t* data2) { return wcscmp( data1, data2 ) == 0; } int coco_string_compareto(const wchar_t* data1, const wchar_t* data2) { return wcscmp(data1, data2); } int coco_string_hash(const wchar_t *data) { int h = 0; if (!data) { return 0; } while (*data != 0) { h = (h * 7) ^ *data; ++data; } if (h < 0) { h = -h; } return h; } // string handling, ascii character wchar_t* coco_string_create(const char* value) { int len = 0; if (value) { len = strlen(value); } wchar_t* data = new wchar_t[len + 1]; for (int i = 0; i < len; ++i) { data[i] = (wchar_t) value[i]; } data[len] = 0; return data; } char* coco_string_create_char(const wchar_t *value) { int len = coco_string_length(value); char *res = new char[len + 1]; for (int i = 0; i < len; ++i) { res[i] = (char) value[i]; } res[len] = 0; return res; } void coco_string_delete(char* &data) { delete [] data; data = NULL; } - - Token::Token() { kind = 0; pos = 0; col = 0; line = 0; val = NULL; next = NULL; } Token::~Token() { coco_string_delete(val); } Buffer::Buffer(FILE* s, bool isUserStream) { // ensure binary read on windows #if _MSC_VER >= 1300 _setmode(_fileno(s), _O_BINARY); #endif stream = s; this->isUserStream = isUserStream; if (CanSeek()) { fseek(s, 0, SEEK_END); fileLen = ftell(s); fseek(s, 0, SEEK_SET); - bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH; + bufLen = (fileLen < COCO_MAX_BUFFER_LENGTH) ? fileLen : COCO_MAX_BUFFER_LENGTH; bufStart = INT_MAX; // nothing in the buffer so far } else { fileLen = bufLen = bufStart = 0; } - bufCapacity = (bufLen>0) ? bufLen : MIN_BUFFER_LENGTH; + bufCapacity = (bufLen>0) ? bufLen : COCO_MIN_BUFFER_LENGTH; buf = new unsigned char[bufCapacity]; if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start) else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid if (bufLen == fileLen && CanSeek()) Close(); } Buffer::Buffer(Buffer *b) { buf = b->buf; bufCapacity = b->bufCapacity; b->buf = NULL; bufStart = b->bufStart; bufLen = b->bufLen; fileLen = b->fileLen; bufPos = b->bufPos; stream = b->stream; b->stream = NULL; isUserStream = b->isUserStream; } Buffer::Buffer(const unsigned char* buf, int len) { this->buf = new unsigned char[len]; memcpy(this->buf, buf, len*sizeof(unsigned char)); bufStart = 0; bufCapacity = bufLen = len; fileLen = len; bufPos = 0; stream = NULL; } Buffer::~Buffer() { Close(); if (buf != NULL) { delete [] buf; buf = NULL; } } void Buffer::Close() { if (!isUserStream && stream != NULL) { fclose(stream); stream = NULL; } } int Buffer::Read() { if (bufPos < bufLen) { return buf[bufPos++]; } else if (GetPos() < fileLen) { SetPos(GetPos()); // shift buffer start to Pos return buf[bufPos++]; } else if ((stream != NULL) && !CanSeek() && (ReadNextStreamChunk() > 0)) { return buf[bufPos++]; } else { return EoF; } } int Buffer::Peek() { int curPos = GetPos(); int ch = Read(); SetPos(curPos); return ch; } // beg .. begin, zero-based, inclusive, in byte // end .. end, zero-based, exclusive, in byte wchar_t* Buffer::GetString(int beg, int end) { int len = 0; wchar_t *buf = new wchar_t[end - beg]; int oldPos = GetPos(); SetPos(beg); while (GetPos() < end) buf[len++] = (wchar_t) Read(); SetPos(oldPos); wchar_t *res = coco_string_create(buf, 0, len); coco_string_delete(buf); return res; } int Buffer::GetPos() { return bufPos + bufStart; } void Buffer::SetPos(int value) { if ((value >= fileLen) && (stream != NULL) && !CanSeek()) { // Wanted position is after buffer and the stream // is not seek-able e.g. network or console, // thus we have to read the stream manually till // the wanted position is in sight. while ((value >= fileLen) && (ReadNextStreamChunk() > 0)); } if ((value < 0) || (value > fileLen)) { wprintf(L"--- buffer out of bounds access, position: %d\n", value); exit(1); } if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer bufPos = value - bufStart; } else if (stream != NULL) { // must be swapped in fseek(stream, value, SEEK_SET); bufLen = fread(buf, sizeof(unsigned char), bufCapacity, stream); bufStart = value; bufPos = 0; } else { bufPos = fileLen - bufStart; // make Pos return fileLen } } // Read the next chunk of bytes from the stream, increases the buffer // if needed and updates the fields fileLen and bufLen. // Returns the number of bytes read. int Buffer::ReadNextStreamChunk() { int free = bufCapacity - bufLen; if (free == 0) { // in the case of a growing input stream // we can neither seek in the stream, nor can we // foresee the maximum length, thus we must adapt // the buffer size on demand. bufCapacity = bufLen * 2; unsigned char *newBuf = new unsigned char[bufCapacity]; memcpy(newBuf, buf, bufLen*sizeof(unsigned char)); delete [] buf; buf = newBuf; free = bufLen; } int read = fread(buf + bufLen, sizeof(unsigned char), free, stream); if (read > 0) { fileLen = bufLen = (bufLen + read); return read; } // end of stream reached return 0; } bool Buffer::CanSeek() { return (stream != NULL) && (ftell(stream) != -1); } int UTF8Buffer::Read() { int ch; do { ch = Buffer::Read(); // until we find a utf8 start (0xxxxxxx or 11xxxxxx) } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EoF)); if (ch < 128 || ch == EoF) { // nothing to do, first 127 chars are the same in ascii and utf8 // 0xxxxxxx or end of file character } else if ((ch & 0xF0) == 0xF0) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx int c1 = ch & 0x07; ch = Buffer::Read(); int c2 = ch & 0x3F; ch = Buffer::Read(); int c3 = ch & 0x3F; ch = Buffer::Read(); int c4 = ch & 0x3F; ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; } else if ((ch & 0xE0) == 0xE0) { // 1110xxxx 10xxxxxx 10xxxxxx int c1 = ch & 0x0F; ch = Buffer::Read(); int c2 = ch & 0x3F; ch = Buffer::Read(); int c3 = ch & 0x3F; ch = (((c1 << 6) | c2) << 6) | c3; } else if ((ch & 0xC0) == 0xC0) { // 110xxxxx 10xxxxxx int c1 = ch & 0x1F; ch = Buffer::Read(); int c2 = ch & 0x3F; ch = (c1 << 6) | c2; } return ch; } Scanner::Scanner(const unsigned char* buf, int len) { buffer = new Buffer(buf, len); Init(); } Scanner::Scanner(const wchar_t* fileName) { FILE* stream; char *chFileName = coco_string_create_char(fileName); if ((stream = fopen(chFileName, "rb")) == NULL) { wprintf(L"--- Cannot open file %ls\n", fileName); exit(1); } coco_string_delete(chFileName); buffer = new Buffer(stream, false); Init(); } Scanner::Scanner(FILE* s) { buffer = new Buffer(s, true); Init(); } Scanner::~Scanner() { char* cur = (char*) firstHeap; while(cur != NULL) { - cur = *(char**) (cur + HEAP_BLOCK_SIZE); + cur = *(char**) (cur + COCO_HEAP_BLOCK_SIZE); free(firstHeap); firstHeap = cur; } delete [] tval; delete buffer; } void Scanner::Init() { EOL = '\n'; eofSym = 0; - maxT = 27; - noSym = 27; + maxT = 34; + noSym = 34; int i; for (i = 65; i <= 90; ++i) start.set(i, 1); for (i = 97; i <= 122; ++i) start.set(i, 1); for (i = 48; i <= 57; ++i) start.set(i, 2); start.set(34, 3); - start.set(61, 21); - start.set(58, 5); - start.set(40, 6); - start.set(44, 7); - start.set(41, 8); - start.set(123, 9); - start.set(59, 10); - start.set(125, 11); - start.set(91, 12); - start.set(93, 13); - start.set(45, 14); - start.set(43, 15); - start.set(42, 16); - start.set(47, 17); - start.set(60, 19); - start.set(62, 20); + start.set(40, 5); + start.set(41, 6); + start.set(61, 7); + start.set(58, 8); + start.set(44, 9); + start.set(45, 21); + start.set(123, 11); + start.set(59, 12); + start.set(125, 13); + start.set(91, 14); + start.set(93, 15); + start.set(62, 16); + start.set(43, 17); + start.set(42, 18); + start.set(47, 19); + start.set(60, 20); start.set(Buffer::EoF, -1); - keywords.set(L"function", 5); - keywords.set(L"string", 13); - keywords.set(L"int", 14); - keywords.set(L"num", 15); - keywords.set(L"float", 16); - keywords.set(L"bool", 17); + keywords.set(L"function", 7); + keywords.set(L"string", 14); + keywords.set(L"int", 15); + keywords.set(L"num", 16); + keywords.set(L"float", 17); + keywords.set(L"bool", 18); + keywords.set(L"assert", 22); + keywords.set(L"require", 23); + keywords.set(L"rule", 24); + keywords.set(L"case", 25); + keywords.set(L"variable", 26); + keywords.set(L"warning", 27); + keywords.set(L"message", 28); tvalLength = 128; tval = new wchar_t[tvalLength]; // text of current token - // HEAP_BLOCK_SIZE byte heap + pointer to next heap block - heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); + // COCO_HEAP_BLOCK_SIZE byte heap + pointer to next heap block + heap = malloc(COCO_HEAP_BLOCK_SIZE + sizeof(void*)); firstHeap = heap; - heapEnd = (void**) (((char*) heap) + HEAP_BLOCK_SIZE); + heapEnd = (void**) (((char*) heap) + COCO_HEAP_BLOCK_SIZE); *heapEnd = 0; heapTop = heap; - if (sizeof(Token) > HEAP_BLOCK_SIZE) { - wprintf(L"--- Too small HEAP_BLOCK_SIZE\n"); + if (sizeof(Token) > COCO_HEAP_BLOCK_SIZE) { + wprintf(L"--- Too small COCO_HEAP_BLOCK_SIZE\n"); exit(1); } pos = -1; line = 1; col = 0; charPos = -1; oldEols = 0; NextCh(); if (ch == 0xEF) { // check optional byte order mark for UTF-8 NextCh(); int ch1 = ch; NextCh(); int ch2 = ch; if (ch1 != 0xBB || ch2 != 0xBF) { wprintf(L"Illegal byte order mark at start of file"); exit(1); } Buffer *oldBuf = buffer; buffer = new UTF8Buffer(buffer); col = 0; charPos = -1; delete oldBuf; oldBuf = NULL; NextCh(); } pt = tokens = CreateToken(); // first token is a dummy } void Scanner::NextCh() { if (oldEols > 0) { ch = EOL; oldEols--; } else { pos = buffer->GetPos(); // buffer reads unicode chars, if UTF8 has been detected ch = buffer->Read(); col++; charPos++; // replace isolated '\r' by '\n' in order to make // eol handling uniform across Windows, Unix and Mac if (ch == L'\r' && buffer->Peek() != L'\n') ch = EOL; if (ch == EOL) { line++; col = 0; } } } void Scanner::AddCh() { if (tlen >= tvalLength) { tvalLength *= 2; wchar_t *newBuf = new wchar_t[tvalLength]; memcpy(newBuf, tval, tlen*sizeof(wchar_t)); delete [] tval; tval = newBuf; } if (ch != Buffer::EoF) { tval[tlen++] = ch; NextCh(); } } bool Scanner::Comment0() { int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos; NextCh(); if (ch == L'/') { NextCh(); for(;;) { if (ch == 10) { level--; if (level == 0) { oldEols = line - line0; NextCh(); return true; } NextCh(); } else if (ch == buffer->EoF) return false; else NextCh(); } } else { buffer->SetPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0; } return false; } bool Scanner::Comment1() { int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos; NextCh(); if (ch == L'*') { NextCh(); for(;;) { if (ch == L'*') { NextCh(); if (ch == L'/') { level--; if (level == 0) { oldEols = line - line0; NextCh(); return true; } NextCh(); } } else if (ch == L'/') { NextCh(); if (ch == L'*') { level++; NextCh(); } } else if (ch == buffer->EoF) return false; else NextCh(); } } else { buffer->SetPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0; } return false; } void Scanner::CreateHeapBlock() { void* newHeap; char* cur = (char*) firstHeap; - while(((char*) tokens < cur) || ((char*) tokens > (cur + HEAP_BLOCK_SIZE))) { - cur = *((char**) (cur + HEAP_BLOCK_SIZE)); + while(((char*) tokens < cur) || ((char*) tokens > (cur + COCO_HEAP_BLOCK_SIZE))) { + cur = *((char**) (cur + COCO_HEAP_BLOCK_SIZE)); free(firstHeap); firstHeap = cur; } - // HEAP_BLOCK_SIZE byte heap + pointer to next heap block - newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); + // COCO_HEAP_BLOCK_SIZE byte heap + pointer to next heap block + newHeap = malloc(COCO_HEAP_BLOCK_SIZE + sizeof(void*)); *heapEnd = newHeap; - heapEnd = (void**) (((char*) newHeap) + HEAP_BLOCK_SIZE); + heapEnd = (void**) (((char*) newHeap) + COCO_HEAP_BLOCK_SIZE); *heapEnd = 0; heap = newHeap; heapTop = heap; } Token* Scanner::CreateToken() { Token *t; if (((char*) heapTop + (int) sizeof(Token)) >= (char*) heapEnd) { CreateHeapBlock(); } t = (Token*) heapTop; heapTop = (void*) ((char*) heapTop + sizeof(Token)); t->val = NULL; t->next = NULL; return t; } void Scanner::AppendVal(Token *t) { int reqMem = (tlen + 1) * sizeof(wchar_t); if (((char*) heapTop + reqMem) >= (char*) heapEnd) { - if (reqMem > HEAP_BLOCK_SIZE) { + if (reqMem > COCO_HEAP_BLOCK_SIZE) { wprintf(L"--- Too long token value\n"); exit(1); } CreateHeapBlock(); } t->val = (wchar_t*) heapTop; heapTop = (void*) ((char*) heapTop + reqMem); wcsncpy(t->val, tval, tlen); t->val[tlen] = L'\0'; } Token* Scanner::NextToken() { while (ch == ' ' || (ch >= 9 && ch <= 10) || ch == 13 ) NextCh(); if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken(); int recKind = noSym; int recEnd = pos; t = CreateToken(); t->pos = pos; t->col = col; t->line = line; t->charPos = charPos; int state = start.state(ch); tlen = 0; AddCh(); switch (state) { case -1: { t->kind = eofSym; break; } // NextCh already done case 0: { case_0: if (recKind != noSym) { tlen = recEnd - t->pos; SetScannerBehindT(); } t->kind = recKind; break; } // NextCh already done case 1: case_1: recEnd = pos; recKind = 1; if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;} else {t->kind = 1; wchar_t *literal = coco_string_create(tval, 0, tlen); t->kind = keywords.get(literal, t->kind); coco_string_delete(literal); break;} case 2: case_2: recEnd = pos; recKind = 2; if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_2;} else {t->kind = 2; break;} case 3: case_3: if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_3;} else if (ch == L'"') {AddCh(); goto case_4;} else {goto case_0;} case 4: case_4: {t->kind = 3; break;} case 5: - {t->kind = 6; break;} + {t->kind = 4; break;} case 6: - {t->kind = 7; break;} + {t->kind = 5; break;} case 7: - {t->kind = 8; break;} + {t->kind = 6; break;} case 8: - {t->kind = 9; break;} + {t->kind = 8; break;} case 9: - {t->kind = 10; break;} + {t->kind = 9; break;} case 10: - {t->kind = 11; break;} + case_10: + {t->kind = 10; break;} case 11: - {t->kind = 12; break;} + {t->kind = 11; break;} case 12: - {t->kind = 18; break;} + {t->kind = 12; break;} case 13: - {t->kind = 19; break;} + {t->kind = 13; break;} case 14: - {t->kind = 20; break;} + {t->kind = 19; break;} case 15: - {t->kind = 21; break;} + {t->kind = 20; break;} case 16: - {t->kind = 22; break;} + {t->kind = 29; break;} case 17: - {t->kind = 23; break;} + {t->kind = 30; break;} case 18: - case_18: - {t->kind = 24; break;} + {t->kind = 31; break;} case 19: - {t->kind = 25; break;} + {t->kind = 32; break;} case 20: - {t->kind = 26; break;} + {t->kind = 33; break;} case 21: - recEnd = pos; recKind = 4; - if (ch == L'=') {AddCh(); goto case_18;} - else {t->kind = 4; break;} + recEnd = pos; recKind = 21; + if (ch == L'>') {AddCh(); goto case_10;} + else {t->kind = 21; break;} } AppendVal(t); return t; } void Scanner::SetScannerBehindT() { buffer->SetPos(t->pos); NextCh(); line = t->line; col = t->col; charPos = t->charPos; for (int i = 0; i < tlen; i++) NextCh(); } // get the next token (possibly a token already seen during peeking) Token* Scanner::Scan() { if (tokens->next == NULL) { return pt = tokens = NextToken(); } else { pt = tokens = tokens->next; return tokens; } } // peek for the next token, ignore pragmas Token* Scanner::Peek() { do { if (pt->next == NULL) { pt->next = NextToken(); } pt = pt->next; } while (pt->kind > maxT); // skip pragmas return pt; } // make sure that peeking starts at the current scan position void Scanner::ResetPeek() { pt = tokens; } diff --git a/coco/Scanner.h b/coco/Scanner.h index a7bbe0d..9defd77 100644 --- a/coco/Scanner.h +++ b/coco/Scanner.h @@ -1,289 +1,289 @@ /*---------------------------------------------------------------------- Compiler Generator Coco/R, Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz extended by M. Loeberbauer & A. Woess, Univ. of Linz ported to C++ by Csaba Balazs, University of Szeged with improvements by Pat Terry, Rhodes University 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As an exception, it is allowed to write an extension of Coco/R that is used as a plugin in non-free software. If not otherwise stated, any source code generated by Coco/R (other than Coco/R itself) does not fall under the GNU General Public License. -----------------------------------------------------------------------*/ #if !defined(COCO_SCANNER_H__) #define COCO_SCANNER_H__ #include #include #include #include #include // io.h and fcntl are used to ensure binary read from streams on windows #if _MSC_VER >= 1300 #include #include #endif #if _MSC_VER >= 1400 #define coco_swprintf swprintf_s #elif _MSC_VER >= 1300 #define coco_swprintf _snwprintf #elif defined __MINGW32__ #define coco_swprintf _snwprintf #else // assume every other compiler knows swprintf #define coco_swprintf swprintf #endif #define COCO_WCHAR_MAX 65535 -#define MIN_BUFFER_LENGTH 1024 -#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH) -#define HEAP_BLOCK_SIZE (64*1024) +#define COCO_MIN_BUFFER_LENGTH 1024 +#define COCO_MAX_BUFFER_LENGTH (64*COCO_MIN_BUFFER_LENGTH) +#define COCO_HEAP_BLOCK_SIZE (64*1024) #define COCO_CPP_NAMESPACE_SEPARATOR L':' + + // string handling, wide character wchar_t* coco_string_create(const wchar_t *value); wchar_t* coco_string_create(const wchar_t *value, int startIndex); wchar_t* coco_string_create(const wchar_t *value, int startIndex, int length); wchar_t* coco_string_create_upper(const wchar_t* data); wchar_t* coco_string_create_lower(const wchar_t* data); wchar_t* coco_string_create_lower(const wchar_t* data, int startIndex, int dataLen); wchar_t* coco_string_create_append(const wchar_t* data1, const wchar_t* data2); wchar_t* coco_string_create_append(const wchar_t* data, const wchar_t value); void coco_string_delete(wchar_t* &data); int coco_string_length(const wchar_t* data); bool coco_string_endswith(const wchar_t* data, const wchar_t *value); int coco_string_indexof(const wchar_t* data, const wchar_t value); int coco_string_lastindexof(const wchar_t* data, const wchar_t value); void coco_string_merge(wchar_t* &data, const wchar_t* value); bool coco_string_equal(const wchar_t* data1, const wchar_t* data2); int coco_string_compareto(const wchar_t* data1, const wchar_t* data2); int coco_string_hash(const wchar_t* data); // string handling, ascii character wchar_t* coco_string_create(const char *value); char* coco_string_create_char(const wchar_t *value); void coco_string_delete(char* &data); - - class Token { public: int kind; // token kind int pos; // token position in bytes in the source text (starting at 0) int charPos; // token position in characters in the source text (starting at 0) int col; // token column (starting at 1) int line; // token line (starting at 1) wchar_t* val; // token value Token *next; // ML 2005-03-11 Peek tokens are kept in linked list Token(); ~Token(); }; class Buffer { // This Buffer supports the following cases: // 1) seekable stream (file) // a) whole stream in buffer // b) part of stream in buffer // 2) non seekable stream (network, console) private: unsigned char *buf; // input buffer int bufCapacity; // capacity of buf int bufStart; // position of first byte in buffer relative to input stream int bufLen; // length of buffer int fileLen; // length of input stream (may change if the stream is no file) int bufPos; // current position in buffer FILE* stream; // input stream (seekable) bool isUserStream; // was the stream opened by the user? int ReadNextStreamChunk(); bool CanSeek(); // true if stream can be seeked otherwise false public: static const int EoF = COCO_WCHAR_MAX + 1; Buffer(FILE* s, bool isUserStream); Buffer(const unsigned char* buf, int len); Buffer(Buffer *b); virtual ~Buffer(); virtual void Close(); virtual int Read(); virtual int Peek(); virtual wchar_t* GetString(int beg, int end); virtual int GetPos(); virtual void SetPos(int value); }; class UTF8Buffer : public Buffer { public: UTF8Buffer(Buffer *b) : Buffer(b) {}; virtual int Read(); }; //----------------------------------------------------------------------------------- // StartStates -- maps characters to start states of tokens //----------------------------------------------------------------------------------- class StartStates { private: class Elem { public: int key, val; Elem *next; Elem(int key, int val) { this->key = key; this->val = val; next = NULL; } }; Elem **tab; public: StartStates() { tab = new Elem*[128]; memset(tab, 0, 128 * sizeof(Elem*)); } virtual ~StartStates() { for (int i = 0; i < 128; ++i) { Elem *e = tab[i]; while (e != NULL) { Elem *next = e->next; delete e; e = next; } } delete [] tab; } void set(int key, int val) { Elem *e = new Elem(key, val); int k = ((unsigned int) key) % 128; e->next = tab[k]; tab[k] = e; } int state(int key) { Elem *e = tab[((unsigned int) key) % 128]; while (e != NULL && e->key != key) e = e->next; return e == NULL ? 0 : e->val; } }; //------------------------------------------------------------------------------------------- // KeywordMap -- maps strings to integers (identifiers to keyword kinds) //------------------------------------------------------------------------------------------- class KeywordMap { private: class Elem { public: wchar_t *key; int val; Elem *next; Elem(const wchar_t *key, int val) { this->key = coco_string_create(key); this->val = val; next = NULL; } virtual ~Elem() { coco_string_delete(key); } }; Elem **tab; public: KeywordMap() { tab = new Elem*[128]; memset(tab, 0, 128 * sizeof(Elem*)); } virtual ~KeywordMap() { for (int i = 0; i < 128; ++i) { Elem *e = tab[i]; while (e != NULL) { Elem *next = e->next; delete e; e = next; } } delete [] tab; } void set(const wchar_t *key, int val) { Elem *e = new Elem(key, val); int k = coco_string_hash(key) % 128; e->next = tab[k]; tab[k] = e; } int get(const wchar_t *key, int defaultVal) { Elem *e = tab[coco_string_hash(key) % 128]; while (e != NULL && !coco_string_equal(e->key, key)) e = e->next; return e == NULL ? defaultVal : e->val; } }; class Scanner { private: void *firstHeap; void *heap; void *heapTop; void **heapEnd; unsigned char EOL; int eofSym; int noSym; int maxT; int charSetSize; StartStates start; KeywordMap keywords; Token *t; // current token wchar_t *tval; // text of current token int tvalLength; // length of text of current token int tlen; // length of current token Token *tokens; // list of tokens already peeked (first token is a dummy) Token *pt; // current peek token int ch; // current input character int pos; // byte position of current character int charPos; // position by unicode characters starting with 0 int line; // line number of current character int col; // column number of current character int oldEols; // EOLs that appeared in a comment; void CreateHeapBlock(); Token* CreateToken(); void AppendVal(Token *t); void SetScannerBehindT(); void Init(); void NextCh(); void AddCh(); bool Comment0(); bool Comment1(); Token* NextToken(); public: Buffer *buffer; // scanner buffer Scanner(const unsigned char* buf, int len); Scanner(const wchar_t* fileName); Scanner(FILE* s); ~Scanner(); Token* Scan(); Token* Peek(); void ResetPeek(); }; // end Scanner #endif diff --git a/coco/gen-xreate b/coco/gen-xreate new file mode 100755 index 0000000..132dff9 --- /dev/null +++ b/coco/gen-xreate @@ -0,0 +1 @@ +cococpp -frames /usr/share/coco-cpp/ ./xreate.ATG diff --git a/coco/xreate.ATG b/coco/xreate.ATG index ff3cf75..ed7e702 100644 --- a/coco/xreate.ATG +++ b/coco/xreate.ATG @@ -1,118 +1,198 @@ #include "ast.h" #include COMPILER Xreate AST root; // current program unit (procedure or main program) +bool checkParametersList() +{ + scanner.ResetPeek(); + Token x = scanner->Peek(); + return la->kind == _ident && x->kind == _lparen; +} + +bool checkInfix() +{ + scanner.ResetPeek(); + Token x = scanner->Peek(); + return la->kind == _ident && x->kind == _ident; +} + +bool check + CHARACTERS letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". digit = "0123456789". cr = '\r'. lf = '\n'. tab = '\t'. TOKENS ident = letter {letter | digit}. number = digit {digit}. string = '"' {letter} '"'. + lparen = '('. + rparen = ')'. COMMENTS FROM "/*" TO "*/" NESTED COMMENTS FROM "//" TO lf IGNORE cr + lf + tab PRODUCTIONS - -Xreate = {FDecl}. +Xreate = { ( FDecl | RuleDecl ) }. Ident = ident (. name = t->val; .). FDecl<> = (. std::wstring fname; Expression fbody; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut; .) Ident '=' "function" ':' (. Function f = Function(fname); .) ( Type (. f.setReturnType(typOut); .) | '('Ident ':' Type (. f.addArg(varname, typIn); .) {',' Ident ':' Type (. f.addArg(varname, typIn);.) -} ')' ) - -'{' {VDecl ';' } -Expr '}' (. f.setBody(fbody); .) . +} ')' "->" Type (. f.setReturnType(typOut); .) +{',' FnTag } +) '{' {VDecl ';' } +Expr ';' '}' (. f.setBody(fbody); root.add(f); .) . TypeTerm = ("string" | "int" | "num" | "float" | "bool") (. typ = Atom(t->val); .) . Type = (. TypeAnnotation typ2; TypeAtom typ3; .) ('[' Type ']' (. typ = TypeAnnotation(TypeOperator::LIST, typ2); .) | TypeTerm (. typ = TypeAnnotation(typ3); .) ) . VDecl = (. std::wstring vname; Expression e; TypeAnnotation typ; .) Ident '=' (Expr ':' Type (. f.addDeclaration(vname, typ, e); .) |ListLiteral ':' Type (. f.addListDeclaration(vname, typ, e); .) -) ';'. +). + /*============================ METAPROGRAMMING ===============================*/ + +FnTag = (.std::wstring tag; TagModifier mod = TagModifier::NONE; .) +Ident +['-' TagMod] (. f.addTag(tag, mod); .). + +TagMod = +( "assert" (. mod = TagModifier::ASSERT; .) + | "require" (. mod = TagModifier::REQUIRE; .) +). + +RuleDecl<> = +"rule" ':' (. RuleArguments args; RuleGuards guards; RuleBody body; DomainAnnotation typ; .) +'(' Ident ':' Domain (. args.add(arg, typ); .) +{',' Ident ':'Domain (. args.add(arg, typ); .) +} ')' +["case" RGuard {',' RGuard}] + (. .) +'{' RBody '}' . + +Domain = +( + "function" (. dom = DomainAnnotation::FUNCTION; .) + | "variable" (. dom = DomainAnnotation::VARIABLE; .) +). + +RGuard= (. MetaExpression e; .) +MetaExpr (. guards.add(e); .). + +MetaExpr= +MetaExpr2 +[MetaOp MetaExpr2 (. MetaParameters params; + params.add(e); + params.add(e2); + e = MetaExpression(op, params); .) +]. + +MetaExpr2= (. std::wstring i1, i2, infix; MetaParameters params; .) +( IF(checkParametersList()) Ident '(' [ MetaParams ] ')' + (. e = MetaExpression(Operator::CALL, i1, params); .) +| IF(checkInfix()) Ident Ident Ident + (. params.add(Expression(Atom(i1->val))); + params.add(Expression(Atom(i2->val))); + e = MetaExpression(Operator::CALL, Atom(infix->val), params); .) +| Ident (. e = MetaExpression(Atom(i1->val)); .) +| '(' MetaExpr ')' +). + +MetaParams = (. MetaExpr e; .) +MetaExpr (. params.add(e); .) +{',' MetaExpr (. params.add(e).) +}. + +RBody = (. MetaExpr e; .) + "warning" MetaExpr ["message" string] . + +MetaOp< Operator& op> = + '-' '>' (. op = OPERATOR::IMPL; .) +. + + + -ListLiteral = (. Expression e2; .) -'[' -(']' ';' (. e = Expression(Operator::LIST, Expression()); .) -| Expr (. e = Expression(Operator::LIST, e2); .) -{',' Expr (. e.addArg(e2); .) -} -']' -';'). /*============================ Expressions ===============================*/ +ListLiteral = (. Expression e2; .) +'[' (. e = Expression(Operator::LIST, Expression()); .) +[ Expr (. e.addArg(e2); .) +{',' Expr (. e.addArg(e2); .) +}] ']'. + + Expr< Expression& e> (. Operator op; Expression e2; .) = SimExpr< e> [ RelOp< op> - SimExpr< e2> (. Expression e (op, e); - e.addArg(e2); - .) + SimExpr< e2> (. e = Expression(op, e); e.addArg(e2); .) ]. SimExpr< Expression& e> (. Operator op; Expression e2; .) = Term< e> { AddOp< op> - Term< e2> (. e = Expression(op, e); - e.addArg(e2); - .) + Term< e2> (. e = Expression(op, e); e.addArg(e2);.) }. Term< Expression& e> (. Operator op; Expression e2; .) = Factor< e> { MulOp< op> - Factor< e2> (. e = Expression(op, e); - e.addArg(e2); - .) - }. + Factor< e2> (. e = Expression(op, e); e.addArg(e2); .) + }. -Factor< Expression& e> (. std::wstring name; .) +Factor< Expression& e> (. std::wstring name;.) = - ( Ident< name> (. e = Expression(Atom(name)); .) - | number (. e = Expression(Atom(t->val)); .) - | '-' Factor< e> (. e = Expression(Operator::NEG, e); .) + (IF (checkParametersList()) Ident< name> + (. e = Expression(Operator::CALL, Atom(name)); .) + '(' [CalleeParams] ')' + | Ident< name> (. e = Expression(Atom(name)); .) + + | number (. e = Expression(Atom(t->val)); .) + | '-' Factor< e> (. e = Expression(Operator::NEG, e); .) + | '(' Expr ')' ). - +CalleeParams = (. Expression e2; .) + Expr (. e.addArg(e2); .) + {',' Expr (. e.addArg(e2); .) + }. AddOp< Operator& op> = (. op = Operator::ADD; .) ( '+' | '-' (. op = Operator::SUB; .) ). MulOp< Operator& op> = (. op = Operator::MUL; .) ( '*' | '/' (. op = Operator::DIV; .) ). RelOp< Operator& op> = (. op = Operator::EQU; .) - ( "==" + ( '=' '=' | '<' (. op = Operator::LSS; .) | '>' (. op = Operator::GTR; .) ). END Xreate. diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 0000000..58c7116 --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 2.8.11) +project(Xreate) +find_package(LLVM REQUIRED CONFIG) +find_package(Qt5Core) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(SOURCE_FILES + ./src/ast.cpp ./src/ast-compilation.cpp + ./src/llvmlayer.cpp ./src/clasplayer.cpp + #./src/main.cpp + ./tests/tests.cpp + ./src/pass/cfgpass.cpp ./src/pass/functiontagspass.cpp + + /opt/potassco/gringo-4.4.0-source/app/shared/src/clingocontrol.cc + /opt/potassco/gringo-4.4.0-source/app/pyclingo/src/clingo_lib.cc +) + +set(COCO_PATH "./../coco/") +set(COCO_SOURCE_FILES + ${COCO_PATH}/Parser.h + ${COCO_PATH}/Scanner.h + ${COCO_PATH}/Parser.cpp + ${COCO_PATH}/Scanner.cpp +) + +set(POTASSCO_PATH "/opt/potassco/gringo-4.4.0-source") + +INCLUDE_DIRECTORIES(${COCO_PATH} ./src) +INCLUDE_DIRECTORIES(${POTASSCO_PATH}/libgringo +${POTASSCO_PATH}/libclasp +${POTASSCO_PATH}/app/shared/include +${POTASSCO_PATH}/app/pyclingo/src +${POTASSCO_PATH}/libprogram_opts +) + +execute_process(COMMAND ${COCO_PATH}/gen-xreate WORKING_DIRECTORY ${COCO_PATH} OUTPUT_VARIABLE COCO_OUTPUT) +message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT}) + +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) + +add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES}) + +llvm_map_components_to_libnames(llvm_libs support core irreader) +message(STATUS "LLVM LIBS: " ${llvm_libs}) + +set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug) + +#find_library(LIBCLASP_LIBRARY_GRINGO NAMES gringo +# HINTS ${LIBCLASP_PATH}) +#find_library(LIBCLASP_LIBRARY_CLASP NAMES clasp +# HINTS ${LIBCLASP_PATH}) + +set(LIBCLASP_LIBS + ${LIBCLASP_PATH}/libclasp.a + ${LIBCLASP_PATH}/libgringo.a + ${LIBCLASP_PATH}/libprogram_opts.a +) + +message(STATUS ${LIBCLASP_LIBS}) + +target_link_libraries(xreate ${llvm_libs} pthread Qt5::Core ${LIBCLASP_LIBS}) + +add_definitions(-DWITH_THREADS=0) diff --git a/cpp/src/ast-compilation.cpp b/cpp/src/ast-compilation.cpp new file mode 100644 index 0000000..118252a --- /dev/null +++ b/cpp/src/ast-compilation.cpp @@ -0,0 +1,168 @@ +#include + +llvm::Value* +LLVMExpression::compile(LLVMLayer& l, Function* f, std::string* hintRetVar) const +{ + std::string var; + if (hintRetVar && f->__vartable.count(*hintRetVar)) + { + var = *hintRetVar; + } + + #define VARNAME(x) (var.size()? var : x) + llvm::Value* left; llvm::Value* right; + + + switch (__op) + { + case Operator::ADD: case Operator::SUB: case Operator::MUL: case Operator::DIV: case Operator::EQU: case Operator::LSS: case Operator::GTR: + assert(__source.__state == COMPOUND); + assert(__source.operands.size() == 2); + + left = __source.operands[0].compile(l, f); + right = __source.operands[1].compile(l, f); + break; + + default: ; + } + + switch (__op) + { + case Operator::ADD: + return l.builder.CreateFAdd(left, right, VARNAME("tmp_add")); + break; + + case Operator::SUB: + return l.builder.CreateFSub(left, right, VARNAME("tmp_sub")); + break; + + case Operator::MUL: + return l.builder.CreateFMul(left, right, VARNAME("tmp_mul")); + break; + + case Operator::DIV: + return l.builder.CreateFDiv(left, right, VARNAME("tmp_div")); + break; + + case Operator::EQU: + return l.builder.CreateFCmpOEQ(left, right, VARNAME("tmp_equ")); + break; + + case Operator::LSS: + return l.builder.CreateFCmpOLT(left, right, VARNAME("tmp_lss")); + break; + + case Operator::GTR: + return l.builder.CreateFCmpOGT(left, right, VARNAME("tmp_gtr")); + break; + + case Operator::NEG: + left = __source.operands[0].compile(l, f); + return l.builder.CreateFNeg(left, VARNAME("tmp_neg")); + break; + + case Operator::CALL: + { + assert(__source.__state == COMPOUND); + + const std::string& fname = __source.__valueS; + assert(f->root->__indexFunctions.count(fname)); + + const Function& calleeFunc = f->root->getFunctionById(f->root->__indexFunctions[fname]); + llvm::Function* callee = calleeFunc.__raw; + + std::vector args; + args.reserve(operands.size()-1); + + std::transform(__source.operands.begin(), __source.operands.end(), std::inserter(args, args.end()), + [&l, f](const Expression &operand){return compile(operand, f); } + ); + + return l.builder.CreateCall(callee, args, VARNAME("tmp_call")); + } + break; + + + case Operator::NONE: + assert(__source.__state != COMPOUND); + + switch (__source.__state) + { + case IDENT: + { + std::string vname = __source.__valueS; + assert(f->__vartable.count(vname)); + + VID vId =f->__vartable[vname]; + if (f->__rawVars.count(vId)) + { + return f->__rawVars[vId]; + } + + Expression& e = f->__declarations[vId]; + llvm::Value* result = e.compile(l, f, &vname); + f->__rawVars[vId] = result; + return result; + break; + } + + case NUMBER: + double literal = __valueD; + return llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(literal)); + }; + + break; + + } + + assert(false); + return 0; +} + +llvm::Function* +Function::compile(LLVMLayer &l) +{ + + std::vector types; + std::transform(__args.begin(), __args.end(), std::inserter(types, types.end()), + [this](std::string& arg) { + assert(__vartable.count(arg)); + VID argid = __vartable[arg]; + + assert(__definitions.count(argid)); + return __definitions[argid].toLLVMType(); + } ); + + llvm::FunctionType* ft = llvm::FunctionType::get(__retType.toLLVMType(), types,false); + __raw = llvm::cast(l.module->getOrInsertFunction(__name,ft)); + + llvm::Function::arg_iterator fargsI = __raw->arg_begin(); + for(std::string& arg : __args) + { + VID argid = __vartable[arg]; + + __rawVars[argid] = fargsI; + fargsI->setName(arg); + ++fargsI; + } + + llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", __raw); + l.builder.SetInsertPoint(block); + + l.builder.CreateRet(__body.compile(l, this, 0)); + l.moveToGarbage(ft); + + return __raw; +}; + +void +AST::compile(LLVMLayer &layer) +{ + layer.module = new llvm::Module(getModuleName(),llvm::getGlobalContext()); + + for(Function& f: __functions) + { + llvm::Function* rawf = f.compile(layer); + + } +} diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp index f4b6f97..fcc157f 100644 --- a/cpp/src/ast.cpp +++ b/cpp/src/ast.cpp @@ -1,305 +1,236 @@ #include "ast.h" #include +#include +#include +#include + using namespace std; TypeAnnotation::TypeAnnotation() {} TypeAnnotation::TypeAnnotation(const Atom &typ) { __value = typ.get(); } TypeAnnotation::TypeAnnotation(const TypeOperator &op, const TypeAnnotation &typ) {} llvm::Type* TypeAnnotation::toLLVMType() { switch (__value) { case Bool: return llvm::Type::getInt1Ty(llvm::getGlobalContext()); case Int: case Float: case Num: return llvm::Type::getDoubleTy(llvm::getGlobalContext()); default: assert(false); } return NULL; } -Expression::Expression() - : __op(Operator::NONE), state(INVALID) -{} + Expression::Expression(const Atom& number) -: state(NUMBER), __op(Operator::NONE), __valueD(number.get()) +: __state(NUMBER), __op(Operator::NONE), __valueD(number.get()) { } Expression::Expression(const Atom &ident) - : state(IDENT), __op(Operator::NONE), __valueS(ident.get()) + : __state(IDENT), __op(Operator::NONE), __valueS(ident.get()) { } -Expression::Expression(const Operator &op, const Expression &arg) - : state(COMPOUND), __op(op) +Expression::Expression(const Operator &op, std::initializer_list params) + : __state(COMPOUND), __op(op) { - operands.push_back(arg); -} + if (op == Operator::CALL) + { + assert(params.size() > 0); + Expression arg = *params.begin(); -void -Expression::addArg(const Expression &arg) -{ - assert(state == COMPOUND); - assert(op!=Operator::NONE); + assert(arg.__state == Expression::IDENT); + __valueS = std::move(arg.__valueS); + return; + } - operands.push_back(arg); + operands.insert(operands.end(), params); } -llvm::Value* -Expression::compile(LLVMLayer& l, Function* f, std::string* retVarHint) +void +Expression::setOp(Operator op) { - std::string var; - if (retVarHint && f->__vartable.count(*retVarHint)) - { - var = *retVarHint; - } - - #define VARNAME(x) (var.size()? var : x) - llvm::Value* left; llvm::Value* right; + __op = op; - - switch (__op) + switch (op) { - case Operator::ADD: case Operator::SUB: case Operator::MUL: case Operator::DIV: case Operator::EQU: case Operator::LSS: case Operator::GTR: - left = operands[0].compile(l, f); - right = operands[1].compile(l, f); + case Operator::NONE: + __state = INVALID; break; - default: ; - } - - switch (__op) - { - case Operator::ADD: - return l.builder.CreateFAdd(left, right, VARNAME("tmp_add")); - break; - - case Operator::SUB: - return l.builder.CreateFSub(left, right, VARNAME("tmp_sub")); - break; - - case Operator::MUL: - return l.builder.CreateFMul(left, right, VARNAME("tmp_add")); - break; - - case Operator::DIV: - return l.builder.CreateFDiv(left, right, VARNAME("tmp_sub")); - break; - - case Operator::EQU: - return l.builder.CreateFCmpOEQ(left, right, VARNAME("tmp_eq")); - break; - - case Operator::LSS: - return l.builder.CreateFCmpOLT(left, right, VARNAME("tmp_eq")); - break; - - case Operator::GTR: - return l.builder.CreateFCmpOGT(left, right, VARNAME("tmp_eq")); - break; - - case Operator::NEG: - left = operands[0].compile(l, f); - return l.builder.CreateFNeg(left, VARNAME("tmp_eq")); - break; - - case Operator::CALL: - { - std::string fname = operands[0].__valueS; - assert(f->root->__rawFunctions.count(fname)); - - llvm::Function* callee = f->root->__rawFunctions[fname]; - - std::vector args; - args.reserve(operands.size()-1); - for(int i=1; i__vartable.count(vname)); - - vid vId =f->__vartable[vname]; - - assert(var.size()==0); - if (f->__rawVars.count(vId)) - { - return f->__rawVars[vId]; - } - - Expression& e = f->__declarations[vId]; - llvm::Value* result = e.compile(l, f); - f->__rawVars[vId] = result; - return result; + default: + __state = COMPOUND; break; - } + } +} - case NUMBER: - double literal = operands[0].__valueD; - return llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(literal)); - }; +void +Expression::addArg(Expression &&arg) +{ + operands.push_back(arg); +} - break; +Expression::Expression() + : __op(Operator::NONE), __state(INVALID) +{} - } - assert(false); - return 0; +AST::AST() +{ } -AST::AST() +void +AST::add(Function &f) { + f.root = this; + __functions.push_back(f); + __indexFunctions[f.getName()] = __functions.size()-1; } std::string AST::getModuleName() { const std::string name = "moduleTest"; return name; } -void -AST::compile(LLVMLayer &layer) +FID +AST::getFunctionsCount() const { - layer.module = new llvm::Module(getModuleName(),llvm::getGlobalContext()); + return __functions.size(); +} - for(Function& f: __functions) - { - llvm::Function* rawf = f.compile(layer); - __rawFunctions[f.getName()] = rawf; - } +const Function& +AST::getFunctionById(FID id)const +{ + assert(id>=0 && id < __functions.size()); + return __functions[id]; } void AST::run(LLVMLayer &l) { llvm::PassManager PM; - PM.add(llvm::createPrintModulePass(&llvm::outs())); + PM.add(llvm::createPrintModulePass(llvm::outs())); PM.run(*l.module); } Function::Function(const wstring &name) + :__vCounter(0) { char buffer[1000]; wcstombs(buffer, name.c_str(), 1000); __name = buffer; } +void +Function::addAnnotation(const wstring& aname, const AnnotationModifier amod) +{ + char buffer[1000]; + wcstombs(buffer, aname.c_str(), 1000); + std::string name(buffer); + + cout << QString("Function annotation: %1 <- %2").arg(__name.c_str()).arg(name.c_str()).toStdString()<>& +Function::getAnnotations() const +{ + return __tags; +} + void Function::addArg(const wstring &vname, const TypeAnnotation &typ) { char buffer[1000]; wcstombs(buffer, vname.c_str(), 1000); std::string name(buffer); - vid id = registerVar(name); + VID id = registerVar(name); __definitions[id] = typ; __args.push_back(name); } void Function::setBody(const Expression &body) { __body = body; } void Function::setReturnType(const TypeAnnotation &rtyp) { __retType = rtyp; } -vid +VID Function::registerVar(const std::string& vname) { - return ++__vCounter; + __vartable[vname] = ++__vCounter; + return __vCounter; } const std::string& Function::getName() const { return __name; } void Function::addListDeclaration(const wstring &vname, const TypeAnnotation &typ, const Expression &e) {} void Function::addDeclaration(const wstring &vname, const TypeAnnotation &typ, const Expression &e) { char buffer[1000]; wcstombs(buffer, vname.c_str(), 1000); std::string v(buffer); - vid id = registerVar(v); + VID id = registerVar(v); __definitions[id] = typ; __declarations[id] = e; } -llvm::Function* -Function::compile(LLVMLayer &l) -{ - - std::vector types; - std::transform(__args.begin(), __args.end(), std::inserter(types, types.end()), - [this](std::string& arg) { - assert(__vartable.count(arg)); - - vid argid = __vartable[arg]; - assert(__definitions.count(argid)); - return __definitions[argid].toLLVMType(); - } ); - llvm::FunctionType* ft = llvm::FunctionType::get(__retType.toLLVMType(), types,false); - __raw = llvm::cast(l.module->getOrInsertFunction(__name,ft)); - - llvm::Function::arg_iterator fargsI = __raw->arg_begin(); - for(std::string& arg : __args) - { - vid argid = __vartable[arg]; +void +RuleArguments::add(std::string&& name, DomainAnnotation typ) +{ + emplace_back(name, typ); +} - __rawVars[argid] = fargsI; - fargsI->setName(arg); - ++fargsI; - } +void +RuleGuards::add(Expression&& e) +{ + push_back(e); +} - llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", __raw); - l.builder.SetInsertPoint(block); +void +RuleWarning::compile(ClaspLayer& layer) +{ + layer.addRuleWarning(this); +} - l.builder.CreateRet(__body.compile(l, this, 0)); - l.moveToGarbage(ft); - return __raw; -}; diff --git a/cpp/src/ast.h b/cpp/src/ast.h index 6e648c9..22b8597 100644 --- a/cpp/src/ast.h +++ b/cpp/src/ast.h @@ -1,189 +1,248 @@ #ifndef AST_H #define AST_H #include #include #include #include "llvmlayer.h" struct Identifier_t {}; struct Number_t {}; struct Type_t {}; template class Atom{ }; template<> class Atom { public: Atom(const std::wstring& value) { char buffer[1000]; wcstombs(buffer, value.c_str(), 1000); __value = buffer; } const std::string& get() const{return __value; } private: std::string __value; }; template<> class Atom { public: Atom(wchar_t* value) { __value = wcstol(value, 0, 10); } int get()const {return __value; } private: double __value; }; enum TimePrimitive {Bool, Int, Float, Num, String}; template<> class Atom { public: Atom(wchar_t* value) { char buffer_[1000]; wcstombs(buffer_, value, 1000); std::string buffer(buffer_); if (buffer=="bool"){ __value = Bool; } else if (buffer=="int") { __value = Int; } else if (buffer=="float") { __value = Float; } else if (buffer=="num") { __value = Num; } else if (buffer=="string") { __value = String; } } Atom () { } TimePrimitive get() const { return __value; } private: TimePrimitive __value; }; typedef Atom TypeAtom; enum class TypeOperator{LIST}; class TypeAnnotation { public: TypeAnnotation (const Atom& typ); TypeAnnotation (const TypeOperator& op, const TypeAnnotation& typ); TypeAnnotation(); llvm::Type* toLLVMType(); private: TimePrimitive __value; }; - enum class Operator { -ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, CALL, NONE +ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, CALL, NONE, IMPL/* implication */ }; - class Function; class AST; -typedef unsigned int vid; - class Expression { public: - Expression(const Operator& op, const Expression& arg); + Expression(const Operator &op, std::initializer_list params); Expression(const Atom& ident); Expression(const Atom& number); Expression(); - void addArg(const Expression& arg); - llvm::Value* compile(LLVMLayer& l, Function* f, std::string* retVarHint=0); - -private: + void setOp(Operator op); + void addArg(Expression&& arg); +protected: Operator __op; std::vector operands; std::string __valueS; double __valueD; - enum {INVALID, COMPOUND, IDENT, NUMBER, STRING} state; + enum {INVALID, COMPOUND, IDENT, NUMBER, STRING} __state; +}; + +enum class AnnotationModifier +{NONE, ASSERT, REQUIRE}; + +enum class DomainAnnotation +{FUNCTION, VARIABLE}; + +class RuleArguments: public std::vector> +{ +public: + void add(std::string&& name, DomainAnnotation typ); +}; + +class RuleGuards: public std::vector +{ +public: + void add(Expression&& e); +}; + +class MetaRuleAbstract +{ +protected: + RuleArguments __args; + RuleGuards __guards; +}; + +class ClaspLayer; +class RuleWarning: public MetaRuleAbstract +{ + friend class ClaspLayer; +public: + void compile(ClaspLayer& layer); + +private: + std::string __message; + Expression __condition; +}; + +typedef unsigned int VID; + + + +/* +class Expression: ExpressionAbstract +{ + friend class CFGPass; + +public: + llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const; }; +*/ -typedef std::pair VariableDefinition; -typedef std::pair VariableDeclaration; +typedef std::pair VariableDefinition; +typedef std::pair VariableDeclaration; class Function { friend class Expression; + friend class CFGPass; public: Function(const std::wstring& name); void setReturnType(const TypeAnnotation& rtyp); void addArg(const std::wstring& vname, const TypeAnnotation& typ); void setBody(const Expression& body); + void addAnnotation(const std::wstring& aname, const AnnotationModifier amod); + const std::vector>& getAnnotations() const; + void addDeclaration(const std::wstring& vname, const TypeAnnotation& typ, const Expression& e); void addListDeclaration(const std::wstring& vname, const TypeAnnotation& typ, const Expression& e); const std::string& getName() const; llvm::Function* compile(LLVMLayer& l); -private: AST* root; +private: + std::string __name; TypeAnnotation __retType; std::vector __args; + std::vector> __tags; std::map __definitions; std::map __declarations; - std::map __vartable; + std::map __vartable; Expression __body; llvm::Function* __raw; - std::map __rawVars; + std::map __rawVars; + + VID __vCounter; - vid __vCounter; + VID registerVar(const std::string& vname); - vid registerVar(const std::string& vname); + llvm::Value* compileExpression(Expression& expr, LLVMLayer& l, std::string* hintRetVar) const; }; +typedef unsigned int FID; class AST { friend class Expression; + friend class CFGPass; + public: AST(); - void add(const Function& f); + void add(Function& f); void compile(LLVMLayer& l); void run(LLVMLayer& l); std::string getModuleName(); + + FID getFunctionsCount() const; + const Function& getFunctionById(FID id) const; private: std::vector __functions; - - std::map __rawFunctions; + std::map __indexFunctions; }; #endif // AST_H diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp new file mode 100644 index 0000000..a657703 --- /dev/null +++ b/cpp/src/clasplayer.cpp @@ -0,0 +1,276 @@ +#include "clasplayer.h" + +#include // for defining logic programs +#include // unfounded set checkers +#include // for enumerating answer sets +#include + +#include + +#include +#include +#include +#include +using namespace std; + +bool +ClaspLayer::onModel(Gringo::Model const & model) +{ + cout << "Model: " << endl; + for (Gringo::Value atom : model.atoms(Gringo::Model::ATOMS)) + { + atom.print(cout); + cout << endl; + } +} + +QStringList multiplyLists(std::list&& lists) +{ + QStringList&& result = lists.front(); + lists.pop_front(); + + for (QStringList& list: lists) + { + QStringList::const_iterator end = result.end(); + for (QStringList::iterator expr1I=result.begin(); expr1I& relation: graph.__relations) + { + const string& tagFrom = graph.__nodes.at(relation.first); + const string& tagTo = graph.__nodes.at(relation.second); + + cout << (QString("call(%1, %2) .").arg(tagFrom.c_str()).arg(tagTo.c_str())).toStdString()<& tags) +{ + ostream& cout = __partTags; + + cout << (QString("function(%1) .").arg(function.c_str())).toStdString()<__args.begin(), rule->__args.end(), std::inserter(domains, domains.begin()), + [](const auto& argument) { + char* domain; + switch (argument.second) + { case DomainAnnotation::FUNCTION: + domain = "function"; + break; + case DomainAnnotation::VARIABLE: + domain = "variable"; + break; + } + + return QString("%1(%2)").arg(domain).arg(argument.first.c_str()); + }); + + std::QStringList vars; + std::transform(rule->__args.begin(), rule->__args.end(), std::inserter(vars, vars.begin()), + [](const auto& argument) { + return argument.first.c_str(); + }); + + std::QStringList guards; + std::transform(rule->__guards.begin(), rule->__guards.end(), std::inserter(guards, guards.begin()), + [](const MetaExpression& guard) { + return compile(guard)._c_str(); + }); + + QStringList&& branches = compileNeg(rule->__condition); + + for(const std::string& branch: branches) + { + std::string listener = registerListener(rule->__message); + + result = QString("%1(%2):-%3, %4, %5") + .arg(listener.c_str()) + .arg(vars.join(", ")) + .arg(branch.c_str()) + .arg(guards.join(", ")) + .arg(domains.join(", ")); + + __partGeneral<< result << endl; + } +} + +QStringList +ClaspLayer::compile(const Expression& e) const +{ + QStringList result; + + switch(e.__op) + { + case Operator::CALL: + assert(e.__state == COMPOUND); + + std::list operands; + std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands().begin()), + [](const Expression& e) {return compile(e);}); + + QStringList&& operands_ = multiplyLists(operands); + result.append(QString("%1(%2)").arg(e.__valueS.c_str()).arg(operands_.join(", "))); + break; + + case Operator::NONE: + switch (e.__state) + { + case Expression::IDENT: + result.append(e.__valueS); + break; + + case Expression::NUMBER: + result.append(e.__valueD); + break; + + default: + assert(true); + } + break; + } + + return result; +} + +QStringList compileNeg(const Expression& e) const +{ + QStringList result; + switch(__op) + { + case Operator::IMPL: + assert(e.__state == COMPOUND); + assert(e.operands.size() == 2); + QStringList operands1 = compile(e.operands.at(0)); + QStringList operands2 = compile(e.operands.at(1)); + + for (const auto& op1: operands1) + for (const auto& op2: operands2) + { + result.append(QString("%1, not %2").arg(op1).arg(op2)); + } + break; + + default: + assert(true); + } + + return result; +} + +void +ClaspLayer::run() +{ + ostringstream program; + program << __partTags.str() << __partGeneral.str(); + cout << program.str() << endl; + + const char* argv[] = {nullptr, nullptr}; + ClingoLib ctl(2, argv); + + //prg.add("p", ["t"], "q(t).") + Gringo::FWStringVec vars{}; + ctl.add("base", vars, program.str()); + + //prg.ground([("p", [2])]) + Gringo::Control::GroundVec vals{std::make_pair("base", Gringo::FWValVec {})}; + ctl.ground(vals, Gringo::Any()); + + //solve + Gringo::Control::Assumptions as; + Gringo::SolveResult result = ctl.solve(Gringo::Control::ModelHandler([&](Gringo::Model const &model){return this->onModel(model);}), std::move(as)); + + if (result == Gringo::SolveResult::SAT) + { + cout << "SUCCESSFULLY" << endl; + } else { + cout << "UNSUCCESSFULLY" << endl; + } +} + +ClaspLayer::ClaspLayer() +{} + +/* +void AspOutPrinter::reportSolution(const Clasp::Solver&, const Clasp::Enumerator&, bool complete) { + if (complete) std::cout << "No more models!" << std::endl; + else std::cout << "More models possible!" << std::endl; +} + + +void AspOutPrinter::reportModel(const Clasp::Solver& s, const Clasp::Enumerator&) { + std::cout << "Model " << s.stats.solve.models << ": \n"; +// get the symbol table from the solver + const Clasp::AtomIndex& symTab = *s.strategies().symTab; + for (Clasp::AtomIndex::const_iterator it = symTab.begin(); it != symTab.end(); ++it) + { +// print each named atom that is true w.r.t the current assignment + } + std::cout << std::endl; +} + +*/ + + +/***************************************** + * CFGraph + ***************************************** + */ + +void +CFGraph::addNode(FID function, std::string&& tag) +{ + __nodes.insert(make_pair(function, move(tag))); +} + +bool +CFGraph::existsNode(FID function) const +{ + return __nodes.count(function); +} + +void +CFGraph::addLink(FID nodeFrom, FID nodeTo) +{ + assert(__nodes.count(nodeFrom)); + assert(__nodes.count(nodeTo)); + + __relations.insert(std::make_pair(nodeFrom, nodeTo)); +} diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h new file mode 100644 index 0000000..7a8495e --- /dev/null +++ b/cpp/src/clasplayer.h @@ -0,0 +1,44 @@ +#ifndef CLASPLAYER_H +#define CLASPLAYER_H +#include +#include +#include + +typedef std::pair Tag; + +class CFGraph; + +class ClaspLayer +{ + +public: + ClaspLayer(); + + void addFunctionTags(const std::string& function, const std::vector& tags); + void addCFGData(CFGraph&& graph); + void addWarningRule(const char* rule); + + void run(); + +private: + std::ostringstream __partTags; + std::ostringstream __partGeneral; + + bool onModel(Gringo::Model const & model); +}; + +class CFGraph +{ + friend class ClaspLayer; +public: + void addNode(FID function, std::string&& tag); + void addLink(FID nodeFrom, FID nodeTo); + bool existsNode(FID function) const; + void print(std::ostream& cout) const; + +private: + std::map __relations; + std::map __nodes; +}; + +#endif diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp index 97f5978..99a16b7 100644 --- a/cpp/src/llvmlayer.cpp +++ b/cpp/src/llvmlayer.cpp @@ -1,13 +1,17 @@ #include "llvmlayer.h" using namespace llvm; LLVMLayer::LLVMLayer() :builder(getGlobalContext()) { } void LLVMLayer::moveToGarbage(void *o) { __garbage.push_back(o); } + +LLVMExpression::LLVMExpression(Expression &&e) + : Delegate(e) +{} diff --git a/cpp/src/llvmlayer.h b/cpp/src/llvmlayer.h index 6dec359..7cbe58e 100644 --- a/cpp/src/llvmlayer.h +++ b/cpp/src/llvmlayer.h @@ -1,28 +1,31 @@ #ifndef LLVMLAYER_H #define LLVMLAYER_H #include "llvm/IR/Module.h" #include "llvm/IR/Function.h" #include "llvm/PassManager.h" #include "llvm/IR/CallingConv.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/IRBuilder.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/LLVMContext.h" +//#include "ast.h" + class LLVMLayer { public: LLVMLayer(); llvm::Module* module; llvm::IRBuilder<> builder; void moveToGarbage(void* o); + llvm::Value* compile() const; private: std::vector __garbage; }; #endif // LLVMLAYER_H diff --git a/cpp/src/main.cpp b/cpp/src/main.cpp index 3c81c44..e68bba5 100644 --- a/cpp/src/main.cpp +++ b/cpp/src/main.cpp @@ -1,59 +1,59 @@ #include -#include "llvm/Module.h" +#include "llvm/IR/Module.h" #include "llvm/Function.h" #include "llvm/PassManager.h" #include "llvm/CallingConv.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Support/IRBuilder.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; int main() { LLVMContext& ctx = makeLLVMModule(); Module* m = new Module("test"); Constant* c = m->getOrInsertFunction("mul_add", /*ret type*/ IntegerType::get(ctx,32), /*args*/ IntegerType::get(ctx,32), IntegerType::get(ctx, 32), IntegerType::get(ctx,32), /*varargs terminated with null*/ NULL); Function* mul_add = cast(c); mul_add->setCallingConv(CallingConv::C); Function::arg_iterator args = mul_add->arg_begin(); Value* x = args++; x->setName("x"); Value* y = args++; y->setName("y"); Value* z = args++; z->setName("z"); BasicBlock* block = BasicBlock::Create(getGlobalContext(), "entry", mul_add); IRBuilder<> builder(block); Value* tmp = builder.CreateBinOp(Instruction::Mul, x, y, "tmp"); Value* tmp2 = builder.CreateBinOp(Instruction::Add, tmp, z, "tmp2"); builder.CreateRet(tmp2); verifyModule(*m, PrintMessageAction); PassManager man; man.add(createPrintModulePass(&outs())); man.run(*m); delete m; return 0; } diff --git a/cpp/src/pass/cfgpass.cpp b/cpp/src/pass/cfgpass.cpp new file mode 100644 index 0000000..844abc3 --- /dev/null +++ b/cpp/src/pass/cfgpass.cpp @@ -0,0 +1,75 @@ +#include "cfgpass.h" +#include + +using namespace std; + +CFGPass::CFGPass(const AST& entity) + : __root(entity) +{ + +} + +void +CFGPass::process(const Expression& entity, const FID funcId) +{ + switch(entity.__state) + { + case Expression::COMPOUND: + for (const Expression& op: entity.operands) + { + process(op, funcId); + } + + if (entity.__op == Operator::CALL) + { + const std::string& calleeName = entity.__valueS; + assert(__root.__indexFunctions.count(calleeName)); + FID calleeId = __root.__indexFunctions.at(calleeName); + + if (!__graph.existsNode(calleeId)) + { + __graph.addNode(calleeId, string(calleeName)); + process(calleeId); + } + + __graph.addLink(funcId, calleeId); + } + break; + + case Expression::IDENT: + const Function& func = __root.getFunctionById(funcId); + const std::string& identName = entity.__valueS; + + assert(func.__vartable.count(identName)); + VID identId = func.__vartable.at(identName); + + if (func.__declarations.count(identId)) + { + const Expression& identExpr = func.__declarations.at(identId); + process(identExpr, funcId); + } + } +} + +void +CFGPass::process(const FID funcId) +{ + const Function& f = __root.getFunctionById(funcId); + process(f.__body, funcId); +} + +void +CFGPass::run(ClaspLayer& clasp) +{ + __graph = CFGraph(); + cout << "CFGPass::run" << endl; + + for(FID f=0, fcount=__root.getFunctionsCount(); f +#include +#include "clasplayer.h" + +class CFGPass +{ +public: + CFGPass(const AST& entity); + void run(ClaspLayer& clasp); + +private: + const AST& __root; + CFGraph __graph; + + void process(const Expression& entity, const FID funcId); + void process(const FID funcId); +}; + +#endif // CFGPASS_H diff --git a/cpp/src/pass/functiontagspass.cpp b/cpp/src/pass/functiontagspass.cpp new file mode 100644 index 0000000..e57c472 --- /dev/null +++ b/cpp/src/pass/functiontagspass.cpp @@ -0,0 +1,18 @@ +#include "functiontagspass.h" +#include +using namespace std; + +FunctionTagsPass::FunctionTagsPass(AST& root) + : __root(root) +{ +} + +void +FunctionTagsPass::run(ClaspLayer& clasp) +{ + for (FID id=0, count = __root.getFunctionsCount(); id < count; ++id) + { + const Function& f = __root.getFunctionById(id); + clasp.addFunctionTags(f.getName(), f.getAnnotations()); + } +} diff --git a/cpp/src/pass/functiontagspass.h b/cpp/src/pass/functiontagspass.h new file mode 100644 index 0000000..e58020f --- /dev/null +++ b/cpp/src/pass/functiontagspass.h @@ -0,0 +1,17 @@ +#ifndef FUNCTIONTAGSPASS_H +#define FUNCTIONTAGSPASS_H + +#include "ast.h" +#include +#include "clasplayer.h" + +class FunctionTagsPass +{ +public: + FunctionTagsPass(AST& root); + void run(ClaspLayer& clasp); +private: + const AST& __root; +}; + +#endif // FUNCTIONTAGSPASS_H diff --git a/cpp/src/tests.cpp b/cpp/src/tests.cpp deleted file mode 100644 index 3520067..0000000 --- a/cpp/src/tests.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "Scanner.h" -#include "Parser.h" -#include "ast.h" -#include - -using namespace std; - -void testParser_1() -{ - shared_ptr scanner(new Scanner(L"scripts/input.xreate")); - shared_ptr parser(new Parser(scanner.get())); - - AST& root = parser->root; - LLVMLayer l; - - root.compile(l); - root.run(l); -} - -int main() -{ - return 0; -} diff --git a/cpp/tests/tests.cpp b/cpp/tests/tests.cpp new file mode 100644 index 0000000..726d165 --- /dev/null +++ b/cpp/tests/tests.cpp @@ -0,0 +1,61 @@ +#include "Scanner.h" +#include "Parser.h" +#include "ast.h" +#include +#include +#include "cfgpass.h" +#include "clasplayer.h" +#include "functiontagspass.h" +#include + +using namespace std; + +void testParser_1() +{ + shared_ptr scanner(new Scanner(L"scripts/input.xreate")); + shared_ptr parser(new Parser(scanner.get())); + parser->Parse(); + flush(cout); + + AST& root = parser->root; + LLVMLayer l; + + root.compile(l); + root.run(l); +} + +void testClasp2() +{ + shared_ptr scanner(new Scanner(L"scripts/input.xreate")); + shared_ptr parser(new Parser(scanner.get())); + parser->Parse(); + flush(cout); + + if (parser->errors->count) + { + cout << "Found " << parser->errors->count << " errors. Stop" << endl; + exit(1); + } + + AST& root = parser->root; + ClaspLayer clasp; + + FunctionTagsPass(root).run(clasp); + + CFGPass(root).run(clasp); + clasp.addRule(":- call(X, Y), tag(Y, unsafe), not tag(X, unsafe), function(X), function(Y)."); + + clasp.run(); +} + +void tests_ListsMultiply() +{ + +} + +int main() +{ + testClasp2(); + + return 0; +} diff --git a/cpp/xreate/xreate.pro b/cpp/xreate/xreate.pro deleted file mode 100644 index 443eddf..0000000 --- a/cpp/xreate/xreate.pro +++ /dev/null @@ -1,29 +0,0 @@ -TEMPLATE = app -CONFIG += console -CONFIG -= qt - -#INCLUDEPATH += /usr/lib/llvm-3.4/include -LIBS += -L/usr/lib/llvm-3.4/lib `llvm-config-3.4 --libs` -lpthread -lffi -ltinfo -ldl -lm -QMAKE_CXXFLAGS += -I/usr/lib/llvm-3.4/include `llvm-config-3.4 --cxxflags` -std=c++0x - - -SOURCES += \ - # ../src/main.cpp \ - ../../coco/Parser.cpp \ - ../../coco/Scanner.cpp \ - ../src/ast.cpp \ - ../src/tests.cpp \ - ../src/llvmlayer.cpp - -HEADERS += \ - ../../coco/Parser.h \ - ../../coco/Scanner.h \ - ../src/ast.h \ - ../src/llvmlayer.h - -INCLUDEPATH += \ - ../src \ - ../../coco - - - diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..463d822 --- /dev/null +++ b/pom.xml @@ -0,0 +1,62 @@ + + 4.0.0 + + org.xreate + xreate + 1.0-SNAPSHOT + jar + + xreate + http://maven.apache.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + UTF-8 + + + + + junit + junit + 4.10 + jar + + + org.antlr + antlr + 3.2 + + + org.antlr + antlr-runtime + 3.2 + + + com.google.guava + guava + 11.0.2 + + + javolution + javolution + 5.5.1 + + + jllvm + jllvm + 2.8 + + + diff --git a/problems/example-computations.lp b/problems/example-computations.lp index 762f2db..4cdd8a3 100644 --- a/problems/example-computations.lp +++ b/problems/example-computations.lp @@ -1,49 +1,49 @@ %defines: implementation(hashlist). implementation(linkedlist). implementation(treelist). implementation(computation). operation(at). operation(sort). operation(insert). operation(seqaccess). connection_type(ct_inherits). connection_type(ct_convert). relation (recommends). relation (satisfied). relation(unsupported). relation_score(satisfied, 0). relation_score(recommends, 1). relation_score(unsupported, -1). %integration facts: relation_op(seqaccess, computation, recommends). relation_op(at, hashlist, recommends). relation_op(at,treelist, satisfied). relation_op(sort, linkedlist, satisfied). relation_op(sort, treelist, satisfied). relation_op(sort, hashlist, unsupported). %static analysis: var(a).var(tmp2). var(b). var(tmp3). var_connection(a, tmp2). bind_var_op(tmp2, seqaccess). var_connection(tmp2, b, ct_inherits). var_connection(b, tmp3). bind_var_op(tmp3, seqaccess). %domain rules: impl_fulfill(OP, IMPL, SCORE):- relation_op(OP, IMPL, RL), relation_score(RL, SCORE), operation(OP), implementation(IMPL), RL!=unsupported. impl_not_fulfill(OP, IMPL):- relation_op(OP, IMPL, unsupported). %reasoning rules: { var_connection(VAR_FROM, VAR_TO, CT):connection_type(CT) }1 :- var_connection(VAR_FROM, VAR_TO). var_cluster_root(VAR) :- {var_connection(VAR_F, VAR, ct_inherits): var(VAR_F)} 0, var(VAR). var_cluster(VAR0, VAR_TO) :- var_connection(VAR0, VAR_TO, ct_inherits), var_cluster_root(VAR0). var_cluster(VAR0, VAR_TO2) :- var_connection(VAR_TO1, VAR_TO2, ct_inherits), var_cluster(VAR0, VAR_TO1). var_cluster(VAR0, VAR0):- var_cluster_root(VAR0). impl_fulfill_cluster(VAR0, OP, IMPL, SCORE) :- var_cluster(VAR0, VAR_ANY), bind_var_op(VAR_ANY, OP), impl_fulfill(OP, IMPL, SCORE), var_cluster_root(VAR0). impl_not_fulfill_cluster(VAR0, IMPL):-var_cluster(VAR0, VAR_ANY), bind_var_op(VAR_ANY, OP), impl_not_fulfill(OP, IMPL), var_cluster_root(VAR0). bind_var_impl(VAR0, IMPL, SCORE_RESULT) :- SCORE_RESULT = #sum[impl_fulfill_cluster(VAR0, _, IMPL, SCORE) = SCORE], {impl_not_fulfill_cluster(VAR0, IMPL)}0, var_cluster_root(VAR0), implementation(IMPL). %pretty output: #hide. #show chosen_impl/2. - %#show bind_var_impl/3. - %#show var_cluster_owner/1. - %#show var_connection/3. - %#show bind_var_op/2. + #show bind_var_impl/3. + #show var_cluster_owner/1. + #show var_connection/3. + #show bind_var_op/2. diff --git a/problems/test.lp b/problems/test.lp new file mode 100644 index 0000000..8c8a729 --- /dev/null +++ b/problems/test.lp @@ -0,0 +1,12 @@ +% p(1..3). q(2..4). +% { r(X): p(X), r(X): q(X) }. +% s :- #sum { r(X)=X: p(X): q(X) } 1. + +%p(1..50). +%count(X, Y):- Y = #sum {Z, Z: p(Z), Z >= X}, p(X). + +p(1..3). +2 {q(X) : p(X)}. +q(2). +:- not q(3). +:~ p(X), not q(X).[X] \ No newline at end of file diff --git a/problems/unsafe-code.lp b/problems/unsafe-code.lp new file mode 100644 index 0000000..82d0b44 --- /dev/null +++ b/problems/unsafe-code.lp @@ -0,0 +1,10 @@ +%Static analysis: CFG +function(testfunc3) . +function(testfunc2) . +call(testfunc2, testfunc3) . + +%Function tags: +tag(testfunc3, unsafe). +%tag(testfunc2, unsafe). + +:- call(X, Y), tag(Y, unsafe), not tag(X, unsafe), function(X), function(Y). \ No newline at end of file diff --git a/project/diploma-doc.doc b/project/diploma-doc.doc deleted file mode 100644 index 00d6285..0000000 Binary files a/project/diploma-doc.doc and /dev/null differ diff --git a/project/diploma.doc b/project/diploma.doc index e10e822..869f589 100644 Binary files a/project/diploma.doc and b/project/diploma.doc differ diff --git a/project/diploma.odt b/project/diploma.odt deleted file mode 100644 index e20fd80..0000000 Binary files a/project/diploma.odt and /dev/null differ diff --git a/project/draft.odt b/project/draft.odt index 26cd7ca..422f2ae 100644 Binary files a/project/draft.odt and b/project/draft.odt differ diff --git a/scripts/input.xreate b/scripts/input.xreate index 679b16f..22294b3 100644 --- a/scripts/input.xreate +++ b/scripts/input.xreate @@ -1,16 +1,45 @@ + +/* +//unsafe code propagation rule +rule: (X: function, Y: function) +case X calls Y + { + warning Y has unsafe --> X has unsafe + message format("function A should not call unsafe code B", X as A, Y as B) + } + +*/ + +testfunc3 = function: (a: num, b: num)->num , unsafe //function tags list +{ + x = a+b: num; + y = a - b: num; + + (x + y) / 2; +} + +testfunc2 = function: (a: num)->bool // because of testfunc3 marked as unsafe code, + // testfunc2 should be marked so too +{ + b = testfunc3(a+1, a-1): num; + (b==0); +} + +/* find6 = function: bool { x = [1, 2, 3, 4, 5, 6, 7]: [num]; //эффективная инициализация y = map (x) [el]-> {2 * el}; exists(y, 12); } exists = function: (list:[a], el: a)->bool { acc: bool; acc = reduce(list, false) [el, acc] -> { acc = acc & (el == e): saturated(true); } } +*/ diff --git a/src/main/java/org/xreate/ASTNode.java b/src/main/java/org/xreate/ASTNode.java new file mode 100644 index 0000000..02b1e07 --- /dev/null +++ b/src/main/java/org/xreate/ASTNode.java @@ -0,0 +1,89 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.xreate; + +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +public class ASTNode{ + public ASTNode acceptComputableVisitor(ComputableAnalysis visitor) throws NoSuchMethodException, IllegalAccessException, Throwable{ + Method compute = visitor.getClass().getDeclaredMethod("ifComputable", this.getClass()); + + ASTNode v = (ASTNode) compute.invoke(visitor, this); + + return new ASTValue(0); + } +} + +class ASTAssignment extends ASTNode{ + public ASTVar var; + public ASTExpression value; +} + +class ASTExpression extends ASTNode{ + ListMultimap representation; + + public List getUsedVars(){ + return Lists.newArrayList(); //stub + } + + + public ASTNode eval(Map substitutions) + {return new ASTValue(0);} //stub + +} + +class ASTFunction extends ASTNode{ + String representation; + int fpcount; //formal parameters count +} + + +class ASTValue extends ASTExpression{ + public int representation; + + public ASTValue(int source){ + representation = source; + } +} + +class ASTVar extends ASTExpression{ + int id; + + public static Map substitute(List vars) + {return Maps.newHashMap();} + + public ASTVar(){ + id =0; + } +} + + + + +/* + * fargs - formal args + * + * + * + */ + +/* + * + * + * block (fargs, body-list) + * expression -: atom + * atom :- val, var + * assignment + * sequence + * + */ + diff --git a/src/main/java/org/xreate/App.java b/src/main/java/org/xreate/App.java new file mode 100644 index 0000000..ba10572 --- /dev/null +++ b/src/main/java/org/xreate/App.java @@ -0,0 +1,10 @@ +package org.xreate; + +public class App +{ + public static void main( String[] args ) throws NoSuchMethodException, IllegalAccessException, Throwable { + TestRunner2 runner = new TestRunner2(); + + runner.constructAndRun(); + } +} diff --git a/src/main/java/org/xreate/ComputableAnalisys.java b/src/main/java/org/xreate/ComputableAnalisys.java new file mode 100644 index 0000000..d64a7cc --- /dev/null +++ b/src/main/java/org/xreate/ComputableAnalisys.java @@ -0,0 +1,66 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.xreate; + +import java.util.List; +import java.util.Map; + +/** + * + * @author pgess + */ +class ComputableAnalysis{ + protected Map computedStore; + + public ASTNode ifComputable (ASTNode node){ + return node; + } + + /* + * null - если не переменная не вычислима + */ + public ASTNode ifComputable (ASTVar node){ + + return computedStore.get(node); + + /* + Optional value = Optional.of (); + return false; + */ + } + + /* + * null - если выражение не вычислимо + */ + /* + public ASTNode ifComputable (ASTExpression node){ + List vars = node.getUsedVars(); + + Map subs = ASTVar.substitute(vars); + + if (computedStore.keySet().containsAll(vars)){ + + //computedStore. + ASTNode result = node.eval(subs); + return result; + } + + + return null; + } + + */ + + public ASTNode ifComputable (ASTAssignment node) throws NoSuchMethodException, IllegalAccessException, Throwable{ + + ASTNode value = node.value.acceptComputableVisitor(this); + + if (value != null){ + computedStore.put(node.var, value); + } + + return value; + } +} \ No newline at end of file diff --git a/src/main/java/org/xreate/SemanticAnalysis.java b/src/main/java/org/xreate/SemanticAnalysis.java new file mode 100644 index 0000000..a411db6 --- /dev/null +++ b/src/main/java/org/xreate/SemanticAnalysis.java @@ -0,0 +1,15 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.xreate; + +import java.util.Map; + +/** + * + * @author pgess + */ +public class SemanticAnalysis { + public Map opcodes; +} diff --git a/src/main/java/org/xreate/TestRunner2.java b/src/main/java/org/xreate/TestRunner2.java new file mode 100644 index 0000000..5c519c4 --- /dev/null +++ b/src/main/java/org/xreate/TestRunner2.java @@ -0,0 +1,114 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.xreate; + +import com.google.common.collect.Maps; +import java.math.BigInteger; +import org.jllvm.*; +import org.jllvm.bindings.*; +import org.junit.Test; +/** + * + * @author pgess + */ +public class TestRunner2 { + + protected LLVMModule module; + + public void setModule(LLVMModule module){ + this.module = module; + } + + public void constructAndRun() throws Exception{ + boolean isNative = LLVMTargetData.initializeNativeTarget(); + module = new LLVMModule("xreate_first_test"); + + LLVMValue func = constructBody(); + runBody(func); + } + + public LLVMValue constructBody() throws Exception{ + LLVMConstantInteger a = LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, 10, true); + LLVMConstantInteger b = LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, 20, true); + LLVMConstantInteger c = LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, 3, true); + LLVMInstructionBuilder builder = new LLVMInstructionBuilder(); + + LLVMInstruction i = new LLVMAddInstruction(builder, a, b, false, "a+b"); + i = new LLVMMultiplyInstruction(builder, c, i, false, "c * (a + b)"); + + //LLVMModule module; // module = + LLVMFunctionType func_test1_type; + + + + LLVMType[] types = new LLVMType[0]; + //types[0] = new LLVMVoidType(); + + func_test1_type = new LLVMFunctionType(LLVMIntegerType.i32, types, false); + + LLVMFunction test1 = new LLVMFunction(module, "test1", func_test1_type); + LLVMBasicBlock entry = test1.appendBasicBlock("entry"); + builder.positionBuilderAtEnd(entry); + + new LLVMReturnInstruction(builder, i); + + SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1); + int x = Analysis.LLVMVerifyFunction(test1.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction); + x = Analysis.LLVMVerifyModule(module.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction, outerrs); + + ExecutionEngine.delete_StringArray(outerrs); outerrs = null; + + return test1; + } + + public void runBody(LLVMValue test1 ){ + + + SWIGTYPE_p_p_LLVMOpaqueExecutionEngine engines = ExecutionEngine.new_LLVMExecutionEngineRefArray(1); + SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1); + int success = ExecutionEngine.LLVMCreateJITCompilerForModule(engines,module.getInstance(), 0, outerrs); + String outerr = ExecutionEngine.StringArray_getitem(outerrs,0); + ExecutionEngine.delete_StringArray(outerrs); outerrs = null; + SWIGTYPE_p_LLVMOpaqueExecutionEngine instance_ = ExecutionEngine.LLVMExecutionEngineRefArray_getitem(engines,0); + ExecutionEngine.delete_LLVMExecutionEngineRefArray(engines); engines = null; + + /* + LLVMJitCompiler engine = new LLVMJitCompiler(module); + + LLVMGenericValue res = engine.runFunction(test1, args); + + // + BigInteger result = ExecutionEngine.LLVMGenericValueToInt(res.getInstance(), 0); + */ + + LLVMGenericValue[] args = new LLVMGenericValue[0]; + + + SWIGTYPE_p_p_LLVMOpaqueGenericValue arg_array = ExecutionEngine.new_LLVMGenericValueRefArray(args.length); + for(int ii=0;ii parameters = Lists.newArrayList(); + + protected Map index; + + public ASTLispNode(String c){ + caption = c; + } + + public ASTLispNode add(ASTLispNode node){ + parameters.add(node); + return node; + } + + public ASTLispNode get(String node){ + if (null == index){ + buildIndex(); + } + + return index.get(node); + } + + protected void buildIndex(){ + index = Maps.newHashMap(); + + for (ASTLispNode param : parameters){ + index.put(param.caption, param); + } + } +} +class ASTLispConstantNode extends ASTLispNode{ + public int value; + + public ASTLispConstantNode(String c) { + super(c); + + value = Integer.parseInt(c); + } +} + + +class NodeFunctionVarsList { + ASTLispNode node; + + NodeFunctionVarsList(ASTLispNode node){ + this.node = node; + } + + String[] getVarNames(){ + int size = node.parameters.size(); + + String[] result = new String[size]; + + for(int i=0; i htable; + static Map ttable; + + public Map opcodes = Maps.newLinkedHashMap(); + public Map functions = Maps.newLinkedHashMap(); + + + protected LLVMInstructionBuilder builder = new LLVMInstructionBuilder(); + protected LLVMModule module = new LLVMModule("script"); + + //"/private/prg/code/xreate/scripts/opcode.li" + public void run(String filename) throws IOException, RecognitionException, Exception{ + ANTLRStringStream in = new ANTLRFileStream(filename); + + Lexer l = new LispLexer(in); + CommonTokenStream tokens = new CommonTokenStream(l); + + LispParser p = new LispParser(tokens); + + while (true){ + ASTLispNode node = p.statement(null); + + handle(node); + } + + } + + public void opcodeDef(ASTLispNode node){ + ArrayList params = node.parameters; + + opcodes.put(params.get(0).caption, params.get(1).caption); + } + + public void functionDef(ASTLispNode node) throws Exception{ + ArrayList nodes_vars = node.get("vars-list").parameters; + + int nsize = nodes_vars.size(); + LLVMType[] arg_types = new LLVMType[nsize]; + + for (int i=0; i() + .put("opcode", "opcodeDef") + .put("function", "functionDef") + .put ("calculate", "calculate") + .put("main", "main") + .build(); + + /* + * Types Table - хранит информацию о соответствии типов + */ + ttable = new ImmutableMap.Builder() + .put ("i32", LLVMIntegerType.i32) + .put ("i16", LLVMIntegerType.i16) + .put ("i8", LLVMIntegerType.i8) + .build(); + + + } + + class Evaluator{ + Map arguments; + + public Evaluator(String[] names, LLVMValue[] values) { + + int size = names.length; + arguments = Maps.newHashMapWithExpectedSize(size); + + for(int i=0; i= '\t' && LA1_0 <= '\n')||(LA1_0 >= '\f' && LA1_0 <= '\r')||LA1_0==' ') ) { + alt1=1; + } + + + switch (alt1) { + case 1 : + // /private/prg/code/xreate/antlr/lisp.g: + { + if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n')||(input.LA(1) >= '\f' && input.LA(1) <= '\r')||input.LA(1)==' ' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + + + } + break; + + default : + if ( cnt1 >= 1 ) break loop1; + EarlyExitException eee = + new EarlyExitException(1, input); + throw eee; + } + cnt1++; + } while (true); + + + _channel = HIDDEN; + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "WHITESPACE" + + // $ANTLR start "WORD" + public final void mWORD() throws RecognitionException { + try { + int _type = WORD; + int _channel = DEFAULT_TOKEN_CHANNEL; + // /private/prg/code/xreate/antlr/lisp.g:5:6: ( ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )+ ) + // /private/prg/code/xreate/antlr/lisp.g:5:8: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )+ + { + // /private/prg/code/xreate/antlr/lisp.g:5:8: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )+ + int cnt2=0; + loop2: + do { + int alt2=2; + int LA2_0 = input.LA(1); + + if ( ((LA2_0 >= '0' && LA2_0 <= '9')||(LA2_0 >= 'A' && LA2_0 <= 'Z')||LA2_0=='_'||input.LA(1)=='-'||(LA2_0 >= 'a' && LA2_0 <= 'z')) ) { + alt2=1; + } + + + switch (alt2) { + case 1 : + // /private/prg/code/xreate/antlr/lisp.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9')||(input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_' ||input.LA(1)=='-' ||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + + + } + break; + + default : + if ( cnt2 >= 1 ) break loop2; + EarlyExitException eee = + new EarlyExitException(2, input); + throw eee; + } + cnt2++; + } while (true); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "WORD" + + public void mTokens() throws RecognitionException { + // /private/prg/code/xreate/antlr/lisp.g:1:8: ( T__6 | T__7 | T__8 | WHITESPACE | WORD ) + int alt3=5; + switch ( input.LA(1) ) { + case '(': + { + alt3=1; + } + break; + case ')': + { + alt3=2; + } + break; + case ',': + { + alt3=3; + } + break; + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': + { + alt3=4; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case '-': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + { + alt3=5; + } + break; + default: + NoViableAltException nvae = + new NoViableAltException("", 3, 0, input); + + throw nvae; + + } + + switch (alt3) { + case 1 : + // /private/prg/code/xreate/antlr/lisp.g:1:10: T__6 + { + mT__6(); + + + } + break; + case 2 : + // /private/prg/code/xreate/antlr/lisp.g:1:15: T__7 + { + mT__7(); + + + } + break; + case 3 : + // /private/prg/code/xreate/antlr/lisp.g:1:20: T__8 + { + mT__8(); + + + } + break; + case 4 : + // /private/prg/code/xreate/antlr/lisp.g:1:25: WHITESPACE + { + mWHITESPACE(); + + + } + break; + case 5 : + // /private/prg/code/xreate/antlr/lisp.g:1:36: WORD + { + mWORD(); + + + } + break; + + } + + } + + + + +} \ No newline at end of file diff --git a/src/main/java/org/xreate/grammatic/lisp/LispParser.java b/src/main/java/org/xreate/grammatic/lisp/LispParser.java new file mode 100644 index 0000000..19d8dea --- /dev/null +++ b/src/main/java/org/xreate/grammatic/lisp/LispParser.java @@ -0,0 +1,145 @@ +package org.xreate.grammatic.lisp; + +// $ANTLR 3.4 /private/prg/code/xreate/antlr/lisp.g 2012-04-07 17:57:03 + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked"}) +public class LispParser extends Parser { + public static final String[] tokenNames = new String[] { + "", "", "", "", "WHITESPACE", "WORD", "'('", "')'", "','" + }; + + public static final int EOF=-1; + public static final int T__6=6; + public static final int T__7=7; + public static final int T__8=8; + public static final int WHITESPACE=4; + public static final int WORD=5; + + // delegates + public Parser[] getDelegates() { + return new Parser[] {}; + } + + // delegators + + + public LispParser(TokenStream input) { + this(input, new RecognizerSharedState()); + } + public LispParser(TokenStream input, RecognizerSharedState state) { + super(input, state); + } + + public String[] getTokenNames() { return LispParser.tokenNames; } + public String getGrammarFileName() { return "/private/prg/code/xreate/antlr/lisp.g"; } + + + + // $ANTLR start "statement" + // /private/prg/code/xreate/antlr/lisp.g:7:1: statement : WORD ( '(' statement ( ',' statement )* ')' )? ; + public final ASTLispNode statement(ASTLispNode node) throws RecognitionException { + try { + // /private/prg/code/xreate/antlr/lisp.g:8:2: ( WORD ( '(' statement ( ',' statement )* ')' )? ) + // /private/prg/code/xreate/antlr/lisp.g:8:4: WORD ( '(' statement ( ',' statement )* ')' )? + { + CommonToken token = (CommonToken) match(input,WORD,FOLLOW_WORD_in_statement71); + + String text = token.getText(); + ASTLispNode nodeChild = ('0' <= text.charAt(0) && '9'>= text.charAt(0))? new ASTLispConstantNode(text) : new ASTLispNode(text); + if (node != null){ + node.add(nodeChild); + } + node = nodeChild; + + // /private/prg/code/xreate/antlr/lisp.g:8:9: ( '(' statement ( ',' statement )* ')' )? + int alt2=2; + int LA2_0 = input.LA(1); + + if ( (LA2_0==6) ) { + alt2=1; + } + switch (alt2) { + case 1 : + // /private/prg/code/xreate/antlr/lisp.g:8:10: '(' statement ( ',' statement )* ')' + { + match(input,6,FOLLOW_6_in_statement74); + + pushFollow(FOLLOW_statement_in_statement76); + statement(node); + + state._fsp--; + + + // /private/prg/code/xreate/antlr/lisp.g:8:24: ( ',' statement )* + loop1: + do { + int alt1=2; + int LA1_0 = input.LA(1); + + if ( (LA1_0==8) ) { + alt1=1; + } + + + switch (alt1) { + case 1 : + // /private/prg/code/xreate/antlr/lisp.g:8:25: ',' statement + { + match(input,8,FOLLOW_8_in_statement79); + + pushFollow(FOLLOW_statement_in_statement81); + statement(node); + + state._fsp--; + + + } + break; + + default : + break loop1; + } + } while (true); + + + match(input,7,FOLLOW_7_in_statement85); + + } + break; + + } + + + } + + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + } + + finally { + // do for sure before leaving + } + return node; + } + // $ANTLR end "statement" + + // Delegated rules + + + + + public static final BitSet FOLLOW_WORD_in_statement71 = new BitSet(new long[]{0x0000000000000042L}); + public static final BitSet FOLLOW_6_in_statement74 = new BitSet(new long[]{0x0000000000000020L}); + public static final BitSet FOLLOW_statement_in_statement76 = new BitSet(new long[]{0x0000000000000180L}); + public static final BitSet FOLLOW_8_in_statement79 = new BitSet(new long[]{0x0000000000000020L}); + public static final BitSet FOLLOW_statement_in_statement81 = new BitSet(new long[]{0x0000000000000180L}); + public static final BitSet FOLLOW_7_in_statement85 = new BitSet(new long[]{0x0000000000000002L}); + +} \ No newline at end of file diff --git a/src/test/java/org/xreate/ASTTest1.java b/src/test/java/org/xreate/ASTTest1.java new file mode 100644 index 0000000..c30c808 --- /dev/null +++ b/src/test/java/org/xreate/ASTTest1.java @@ -0,0 +1,55 @@ +package org.xreate; + +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Maps; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class ASTTest1 + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public ASTTest1( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( ASTTest1.class ); + } + + /** + * Rigourous Test :-) + */ + public void testAST1() throws NoSuchMethodException, IllegalAccessException, Throwable + { + ASTVar x = new ASTVar(); + ASTValue y = new ASTValue(10); + ASTAssignment as = new ASTAssignment(); + + as.var = x; + as.value = y; + ComputableAnalysis analysis = new ComputableAnalysis(); + ASTNode result = as.acceptComputableVisitor(analysis); + + assertTrue( true ); + } +} + + + diff --git a/src/test/java/org/xreate/LispTest.java b/src/test/java/org/xreate/LispTest.java new file mode 100644 index 0000000..e9f7bc1 --- /dev/null +++ b/src/test/java/org/xreate/LispTest.java @@ -0,0 +1,69 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.xreate; + +import java.io.IOException; +import junit.framework.TestCase; +import org.antlr.runtime.*; +import org.junit.Ignore; +import org.xreate.grammatic.lisp.ASTLispNode; +import org.xreate.grammatic.lisp.LispLexer; +import org.xreate.grammatic.lisp.LispParser; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.xreate.grammatic.lisp.LispInterpreter; +/** + * + * @author pgess + */ +public class LispTest { + static int z; + + @Ignore + @Test + public void test1() throws RecognitionException{ + assertTrue(true); + + ANTLRStringStream in = new ANTLRStringStream("aa(bb, cc(dd, ee))"); + + Lexer l = new LispLexer(in); + CommonTokenStream tokens = new CommonTokenStream(l); + + LispParser p = new LispParser(tokens); + + ASTLispNode node = p.statement(null); + + int x = 0; + } + + @Ignore + @Test + public void test2() throws IOException, RecognitionException{ + ANTLRStringStream in = new ANTLRFileStream("/private/prg/code/xreate/scripts/opcode.li"); + + Lexer l = new LispLexer(in); + CommonTokenStream tokens = new CommonTokenStream(l); + + LispParser p = new LispParser(tokens); + + ASTLispNode node = p.statement(null); + + int x = 0; + } + + @Test + public void test3() throws Exception{ + LispInterpreter lisp = new LispInterpreter(); + + lisp.run("/private/prg/code/xreate/scripts/opcode.li"); + + //assertEquals(answer, 100); + } + + static { + System.loadLibrary("jllvm"); + } +}