- the ex stream >> operator is gone
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 31 Mar 2000 03:48:28 +0000 (03:48 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 31 Mar 2000 03:48:28 +0000 (03:48 +0000)
- 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

ginac/Makefile.am
ginac/Makefile.in
ginac/ex.cpp
ginac/ex.h
ginac/input_lexer.h
ginac/input_lexer.ll
ginac/input_parser.yy
ginac/operators.cpp
ginsh/ginsh_lexer.ll

index cbf8f4e73b8703dda2f7e807c0a91f509ce44e6a..d0b9db47d27ce9bf5f6ef76d3663370299bd0e32 100644 (file)
@@ -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
index 24464f6c0236a32503f943f906c5ac5bc8491d43..2d4944cc5dd828825bd73cdd3f20061187200443 100644 (file)
@@ -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
index 4eb3d15d32210f2142533a6f558daa85bcadb5e4..d53cb9585b94b22a3d82257a13fdee58e5d33b41 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <iostream>
+#include <stdexcept>
 
 #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
index 94512e087e2b0ab85c1b884ff95e1f87cc3f9039..9b1d0fa1e399142bf2f1db285bd9213c71849538 100644 (file)
@@ -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
index 575c836c75c9bca76adbcccbf38446e0a3084ce9..e67ae9236e4fa4c1f460ae65df1da4e04e29a600 100644 (file)
@@ -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. */
index e0e9b468a1186c37f3e98a01574d011b96c7f1be..04b71e832b2f17bd17b17090811d357607541ba5 100644 (file)
@@ -51,7 +51,25 @@ namespace GiNaC {
 #endif // ndef NO_NAMESPACE_GINAC
 
 // Table of all used symbols
-typedef map<string, ex> 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<string, sym_def> 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; i<l.nops(); i++) {
                if (is_ex_exactly_of_type(l.op(i), symbol))
-                       syms[ex_to_symbol(l.op(i)).getname()] = l.op(i);
+                       syms[ex_to_symbol(l.op(i)).getname()] = sym_def(l.op(i), true);
        }
 }
 
+// Check whether symbol was predefined
+bool is_lexer_symbol_predefined(const ex &s)
+{
+       sym_tab::const_iterator i = syms.find(ex_to_symbol(s).getname());
+       if (i == syms.end())
+               return false;
+       else
+               return i->second.predefined;
+}
+
 #ifndef NO_NAMESPACE_GINAC
 } // namespace GiNaC
 #endif // ndef NO_NAMESPACE_GINAC
index e714c9bf97d0f8f04eedcf31de911fb1fc1b72e6..0bec16c75cc493c2fb4e4c32818df237c803ec48 100644 (file)
@@ -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 ')' {
index 6cf750cefa7005542175ee6d46f2178a18a34787..ea256a8ecb597bb30b4e23c4a87c277be453d7e3 100644 (file)
@@ -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
index 7f78a2dd3f97ec72cd0f0d4992c8047cff825f34..250403536b19094cfea4ca69ade10bb6913341fa 100644 (file)
@@ -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;
                        }