From: Christian Bauer Date: Fri, 31 Mar 2000 03:48:28 +0000 (+0000) Subject: - the ex stream >> operator is gone X-Git-Tag: release_0-6-0~38 X-Git-Url: https://ginac.de/ginac.git/tutorial/ginac.git?a=commitdiff_plain;h=fa792492f853255f78b3e10c6f727fd10ad45cac;p=ginac.git - the ex stream >> operator is gone - added a new ex constructor ex(string, ex) instead; use as follows: symbol x("x"), y("y"); ex e("Pi*(4*x^2+y)^10", lst(x, y)); or, for interactive input: symbol x("x"); string s; cout << "Input something (may contain 'x'): "; getline(cin, s); try { e = ex(s, lst(x)); cout << "You entered " << e << endl; cout << "e.diff(x) = " << e.diff(x) << endl; } catch (exception &c) { cerr << c.what() << endl; } - symbols not specified in the list in the second argument to ex(string, ex) but encountered in the input expression will throw an exception --- diff --git a/ginac/Makefile.am b/ginac/Makefile.am index cbf8f4e7..d0b9db47 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -19,8 +19,8 @@ ginacinclude_HEADERS = ginac.h add.h archive.h basic.h clifford.h color.h \ mul.h ncmul.h normal.h numeric.h operators.h power.h registrar.h \ relational.h pseries.h simp_lor.h structure.h symbol.h lortensor.h tinfos.h \ assertion.h -LFLAGS = -olex.yy.c -YFLAGS = -d +LFLAGS = -Pginac_yy -olex.yy.c +YFLAGS = -p ginac_yy -d EXTRA_DIST = container.pl function.pl structure.pl input_parser.h # Files which are generated by perl scripts diff --git a/ginac/Makefile.in b/ginac/Makefile.in index 24464f6c..2d4944cc 100644 --- a/ginac/Makefile.in +++ b/ginac/Makefile.in @@ -111,8 +111,8 @@ libginac_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -re ginacincludedir = $(includedir)/ginac ginacinclude_HEADERS = ginac.h add.h archive.h basic.h clifford.h color.h coloridx.h constant.h ex.h expair.h expairseq.h exprseq.h fail.h flags.h function.h idx.h indexed.h inifcns.h isospin.h lorentzidx.h lst.h matrix.h mul.h ncmul.h normal.h numeric.h operators.h power.h registrar.h relational.h pseries.h simp_lor.h structure.h symbol.h lortensor.h tinfos.h assertion.h -LFLAGS = -olex.yy.c -YFLAGS = -d +LFLAGS = -Pginac_yy -olex.yy.c +YFLAGS = -p ginac_yy -d EXTRA_DIST = container.pl function.pl structure.pl input_parser.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h diff --git a/ginac/ex.cpp b/ginac/ex.cpp index 4eb3d15d..d53cb958 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -21,6 +21,7 @@ */ #include +#include #include "ex.h" #include "add.h" @@ -29,6 +30,7 @@ #include "numeric.h" #include "power.h" #include "relational.h" +#include "input_lexer.h" #include "debugmsg.h" #include "utils.h" @@ -133,6 +135,12 @@ ex::ex(double const d) construct_from_double(d); } +ex::ex(const string &s, const ex &l) +{ + debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT); + construct_from_string_and_lst(s, l); +} + #endif // ndef INLINE_EX_CONSTRUCTORS ////////// @@ -623,6 +631,21 @@ void ex::construct_from_double(double d) GINAC_ASSERT((bp->flags) & status_flags::dynallocated); GINAC_ASSERT(bp->refcount=1); } + +void ex::construct_from_string_and_lst(const string &s, const ex &l) +{ + set_lexer_string(s); + set_lexer_symbols(l); + ginac_yyrestart(NULL); + if (ginac_yyparse()) + throw (std::runtime_error(get_parser_error())); + else { + bp = parsed_ex.bp; + GINAC_ASSERT(bp!=0); + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + ++bp->refcount; + } +} ////////// // static member variables diff --git a/ginac/ex.h b/ginac/ex.h index 94512e08..9b1d0fa1 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -205,6 +205,22 @@ public: ; #endif // def INLINE_EX_CONSTRUCTORS + /** Construct ex from string and a list of symbols. The input grammar is + * similar to the GiNaC output format. All symbols to be used in the + * expression must be specified in a lst in the second argument. Undefined + * symbols and other parser errors will throw an exception. */ + ex(const string &s, const ex &l) +#ifdef INLINE_EX_CONSTRUCTORS + { + construct_from_string_and_lst(s, l); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK + } +#else +; +#endif // def INLINE_EX_CONSTRUCTORS + // functions overriding virtual functions from bases classes // none @@ -329,6 +345,7 @@ private: void construct_from_long(long i); void construct_from_ulong(unsigned long i); void construct_from_double(double d); + void construct_from_string_and_lst(const string &s, const ex &l); void makewriteable(); #ifdef OBSCURE_CINT_HACK diff --git a/ginac/input_lexer.h b/ginac/input_lexer.h index 575c836c..e67ae923 100644 --- a/ginac/input_lexer.h +++ b/ginac/input_lexer.h @@ -47,16 +47,19 @@ namespace GiNaC { class ex; -/** Set the input string to be parsed by yyparse(). */ +/** Set the input string to be parsed by ginac_yyparse() (used internally). */ extern void set_lexer_string(const string &s); -/** Set the list of predefined symbols for the lexer (used internally for stream input). */ +/** Set the list of predefined symbols for the lexer (used internally). */ extern void set_lexer_symbols(ex l); -/** The expression parser function (used internally for stream input). */ -extern int yyparse(); +/** Check whether lexer symbol was predefined (vs. created by the lexer, e.g. function names). */ +extern bool is_lexer_symbol_predefined(const ex &s); -/** The expression returned by the parser (used internally for stream input). */ +/** The expression parser function (used internally). */ +extern int ginac_yyparse(); + +/** The expression returned by the parser (used internally). */ extern ex parsed_ex; /** Get error message from the parser. */ diff --git a/ginac/input_lexer.ll b/ginac/input_lexer.ll index e0e9b468..04b71e83 100644 --- a/ginac/input_lexer.ll +++ b/ginac/input_lexer.ll @@ -51,7 +51,25 @@ namespace GiNaC { #endif // ndef NO_NAMESPACE_GINAC // Table of all used symbols -typedef map sym_tab; +struct sym_def { + sym_def() : predefined(false) {} + sym_def(const ex &s, bool predef) : sym(s), predefined(predef) {} + ~sym_def() {} + + sym_def(const sym_def &other) {sym = other.sym; predefined = other.predefined;} + const sym_def &operator=(const sym_def &other) + { + if (this != &other) { + sym = other.sym; + predefined = other.predefined; + } + return *this; + } + + ex sym; + bool predefined; // true = user supplied symbol, false = lexer generated symbol +}; +typedef map sym_tab; static sym_tab syms; // lex input function @@ -59,9 +77,6 @@ static int lexer_input(char *buf, int max_size); #define YY_INPUT(buf, result, max_size) (result = lexer_input(buf, max_size)) %} - /* The code output by flex doesn't work well with namespaces, so we're doing it this way */ -%option prefix="ginac_yy" - /* Abbreviations */ D [0-9] E [elEL][-+]?{D}+ @@ -77,12 +92,12 @@ AN [0-9a-zA-Z_] [ \t]+ /* skip whitespace */ /* special values */ -Pi yylval = Pi; return T_LITERAL; -Euler yylval = Euler; return T_LITERAL; -Catalan yylval = Catalan; return T_LITERAL; -FAIL yylval = *new fail(); return T_LITERAL; -I yylval = I; return T_NUMBER; -Digits yylval = (long)Digits; return T_DIGITS; +Pi ginac_yylval = Pi; return T_LITERAL; +Euler ginac_yylval = Euler; return T_LITERAL; +Catalan ginac_yylval = Catalan; return T_LITERAL; +FAIL ginac_yylval = *new fail(); return T_LITERAL; +I ginac_yylval = I; return T_NUMBER; +Digits ginac_yylval = (long)Digits; return T_DIGITS; /* comparison */ "==" return T_EQUAL; @@ -98,13 +113,15 @@ Digits yylval = (long)Digits; return T_DIGITS; {D}+ | {D}+"."{D}*({E})? | {D}*"."{D}+({E})? | -{D}+{E} yylval = numeric(yytext); return T_NUMBER; +{D}+{E} ginac_yylval = numeric(yytext); return T_NUMBER; /* symbols */ {A}{AN}* { - if (syms.find(yytext) == syms.end()) - syms[yytext] = *(new symbol(yytext)); - yylval = syms[yytext]; + sym_tab::const_iterator i = syms.find(yytext); + if (i == syms.end()) { + syms[yytext] = sym_def(ginac_yylval = *(new symbol(yytext)), false); + } else + ginac_yylval = i->second.sym; return T_SYMBOL; } @@ -162,10 +179,20 @@ void set_lexer_symbols(ex l) return; for (int i=0; isecond.predefined; +} + #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC #endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/input_parser.yy b/ginac/input_parser.yy index e714c9bf..0bec16c7 100644 --- a/ginac/input_parser.yy +++ b/ginac/input_parser.yy @@ -45,9 +45,6 @@ namespace GiNaC { #define YYERROR_VERBOSE 1 -#define yylex ginac_yylex -#define yyerror ginac_yyerror - // Parsed output expression ex parsed_ex; @@ -90,7 +87,12 @@ input : exp { ; exp : T_NUMBER {$$ = $1;} - | T_SYMBOL {$$ = $1.eval();} + | T_SYMBOL { + if (is_lexer_symbol_predefined($1)) + $$ = $1.eval(); + else + throw (std::runtime_error("unknown symbol '" + ex_to_symbol($1).getname() + "'")); + } | T_LITERAL {$$ = $1;} | T_DIGITS {$$ = $1;} | T_SYMBOL '(' exprseq ')' { diff --git a/ginac/operators.cpp b/ginac/operators.cpp index 6cf750ce..ea256a8e 100644 --- a/ginac/operators.cpp +++ b/ginac/operators.cpp @@ -29,7 +29,6 @@ #include "numeric.h" #include "power.h" #include "relational.h" -#include "input_lexer.h" #include "debugmsg.h" #include "utils.h" @@ -336,21 +335,9 @@ ostream & operator<<(ostream & os, const ex & e) return os; } -/** Input (parse) expression from stream. The input grammar is similar to the - * GiNaC output format. If 'e' contains a list of symbols upon entry, these - * symbols are used in the parsed expression in all places where symbols with - * the same names appear. All other encountered symbols will be newly created. */ istream & operator>>(istream & is, ex & e) { - string s; - getline(is, s); - set_lexer_string(s); - set_lexer_symbols(e); - ginac_yyrestart(NULL); - if (yyparse()) - throw (std::runtime_error(get_parser_error())); - else - e = parsed_ex; + throw (std::logic_error("expression input from streams not implemented")); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginsh/ginsh_lexer.ll b/ginsh/ginsh_lexer.ll index 7f78a2dd..25040353 100644 --- a/ginsh/ginsh_lexer.ll +++ b/ginsh/ginsh_lexer.ll @@ -101,9 +101,11 @@ score return T_SCORE; /* symbols */ {A}{AN}* { - if (syms.find(yytext) == syms.end()) - syms[yytext] = *(new symbol(yytext)); - yylval = syms[yytext]; + sym_tab::const_iterator i = syms.find(yytext); + if (i == syms.end()) { + yylval = syms[yytext] = *(new symbol(yytext)); + } else + yylval = i->second; return T_SYMBOL; }