From: Alexei Sheplyakov Date: Thu, 9 Dec 2010 18:42:50 +0000 (+0200) Subject: Revert "Changed the parser such that it understands all defined functions" X-Git-Tag: release_1-6-0~31 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=3aec0ba298693329c1194e547043fef1a78b1b0d;hp=f5abf61d2cb1a1d1809d270a24fa098575b172c4 Revert "Changed the parser such that it understands all defined functions" This reverts commit f38cbcd651246fb5c1294705d29399f3cbfddaf5, which broke parsing user-defined classes. --- diff --git a/INSTALL b/INSTALL index 3c188b66..3be16c1f 100644 --- 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 diff --git a/configure.ac b/configure.ac index 9f7df706..9fe9d5f3 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/ginac/Makefile.am b/ginac/Makefile.am index 03e1845b..bf20afc4 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -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 diff --git a/ginac/function.pl b/ginac/function.pl index 07e82e19..1c6ce297 100644 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -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 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 index 00000000..897b1f72 --- /dev/null +++ b/ginac/parser/builtin_fcns.def @@ -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 index 00000000..3ae6ff83 --- /dev/null +++ b/ginac/parser/default_reader.tpl @@ -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 + diff --git a/ginac/parser/parse_context.cpp b/ginac/parser/parse_context.cpp index 88b0b30e..2230d614 100644 --- a/ginac/parser/parse_context.cpp +++ b/ginac/parser/parse_context.cpp @@ -22,8 +22,6 @@ #include "parse_context.h" -#include "function.h" - #include #include @@ -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 flist = function::get_registered_functions(); - std::vector::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 diff --git a/ginac/parser/parse_context.h b/ginac/parser/parse_context.h index 07496d7e..35163209 100644 --- a/ginac/parser/parse_context.h +++ b/ginac/parser/parse_context.h @@ -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_table; +typedef std::map 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 diff --git a/ginac/parser/parser.cpp b/ginac/parser/parser.cpp index 06743833..42a7ae2b 100644 --- a/ginac/parser/parser.cpp +++ b/ginac/parser/parser.cpp @@ -24,7 +24,6 @@ #include "lexer.h" #include "debug.h" #include "mul.h" -#include "function.h" #include "constant.h" #include @@ -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; }