From: Jens Vollinga Date: Fri, 10 Jul 2009 13:01:04 +0000 (+0200) Subject: Changed the parser such that it understands all defined functions X-Git-Tag: release_1-6-0~77 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=f38cbcd651246fb5c1294705d29399f3cbfddaf5;ds=sidebyside Changed the parser such that it understands all defined functions including the user defined ones. To this end a method has been added to class function to allow the modified get_default_reader() function to build up a complete prototype table. The autogen tool is no longer required. --- diff --git a/INSTALL b/INSTALL index 3be16c1f..3c188b66 100644 --- a/INSTALL +++ b/INSTALL @@ -30,8 +30,7 @@ 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), autogen (>= 5.6.0) to be -installed. +libtool (>= 1.5), bison (>= 2.3), flex (>= 2.5.33) to be installed. INSTALLATION diff --git a/configure.ac b/configure.ac index 551f4f95..14b888f1 100644 --- a/configure.ac +++ b/configure.ac @@ -119,10 +119,6 @@ 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 bf20afc4..03e1845b 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -13,7 +13,6 @@ 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 \ @@ -67,22 +66,7 @@ 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 \ -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 - +EXTRA_DIST = function.pl version.h.in # 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 e1533be2..af14a753 100644 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -536,6 +536,7 @@ 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 deleted file mode 100644 index 897b1f72..00000000 --- a/ginac/parser/builtin_fcns.def +++ /dev/null @@ -1,90 +0,0 @@ -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 deleted file mode 100644 index 3ae6ff83..00000000 --- a/ginac/parser/default_reader.tpl +++ /dev/null @@ -1,50 +0,0 @@ -[+ 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 5c442023..d9790276 100644 --- a/ginac/parser/parse_context.cpp +++ b/ginac/parser/parse_context.cpp @@ -22,6 +22,8 @@ #include "parse_context.h" +#include "function.h" + #include #include @@ -51,4 +53,22 @@ 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 15dfcd63..c7360ddd 100644 --- a/ginac/parser/parse_context.h +++ b/ginac/parser/parse_context.h @@ -72,25 +72,18 @@ 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; /** - * Default prototype table. + * Creates a default prototype table containing all defined GiNaC functions. * - * It supports most of builtin GiNaC functions. + * 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. */ -extern const prototype_table& get_default_reader(); +extern const prototype_table& get_default_reader(bool force_init = false); } // namespace GiNaC diff --git a/ginac/parser/parser.cpp b/ginac/parser/parser.cpp index 42edf5b0..2bc21821 100644 --- a/ginac/parser/parser.cpp +++ b/ginac/parser/parser.cpp @@ -24,6 +24,7 @@ #include "lexer.h" #include "debug.h" #include "mul.h" +#include "function.h" #include "constant.h" #include @@ -65,7 +66,7 @@ ex parser::parse_identifier_expr() Parse_error_("no function \"" << name << "\" with " << args.size() << " arguments"); } - ex ret = reader->second(args); + ex ret = function(reader->second, args); return ret; }