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
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
*/
#include <iostream>
+#include <stdexcept>
#include "ex.h"
#include "add.h"
#include "numeric.h"
#include "power.h"
#include "relational.h"
+#include "input_lexer.h"
#include "debugmsg.h"
#include "utils.h"
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
//////////
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
;
#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
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
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. */
#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
#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}+
[ \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;
{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;
}
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
#define YYERROR_VERBOSE 1
-#define yylex ginac_yylex
-#define yyerror ginac_yyerror
-
// Parsed output expression
ex parsed_ex;
;
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 ')' {
#include "numeric.h"
#include "power.h"
#include "relational.h"
-#include "input_lexer.h"
#include "debugmsg.h"
#include "utils.h"
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
/* 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;
}