Revert "Changed the parser such that it understands all defined functions"
authorAlexei Sheplyakov <Alexei.Sheplyakov@gmail.com>
Thu, 9 Dec 2010 18:42:50 +0000 (20:42 +0200)
committerAlexei Sheplyakov <Alexei.Sheplyakov@gmail.com>
Thu, 9 Dec 2010 18:42:50 +0000 (20:42 +0200)
This reverts commit f38cbcd651246fb5c1294705d29399f3cbfddaf5, which
broke parsing user-defined classes.

INSTALL
configure.ac
ginac/Makefile.am
ginac/function.pl
ginac/parser/builtin_fcns.def [new file with mode: 0644]
ginac/parser/default_reader.tpl [new file with mode: 0644]
ginac/parser/parse_context.cpp
ginac/parser/parse_context.h
ginac/parser/parser.cpp

diff --git a/INSTALL b/INSTALL
index 3c188b6..3be16c1 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -30,7 +30,8 @@ Known not to work with:
    is missing there.
 
 If you install from git, you also need GNU autoconf (>=2.59), automake (>=1.8),
-libtool (>= 1.5), bison (>= 2.3), flex (>= 2.5.33) to be installed.
+libtool (>= 1.5), bison (>= 2.3), flex (>= 2.5.33), autogen (>= 5.6.0) to be
+installed.
 
 
 INSTALLATION
index 9f7df70..9fe9d5f 100644 (file)
@@ -119,6 +119,10 @@ AM_CONDITIONAL(CONFIG_TEX, [test ! \( -z "$LATEX" -o -z $"PDFLATEX" -o -z "$MAKE
 AC_PATH_PROG(FIG2DEV, fig2dev, "")
 AM_CONDITIONAL(CONFIG_FIG2DEV, [test ! -z "$FIG2DEV"])
 
+dnl generate boilerplate code for the (new) parser.
+dnl Only developers need this tool.
+AC_PATH_PROG(AUTOGEN, autogen, "")
+
 dnl Output makefiles etc.
 AC_CONFIG_FILES([
 Makefile
index 03e1845..bf20afc 100644 (file)
@@ -13,6 +13,7 @@ libginac_la_SOURCES = add.cpp archive.cpp basic.cpp clifford.cpp color.cpp \
   parser/parse_binop_rhs.cpp \
   parser/parser.cpp \
   parser/parse_context.cpp \
+  parser/builtin_fcns.cpp \
   parser/lexer.cpp \
   parser/lexer.h \
   parser/parser_compat.cpp \
@@ -66,7 +67,22 @@ ginacinclude_HEADERS = ginac.h add.h archive.h assertion.h basic.h class_info.h
   parser/parser.h \
   parser/parse_context.h
 
-EXTRA_DIST = function.pl version.h.in
+EXTRA_DIST = function.pl version.h.in \
+parser/default_reader.tpl parser/builtin_fcns.def
+
+# Files produced by autogen(1) from templates
+$(srcdir)/parser/builtin_fcns.cpp: $(srcdir)/parser/builtin_fcns.def $(srcdir)/parser/default_reader.tpl
+       set -e; if [ -n "$(AUTOGEN)" ]; then \
+               cd $(srcdir)/parser; \
+               $(AUTOGEN) -T default_reader.tpl builtin_fcns.def; \
+       elif [ -f $@ ]; then \
+               echo "WARNING: AutoGen is not available, the \"$@\" file WON'T be re-generated"; \
+       else \
+               echo "*** ERROR: the \"$@\" file does not exist, and AutoGen is not installed on your system"; \
+               echo "***        Please install AutoGen (http://www.gnu.org/software/autogen)"; \
+               exit 1; \
+       fi
+               
 
 # Files which are generated by perl scripts
 $(srcdir)/function.h $(srcdir)/function.cpp: $(srcdir)/function.pl
index 07e82e1..1c6ce29 100644 (file)
@@ -536,7 +536,6 @@ public:
        static unsigned register_new(function_options const & opt);
        static unsigned current_serial;
        static unsigned find_function(const std::string &name, unsigned nparams);
-       static std::vector<function_options> get_registered_functions() { return registered_functions(); };
        unsigned get_serial() const {return serial;}
        std::string get_name() const;
 
diff --git a/ginac/parser/builtin_fcns.def b/ginac/parser/builtin_fcns.def
new file mode 100644 (file)
index 0000000..897b1f7
--- /dev/null
@@ -0,0 +1,90 @@
+Autogen definitions ginacfcns;
+
+function = { name = "log"; };
+function = { name = "exp"; };
+function = { name = "sin"; };
+function = { name = "cos"; };
+function = { name = "tan"; };
+function = { name = "asin"; };
+function = { name = "acos"; };
+function = { name = "atan"; };
+
+function = { name = "sinh"; };
+function = { name = "cosh"; };
+function = { name = "tanh"; };
+function = { name = "asinh"; };
+function = { name = "acosh"; };
+function = { name = "atanh"; };
+
+function = { 
+       name = "atan2";
+       args = 2;
+};
+
+function = { 
+       name = "Li2";
+       comment = "Dilogarithm";
+};
+
+function = {
+       name = "Li3";
+       comment = "Trilogarithm";
+};
+
+function = {
+       name = "zetaderiv";
+       comment = "Derivatives of Riemann's Zeta-function";
+       args = 2;
+};
+
+function = {
+       name = "Li";
+       args = 2;
+       comment = "Polylogarithm and multiple polylogarithm";
+};
+
+function = {
+       name =  "S";
+       args = 3;
+       comment = "Nielsen's generalized polylogarithm";
+};
+
+function = {
+       name =  "H";
+       args = 2;
+       comment = "Harmonic polylogarithm";
+};
+
+function = { name = "lgamma"; };
+function = { name = "tgamma"; };
+
+function = {
+       name = "beta";
+       args = 2;
+       comment = "Beta-function";
+};
+
+function = { name = "factorial"; };
+
+function = {
+       name = "binomial";
+       args = 2;
+};
+
+function = {
+       name = "Order";
+       comment = "Order term function (for truncated power series)";
+};
+
+/* Thease are not functions, but anyway ... */
+function = { name = "sqrt"; };
+
+function = { 
+       name = "pow";
+       args = 2;
+};
+
+function = {
+       name = "power";
+       args = 2;
+};
diff --git a/ginac/parser/default_reader.tpl b/ginac/parser/default_reader.tpl
new file mode 100644 (file)
index 0000000..3ae6ff8
--- /dev/null
@@ -0,0 +1,50 @@
+[+ AutoGen5 template .cpp +][+ 
+COMMENT a part of GiNaC parser -- construct functions from a byte stream.
++][+
+(use-modules (ice-9 format))
+
+(define (sequence start end . step)
+  (let ((step (if (null? step) 1 (car step))))
+    (let loop ((n start))
+      (if (> n end) '() (cons n (loop (+ step n)))))))
++]/*
+[+ (dne " * " " * " ) +]
+ *
+ * If you want to change this file, edit either `[+ (def-file) +]' or
+ * `[+ (tpl-file) +]' file, and run the following command:
+ *
+ * autogen -T [+ (tpl-file) +] [+ (def-file) +]
+ */
+#include "parse_context.h"
+#include "power.h"
+#include "operators.h"
+#include "inifcns.h"
+
+namespace GiNaC
+{
+[+ FOR function +]
+static ex [+ (get "name") +]_reader(const exvector& ev)
+{
+       return GiNaC::[+ (get "name") +]([+
+               (let ((nargs (if (exist? "args")
+                                (string->number (get "args")) 1)))
+                 (format '#f "~{ev[~a]~^, ~}" (sequence 0 (- nargs 1)))) +]);
+}[+ ENDFOR +]
+
+const prototype_table& get_default_reader()
+{
+       using std::make_pair;
+       static bool initialized = false;
+       static prototype_table reader;
+       if (!initialized) {
+[+ FOR function +]
+               reader[make_pair("[+ (get "name") +]", [+ 
+                                   (if (exist? "args") (get "args") "1")
+                                +])] = [+ (get "name") +]_reader;[+
+   ENDFOR +]
+               initialized = true;
+       }
+       return reader;
+}
+} // namespace GiNaC
+
index 88b0b30..2230d61 100644 (file)
@@ -22,8 +22,6 @@
 
 #include "parse_context.h"
 
-#include "function.h"
-
 #include <sstream>
 #include <stdexcept>
 
@@ -46,22 +44,4 @@ find_or_insert_symbol(const std::string& name, symtab& syms, const bool strict)
        return sy;
 }
 
-const prototype_table& get_default_reader(bool force_init)
-{
-       using std::make_pair;
-       static bool initialized = false;
-       static prototype_table reader;
-       if ( !initialized || force_init ) {
-               std::vector<function_options> flist = function::get_registered_functions();
-               std::vector<function_options>::iterator i = flist.begin(), end = flist.end();
-               for ( ; i != end; ++i ) {
-                       std::string name = i->get_name();
-                       unsigned narg = i->get_nparams();
-                       reader[make_pair(name, narg)] = function::find_function(name, narg);
-               }
-               initialized = true;
-       }
-       return reader;
-}
-
 } // namespace GiNaC
index 07496d7..3516320 100644 (file)
@@ -72,18 +72,25 @@ typedef ex (*reader_func)(const exvector& args);
  * foo(x+y, z^2, t)), it looks up such a table to find out which
  * function (or class) corresponds to the given name and has the given
  * number of the arguments.
+ *
+ * N.B.
+ *
+ * 1. The function don't have to return a (GiNaC) function or class, it
+ *    can return any expression.
+ * 2. Overloaded functions/ctors are paritally supported, i.e. there might
+ *    be several functions with the same name, but they should take different
+ *    number of arguments.
+ * 3. User can extend the parser via custom prototype tables. It's possible
+ *    to read user defined classes, create abbreviations, etc.
  */
-typedef std::map<prototype, unsigned> prototype_table;
+typedef std::map<prototype, reader_func> prototype_table;
 
 /**
- * Creates a default prototype table containing all defined GiNaC functions.
+ * Default prototype table.
  *
- * The data referenced by the return value is only created once when this
- * function is called for the first time. This might cause problems in very
- * rare stituations (i.e. if functions are added after this first call). In
- * that case, a new initialization can be forced with an "true" argument.
+ * It supports most of builtin GiNaC functions.
  */
-extern const prototype_table& get_default_reader(bool force_init = false);
+extern const prototype_table& get_default_reader();
 
 } // namespace GiNaC
 
index 0674383..42a7ae2 100644 (file)
@@ -24,7 +24,6 @@
 #include "lexer.h"
 #include "debug.h"
 #include "mul.h"
-#include "function.h"
 #include "constant.h"
 
 #include <sstream>
@@ -66,7 +65,7 @@ ex parser::parse_identifier_expr()
                Parse_error_("no function \"" << name << "\" with " <<
                             args.size() << " arguments");
        }
-       ex ret = function(reader->second, args);
+       ex ret = reader->second(args);
        return ret;
 }