No OneTemporary

File Metadata

Created
Sat, Mar 14, 5:09 AM
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 <wchar.h>
#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<Type_t>(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<Identifier_t>(i1->val)));
+ params.add(Expression(Atom<Identifier_t>(i2->val)));
+ e = MetaExpression(Operator::CALL, Atom<Identifier_t>(infix->val), params);
+ } else if (la->kind == _ident) {
+ Ident(i1);
+ e = MetaExpression(Atom<Identifier_t>(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<Identifier_t>(name));
+ Expect(_lparen);
+ if (StartOf(3)) {
+ CalleeParams(e);
+ }
+ Expect(_rparen);
+ } else if (la->kind == _ident) {
Ident(name);
e = Expression(Atom<Identifier_t>(name));
- } else if (la->kind == 2) {
+ } else if (la->kind == _number) {
Get();
e = Expression(Atom<Number_t>(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<typename T>
struct ParserInitExistsRecognizer {
template<typename U, void (U::*)() = &U::Init>
struct ExistsIfInitIsDefinedMarker{};
struct InitIsMissingType {
char dummy1;
};
struct InitExistsType {
char dummy1; char dummy2;
};
// exists always
template<typename U>
static InitIsMissingType is_here(...);
// exist only if ExistsIfInitIsDefinedMarker is defined
template<typename U>
static InitExistsType is_here(ExistsIfInitIsDefinedMarker<U>*);
enum { InitExists = (sizeof(is_here<T>(NULL)) == sizeof(InitExistsType)) };
};
template<typename T>
struct ParserDestroyExistsRecognizer {
template<typename U, void (U::*)() = &U::Destroy>
struct ExistsIfDestroyIsDefinedMarker{};
struct DestroyIsMissingType {
char dummy1;
};
struct DestroyExistsType {
char dummy1; char dummy2;
};
// exists always
template<typename U>
static DestroyIsMissingType is_here(...);
// exist only if ExistsIfDestroyIsDefinedMarker is defined
template<typename U>
static DestroyExistsType is_here(ExistsIfDestroyIsDefinedMarker<U>*);
enum { DestroyExists = (sizeof(is_here<T>(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<typename T, bool = ParserInitExistsRecognizer<T>::InitExists>
struct ParserInitCaller {
static void CallInit(T *t) {
// nothing to do
}
};
// True case of the ParserInitCaller, gets used if the Init method exists
template<typename T>
struct ParserInitCaller<T, true> {
static void CallInit(T *t) {
t->Init();
}
};
// Generic case of the ParserDestroyCaller, gets used if the Destroy method is missing
template<typename T, bool = ParserDestroyExistsRecognizer<T>::DestroyExists>
struct ParserDestroyCaller {
static void CallDestroy(T *t) {
// nothing to do
}
};
// True case of the ParserDestroyCaller, gets used if the Destroy method exists
template<typename T>
struct ParserDestroyCaller<T, true> {
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<Parser>::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<Parser>::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 <string>
#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 <memory.h>
#include <string.h>
#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 <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
// io.h and fcntl are used to ensure binary read from streams on windows
#if _MSC_VER >= 1300
#include <io.h>
#include <fcntl.h>
#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 <string>
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<std::wstring& name>
= ident (. name = t->val; .).
FDecl<> = (. std::wstring fname; Expression fbody; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut; .)
Ident<fname> '=' "function" ':' (. Function f = Function(fname); .)
( Type<typOut> (. f.setReturnType(typOut); .)
| '('Ident<varname> ':' Type<typIn> (. f.addArg(varname, typIn); .)
{',' Ident<varname> ':' Type<typIn> (. f.addArg(varname, typIn);.)
-} ')' )
-
-'{' {VDecl<f> ';' }
-Expr<fbody> '}' (. f.setBody(fbody); .) .
+} ')' "->" Type<typOut> (. f.setReturnType(typOut); .)
+{',' FnTag<f> }
+) '{' {VDecl<f> ';' }
+Expr<fbody> ';' '}' (. f.setBody(fbody); root.add(f); .) .
TypeTerm<TypeAtom& typ> = ("string" | "int" | "num" | "float" | "bool") (. typ = Atom<Type_t>(t->val); .) .
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypeAtom typ3; .)
('[' Type<typ2> ']' (. typ = TypeAnnotation(TypeOperator::LIST, typ2); .)
| TypeTerm<typ3> (. typ = TypeAnnotation(typ3); .)
) .
VDecl<Function& f> = (. std::wstring vname; Expression e; TypeAnnotation typ; .)
Ident<vname> '='
(Expr<e> ':' Type<typ> (. f.addDeclaration(vname, typ, e); .)
|ListLiteral<e> ':' Type<typ> (. f.addListDeclaration(vname, typ, e); .)
-) ';'.
+).
+ /*============================ METAPROGRAMMING ===============================*/
+
+FnTag<Function& f> = (.std::wstring tag; TagModifier mod = TagModifier::NONE; .)
+Ident<tag>
+['-' TagMod<mod>] (. f.addTag(tag, mod); .).
+
+TagMod<TagModifier& mod> =
+( "assert" (. mod = TagModifier::ASSERT; .)
+ | "require" (. mod = TagModifier::REQUIRE; .)
+).
+
+RuleDecl<> =
+"rule" ':' (. RuleArguments args; RuleGuards guards; RuleBody body; DomainAnnotation typ; .)
+'(' Ident<arg> ':' Domain<typ> (. args.add(arg, typ); .)
+{',' Ident<arg> ':'Domain<typ> (. args.add(arg, typ); .)
+} ')'
+["case" RGuard<guards> {',' RGuard<guards>}]
+ (. .)
+'{' RBody<args, guards> '}' .
+
+Domain<DomainAnnotation& dom> =
+(
+ "function" (. dom = DomainAnnotation::FUNCTION; .)
+ | "variable" (. dom = DomainAnnotation::VARIABLE; .)
+).
+
+RGuard<RuleGuards& guards>= (. MetaExpression e; .)
+MetaExpr<e> (. guards.add(e); .).
+
+MetaExpr<MetaExpression& e>=
+MetaExpr2<e>
+[MetaOp<op> MetaExpr2<e2> (. MetaParameters params;
+ params.add(e);
+ params.add(e2);
+ e = MetaExpression(op, params); .)
+].
+
+MetaExpr2<MetaExpression& e>= (. std::wstring i1, i2, infix; MetaParameters params; .)
+( IF(checkParametersList()) Ident<i1> '(' [ MetaParams<params> ] ')'
+ (. e = MetaExpression(Operator::CALL, i1, params); .)
+| IF(checkInfix()) Ident<i1> Ident<infix> Ident<i2>
+ (. params.add(Expression(Atom<Identifier_t>(i1->val)));
+ params.add(Expression(Atom<Identifier_t>(i2->val)));
+ e = MetaExpression(Operator::CALL, Atom<Identifier_t>(infix->val), params); .)
+| Ident<i1> (. e = MetaExpression(Atom<Identifier_t>(i1->val)); .)
+| '(' MetaExpr<e> ')'
+).
+
+MetaParams<MetaParameters& params> = (. MetaExpr e; .)
+MetaExpr<e> (. params.add(e); .)
+{',' MetaExpr<e> (. params.add(e).)
+}.
+
+RBody<RuleBody& body> = (. MetaExpr e; .)
+ "warning" MetaExpr<e> ["message" string] .
+
+MetaOp< Operator& op> =
+ '-' '>' (. op = OPERATOR::IMPL; .)
+.
+
+
+
-ListLiteral<Expression& e> = (. Expression e2; .)
-'['
-(']' ';' (. e = Expression(Operator::LIST, Expression()); .)
-| Expr<e2> (. e = Expression(Operator::LIST, e2); .)
-{',' Expr<e2> (. e.addArg(e2); .)
-}
-']'
-';').
/*============================ Expressions ===============================*/
+ListLiteral<Expression& e> = (. Expression e2; .)
+'[' (. e = Expression(Operator::LIST, Expression()); .)
+[ Expr<e2> (. e.addArg(e2); .)
+{',' Expr<e2> (. 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<Identifier_t>(name)); .)
- | number (. e = Expression(Atom<Number_t>(t->val)); .)
- | '-' Factor< e> (. e = Expression(Operator::NEG, e); .)
+ (IF (checkParametersList()) Ident< name>
+ (. e = Expression(Operator::CALL, Atom<Identifier_t>(name)); .)
+ '(' [CalleeParams<e>] ')'
+ | Ident< name> (. e = Expression(Atom<Identifier_t>(name)); .)
+
+ | number (. e = Expression(Atom<Number_t>(t->val)); .)
+ | '-' Factor< e> (. e = Expression(Operator::NEG, e); .)
+ | '(' Expr<e> ')'
).
-
+CalleeParams<Expression& e> = (. Expression e2; .)
+ Expr<e2> (. e.addArg(e2); .)
+ {',' Expr<e2> (. 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 <ast.h>
+
+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<llvm::Value*> 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<llvm::Type*> 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<llvm::Function>(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 <stdexcept>
+#include <iostream>
+#include <QString>
+#include <clasplayer.h>
+
using namespace std;
TypeAnnotation::TypeAnnotation()
{}
TypeAnnotation::TypeAnnotation(const Atom<Type_t> &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_t>& number)
-: state(NUMBER), __op(Operator::NONE), __valueD(number.get())
+: __state(NUMBER), __op(Operator::NONE), __valueD(number.get())
{
}
Expression::Expression(const Atom<Identifier_t> &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<Expression> 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<llvm::Value*> args;
- args.reserve(operands.size()-1);
- for(int i=1; i<operands.size(); ++i)
- {
- args.push_back(operands[i].compile(l, f));
- }
-
- return l.builder.CreateCall(callee, args, VARNAME("tmp_call"));
- }
- break;
-
-
- case Operator::NONE:
- switch (state)
- {
- case IDENT:
- {
- std::string vname = operands[0].__valueS;
- assert(f->__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()<<endl;
+ __tags.push_back(std::make_pair(name, amod));
+}
+
+const std::vector<std::pair<std::string, AnnotationModifier>>&
+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<llvm::Type*> 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<llvm::Function>(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 <vector>
#include <stdlib.h>
#include <string>
#include "llvmlayer.h"
struct Identifier_t {};
struct Number_t {};
struct Type_t {};
template<typename A>
class Atom{
};
template<> class Atom<Identifier_t>
{
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<Number_t>
{
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<Type_t>
{
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<Type_t> TypeAtom;
enum class TypeOperator{LIST};
class TypeAnnotation
{
public:
TypeAnnotation (const Atom<Type_t>& 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<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& 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<Expression> 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<std::pair<std::string, DomainAnnotation>>
+{
+public:
+ void add(std::string&& name, DomainAnnotation typ);
+};
+
+class RuleGuards: public std::vector<Expression>
+{
+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<vid, TypeAnnotation> VariableDefinition;
-typedef std::pair<vid, Expression> VariableDeclaration;
+typedef std::pair<VID, TypeAnnotation> VariableDefinition;
+typedef std::pair<VID, Expression> 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<std::pair<std::string, AnnotationModifier>>& 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<std::string> __args;
+ std::vector<std::pair<std::string, AnnotationModifier>> __tags;
std::map<VariableDefinition::first_type, VariableDefinition::second_type> __definitions;
std::map<VariableDeclaration::first_type, VariableDeclaration::second_type> __declarations;
- std::map<std::string, vid> __vartable;
+ std::map<std::string, VID> __vartable;
Expression __body;
llvm::Function* __raw;
- std::map<vid,llvm::Value*> __rawVars;
+ std::map<VID,llvm::Value*> __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<Function> __functions;
-
- std::map<std::string, llvm::Function*> __rawFunctions;
+ std::map<std::string, FID> __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 <clasp/program_builder.h> // for defining logic programs
+#include <clasp/unfounded_check.h> // unfounded set checkers
+#include <clasp/model_enumerators.h> // for enumerating answer sets
+#include <clasp/clasp_facade.h>
+
+#include <clingocontrol.hh>
+
+#include <iostream>
+#include <clingo_lib.hh>
+#include <QString>
+#include <QStringList>
+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<QStringList>&& 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<end; ++expr1I)
+ {
+ if (list.size() == 0 ) continue;
+
+ StringList::const_iterator expr2I=list.begin();
+ for(int expr2No=0, size = list.size()-1; expr2No < size; ++expr2No, ++expr1I)
+ result.append(QString("%1, %2").arg(*expr1I).arg(*expr2I));
+
+ *expr1I = QString("%1, %2").arg(*expr1I).arg(*expr2I);
+ }
+ }
+
+ return result;
+}
+
+void
+ClaspLayer::addCFGData(CFGraph &&graph)
+{
+ ostream& cout = __partGeneral;
+
+ cout <<endl<< "%\t\tStatic analysis: CFG" << endl;
+
+ for (const std::pair<FID, FID>& 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()<<endl;
+ }
+}
+
+void
+ClaspLayer::addFunctionTags(const std::string& function, const std::vector<Tag>& tags)
+{
+ ostream& cout = __partTags;
+
+ cout << (QString("function(%1) .").arg(function.c_str())).toStdString()<<std::endl;
+
+ int tagsCount=0;
+ for(Tag tag: tags)
+ {
+ cout << QString("tag(%1, %2).").arg(function.c_str()).arg(tag.first.c_str()).toStdString() << endl;
+ ++tagsCount;
+ }
+ if (tagsCount == 0)
+ {
+ cout << "%no tags at all" << endl;
+ }
+}
+
+void
+ClaspLayer::addRuleWarning(RuleWarning* rule)
+{
+ //__partGeneral << rule << endl;
+
+ std::QStringList domains;
+ std::transform(rule->__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<QStringList> 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 <string>
+#include <gringo/control.hh>
+#include <ast.h>
+
+typedef std::pair<std::string, AnnotationModifier> Tag;
+
+class CFGraph;
+
+class ClaspLayer
+{
+
+public:
+ ClaspLayer();
+
+ void addFunctionTags(const std::string& function, const std::vector<Tag>& 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<FID, FID> __relations;
+ std::map<FID, std::string> __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<Expression>(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<void*> __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 <iostream>
-#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<Function>(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 <QString>
+
+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<fcount; ++f)
+ {
+ const Function& func = __root.getFunctionById(f);
+ __graph.addNode(f, string(func.getName()));
+ process(f);
+ }
+
+ clasp.addCFGData(std::move(__graph));
+}
diff --git a/cpp/src/pass/cfgpass.h b/cpp/src/pass/cfgpass.h
new file mode 100644
index 0000000..aff1589
--- /dev/null
+++ b/cpp/src/pass/cfgpass.h
@@ -0,0 +1,25 @@
+// Control Flow Graph determination pass
+
+#ifndef CFGPASS_H
+#define CFGPASS_H
+
+#include "ast.h"
+#include <set>
+#include <iostream>
+#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 <QString>
+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 <iostream>
+#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 <memory>
-
-using namespace std;
-
-void testParser_1()
-{
- shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
- shared_ptr<Parser> 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 <memory>
+#include <iostream>
+#include "cfgpass.h"
+#include "clasplayer.h"
+#include "functiontagspass.h"
+#include <sstream>
+
+using namespace std;
+
+void testParser_1()
+{
+ shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
+ shared_ptr<Parser> 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> scanner(new Scanner(L"scripts/input.xreate"));
+ shared_ptr<Parser> 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 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.xreate</groupId>
+ <artifactId>xreate</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>xreate</name>
+ <url>http://maven.apache.org</url>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.10</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr</artifactId>
+ <version>3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr-runtime</artifactId>
+ <version>3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>11.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>javolution</groupId>
+ <artifactId>javolution</artifactId>
+ <version>5.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>jllvm</groupId>
+ <artifactId>jllvm</artifactId>
+ <version>2.8</version>
+ </dependency>
+ </dependencies>
+</project>
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 <ASTFunction, ASTExpression> representation;
+
+ public List<ASTVar> getUsedVars(){
+ return Lists.newArrayList(); //stub
+ }
+
+
+ public ASTNode eval(Map<ASTVar, ASTNode> 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<ASTVar, ASTValue> substitute(List<ASTVar> 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<ASTVar, ASTNode> computedStore;
+
+ public ASTNode ifComputable (ASTNode node){
+ return node;
+ }
+
+ /*
+ * null - если не переменная не вычислима
+ */
+ public ASTNode ifComputable (ASTVar node){
+
+ return computedStore.get(node);
+
+ /*
+ Optional<ASTValue> value = Optional.of ();
+ return false;
+ */
+ }
+
+ /*
+ * null - если выражение не вычислимо
+ */
+ /*
+ public ASTNode ifComputable (ASTExpression node){
+ List<ASTVar> vars = node.getUsedVars();
+
+ Map<ASTVar, ASTValue> 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<String, String> 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<args.length;ii++)
+ ExecutionEngine.LLVMGenericValueRefArray_setitem(arg_array,ii,args[ii].getInstance());
+
+ SWIGTYPE_p_LLVMOpaqueGenericValue res = ExecutionEngine.LLVMRunFunction(instance_,test1.getInstance(),args.length,arg_array);
+ ExecutionEngine.delete_LLVMGenericValueRefArray(arg_array);
+
+ BigInteger result = ExecutionEngine.LLVMGenericValueToInt(res, 0);
+ //LLVMGenericInt result = (LLVMGenericInt) new LLVMGenericValue(res);
+
+
+ /*
+ LLVMJitCompiler program = new LLVMJitCompiler (module);
+ LLVMGenericInt result = (LLVMGenericInt) program.runFunction(test1, new LLVMGenericValue[0]);
+ */
+
+
+ int r = result.intValue();
+
+ System.out.println(r);
+ }
+
+ static {
+ System.loadLibrary("jllvm");
+ }
+}
diff --git a/src/main/java/org/xreate/grammatic/lisp/ASTLispNode.java b/src/main/java/org/xreate/grammatic/lisp/ASTLispNode.java
new file mode 100644
index 0000000..561443f
--- /dev/null
+++ b/src/main/java/org/xreate/grammatic/lisp/ASTLispNode.java
@@ -0,0 +1,73 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.xreate.grammatic.lisp;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.util.ArrayList;
+import java.util.Map;
+
+
+public class ASTLispNode {
+ public String caption;
+ public ArrayList<ASTLispNode> parameters = Lists.newArrayList();
+
+ protected Map<String, ASTLispNode> 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<size; i++){
+ result[i] = node.parameters.get(i).get("name").parameters.get(0).caption;
+ }
+
+ return result;
+ }
+}
diff --git a/src/main/java/org/xreate/grammatic/lisp/LispInterpreter.java b/src/main/java/org/xreate/grammatic/lisp/LispInterpreter.java
new file mode 100644
index 0000000..56a77d3
--- /dev/null
+++ b/src/main/java/org/xreate/grammatic/lisp/LispInterpreter.java
@@ -0,0 +1,260 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.xreate.grammatic.lisp;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.antlr.runtime.*;
+import org.jllvm.*;
+import org.jllvm.bindings.*;
+import org.xreate.TestRunner2;
+
+/**
+ *
+ * @author pgess
+ */
+public class LispInterpreter {
+ static Map<String, String> htable;
+ static Map<String, LLVMType> ttable;
+
+ public Map<String, String> opcodes = Maps.newLinkedHashMap();
+ public Map<String, LLVMFunction> 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<ASTLispNode> params = node.parameters;
+
+ opcodes.put(params.get(0).caption, params.get(1).caption);
+ }
+
+ public void functionDef(ASTLispNode node) throws Exception{
+ ArrayList<ASTLispNode> nodes_vars = node.get("vars-list").parameters;
+
+ int nsize = nodes_vars.size();
+ LLVMType[] arg_types = new LLVMType[nsize];
+
+ for (int i=0; i<nsize; i++){
+ String type_caption = nodes_vars.get(i).get("type").parameters.get(0).caption;
+ arg_types[i] = ttable.get(type_caption);
+ }
+
+ LLVMType ret_type = ttable.get(node.get("return").get("type").parameters.get(0).caption);
+ String func_name = node.get("name").parameters.get(0).caption;
+
+ LLVMFunctionType func_type =new LLVMFunctionType(ret_type, arg_types, false);
+ LLVMFunction func = new LLVMFunction(module, func_name, func_type);
+
+ LLVMBasicBlock entry = func.appendBasicBlock("entry");
+ builder.positionBuilderAtEnd(entry);
+
+ LLVMValue[] values = func.getParameters();
+ String[] vars = new NodeFunctionVarsList(node.get("vars-list")).getVarNames();
+
+ LLVMValue func_body = new Evaluator(vars, values).eval(node.get("body").parameters.get(0));
+
+ new LLVMReturnInstruction(builder, func_body);
+
+ SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
+ int x = Analysis.LLVMVerifyFunction(func.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction);
+ x = Analysis.LLVMVerifyModule(module.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction, outerrs);
+ ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
+
+ functions.put(func_name, func);
+ }
+
+ public int main(ASTLispNode node) throws Exception{
+
+ String func_main_name = node.parameters.get(0).caption;
+ LLVMFunction func_main = functions.get(func_main_name);
+ if (null == func_main){
+ throw new Exception("Main function not found!");
+ }
+
+ boolean isNative = LLVMTargetData.initializeNativeTarget();
+ LispJITRunnerWrapper program = new LispJITRunnerWrapper(module);
+ LLVMGenericValue resultRef = program.runFunction(func_main, new LLVMGenericValue[0]);
+ BigInteger resultBig = ExecutionEngine.LLVMGenericValueToInt(resultRef.getInstance(), 0);
+ int result = resultBig.intValue();
+ return result;
+
+ /*
+ TestRunner2 runner = new TestRunner2();
+ runner.setModule(module);
+ runner.runBody(func_main);
+
+ return 0;
+ *
+ */
+ }
+
+
+
+
+ public Object handle(ASTLispNode node) throws Exception{
+ String caption = node.caption;
+ String method = htable.get(caption);
+
+ if (method == null) {
+ throw new Exception();
+ }
+
+ Method invoker = this.getClass().getDeclaredMethod(method, ASTLispNode.class);
+ return invoker.invoke(this, node);
+ }
+
+ public LispInterpreter(){
+ }
+
+ static {
+ /*
+ * Handler table хранит информацию о соответствии метода и команды
+ */
+ htable = new ImmutableMap.Builder<String, String>()
+ .put("opcode", "opcodeDef")
+ .put("function", "functionDef")
+ .put ("calculate", "calculate")
+ .put("main", "main")
+ .build();
+
+ /*
+ * Types Table - хранит информацию о соответствии типов
+ */
+ ttable = new ImmutableMap.Builder<String, LLVMType>()
+ .put ("i32", LLVMIntegerType.i32)
+ .put ("i16", LLVMIntegerType.i16)
+ .put ("i8", LLVMIntegerType.i8)
+ .build();
+
+
+ }
+
+ class Evaluator{
+ Map<String, LLVMValue> arguments;
+
+ public Evaluator(String[] names, LLVMValue[] values) {
+
+ int size = names.length;
+ arguments = Maps.newHashMapWithExpectedSize(size);
+
+ for(int i=0; i<size; i++){
+ arguments.put(names[i], values[i]);
+ }
+ }
+
+ public LLVMValue LLVMAddInstruction(ASTLispNode node) throws Exception{
+
+ LLVMValue arg1 = eval(node.parameters.get(0));
+ LLVMValue arg2 = eval(node.parameters.get(1));
+
+ return new LLVMAddInstruction(builder, arg1, arg2, false, "add");
+ }
+
+ public LLVMValue LLVMDivideInstruction(ASTLispNode node) throws Exception{
+ LLVMValue arg1 = eval(node.parameters.get(0));
+ LLVMValue arg2 = eval(node.parameters.get(1));
+
+ return new LLVMDivideInstruction(builder, arg1, arg2, LLVMDivideInstruction.DivisionType.UNSIGNEDINT, "div");
+ }
+
+ public LLVMValue LLVMCallFunctionInstruction(ASTLispNode node) throws Exception{
+ LLVMFunction func = functions.get(node.caption);
+
+ int size = node.parameters.size();
+
+ LLVMValue[] args = new LLVMValue[size];
+
+ for (int i=0; i<size; i++){
+ args[i] = eval(node.parameters.get(i));
+ }
+
+// long argsNum = Core.LLVMCountParamTypes(Core.LLVMTypeOf(func.getInstance()));
+
+ SWIGTYPE_p_p_LLVMOpaqueValue args_opaque = Core.new_LLVMValueRefArray(args.length);
+ for(int i=0;i<args.length;i++)
+ Core.LLVMValueRefArray_setitem(args_opaque,i,args[i].getInstance());
+ SWIGTYPE_p_LLVMOpaqueValue instance = Core.LLVMBuildCall(builder.getInstance(),func.getInstance(),args_opaque,args.length, node.caption + "aaa");
+
+ Core.delete_LLVMValueRefArray(args_opaque);
+
+ return new LLVMValue(instance);
+ //return new LLVMCallInstruction(builder, func, args, node.caption);
+ }
+
+ public LLVMValue eval(ASTLispNode node) throws Exception{
+ if (node instanceof ASTLispConstantNode){
+ return LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, ((ASTLispConstantNode) node).value, false);
+ }
+
+ String instruction = opcodes.get(node.caption);
+
+ if (instruction != null) {
+ Method invoker = this.getClass().getDeclaredMethod(instruction, ASTLispNode.class);
+ return (LLVMValue) invoker.invoke(this, node);
+ }
+
+ LLVMValue arg = arguments.get(node.caption);
+
+ if (arg != null){
+ return arg;
+ }
+
+ if (functions.containsKey(node.caption)){
+ return LLVMCallFunctionInstruction(node);
+ }
+
+ throw new Exception("Cant evaluate symbol: " + node.caption);
+ }
+
+ }
+}
+
+
+
+class LispJITRunnerWrapper extends LLVMExecutionEngine{
+ LispJITRunnerWrapper(LLVMModule module) throws Exception{
+ super();
+
+ 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;
+ instance = ExecutionEngine.LLVMExecutionEngineRefArray_getitem(engines,0);
+ ExecutionEngine.delete_LLVMExecutionEngineRefArray(engines); engines = null;
+
+ /*
+ if(success == 0)
+ throw new Exception(outerr);
+ *
+ */
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/xreate/grammatic/lisp/LispLexer.java b/src/main/java/org/xreate/grammatic/lisp/LispLexer.java
new file mode 100644
index 0000000..8f8d69a
--- /dev/null
+++ b/src/main/java/org/xreate/grammatic/lisp/LispLexer.java
@@ -0,0 +1,368 @@
+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 LispLexer extends Lexer {
+ 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
+ // delegators
+ public Lexer[] getDelegates() {
+ return new Lexer[] {};
+ }
+
+ public LispLexer() {}
+ public LispLexer(CharStream input) {
+ this(input, new RecognizerSharedState());
+ }
+ public LispLexer(CharStream input, RecognizerSharedState state) {
+ super(input,state);
+ }
+ public String getGrammarFileName() { return "/private/prg/code/xreate/antlr/lisp.g"; }
+
+ // $ANTLR start "T__6"
+ public final void mT__6() throws RecognitionException {
+ try {
+ int _type = T__6;
+ int _channel = DEFAULT_TOKEN_CHANNEL;
+ // /private/prg/code/xreate/antlr/lisp.g:2:6: ( '(' )
+ // /private/prg/code/xreate/antlr/lisp.g:2:8: '('
+ {
+ match('(');
+
+ }
+
+ state.type = _type;
+ state.channel = _channel;
+ }
+ finally {
+ // do for sure before leaving
+ }
+ }
+ // $ANTLR end "T__6"
+
+ // $ANTLR start "T__7"
+ public final void mT__7() throws RecognitionException {
+ try {
+ int _type = T__7;
+ int _channel = DEFAULT_TOKEN_CHANNEL;
+ // /private/prg/code/xreate/antlr/lisp.g:3:6: ( ')' )
+ // /private/prg/code/xreate/antlr/lisp.g:3:8: ')'
+ {
+ match(')');
+
+ }
+
+ state.type = _type;
+ state.channel = _channel;
+ }
+ finally {
+ // do for sure before leaving
+ }
+ }
+ // $ANTLR end "T__7"
+
+ // $ANTLR start "T__8"
+ public final void mT__8() throws RecognitionException {
+ try {
+ int _type = T__8;
+ int _channel = DEFAULT_TOKEN_CHANNEL;
+ // /private/prg/code/xreate/antlr/lisp.g:4:6: ( ',' )
+ // /private/prg/code/xreate/antlr/lisp.g:4:8: ','
+ {
+ match(',');
+
+ }
+
+ state.type = _type;
+ state.channel = _channel;
+ }
+ finally {
+ // do for sure before leaving
+ }
+ }
+ // $ANTLR end "T__8"
+
+ // $ANTLR start "WHITESPACE"
+ public final void mWHITESPACE() throws RecognitionException {
+ try {
+ int _type = WHITESPACE;
+ int _channel = DEFAULT_TOKEN_CHANNEL;
+ // /private/prg/code/xreate/antlr/lisp.g:3:12: ( ( '\\t' | ' ' | '\\r' | '\\n' | '\\u000C' )+ )
+ // /private/prg/code/xreate/antlr/lisp.g:3:14: ( '\\t' | ' ' | '\\r' | '\\n' | '\\u000C' )+
+ {
+ // /private/prg/code/xreate/antlr/lisp.g:3:14: ( '\\t' | ' ' | '\\r' | '\\n' | '\\u000C' )+
+ int cnt1=0;
+ loop1:
+ do {
+ int alt1=2;
+ int LA1_0 = input.LA(1);
+
+ if ( ((LA1_0 >= '\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[] {
+ "<invalid>", "<EOR>", "<DOWN>", "<UP>", "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");
+ }
+}

Event Timeline