ex(long i);
ex(unsigned long i);
ex(double const d);
+
/** 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. */
+ * similar to the GiNaC output format. All symbols and indices 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 std::string &s, const ex &l);
// non-virtual functions in this class
/** Set the input string to be parsed by ginac_yyparse() (used internally). */
extern void set_lexer_string(const std::string &s);
+/** Get name of symbol/index (used internally). */
+extern std::string get_symbol_name(const ex & s);
+
/** Set the list of predefined symbols for the lexer (used internally). */
extern void set_lexer_symbols(ex l);
#include "numeric.h"
#include "symbol.h"
#include "lst.h"
+#include "idx.h"
using namespace GiNaC;
namespace GiNaC {
} // namespace GiNaC
-// Table of all used symbols
+// Table of all used symbols/indices
struct sym_def {
sym_def() : predefined(false) {}
sym_def(const ex &s, bool predef) : sym(s), predefined(predef) {}
curr_pos = 0;
}
-// Set the list of predefined symbols
+// Get name of symbol/index
+std::string get_symbol_name(const ex & s)
+{
+ if (is_a<symbol>(s))
+ return ex_to<symbol>(s).get_name();
+ else if (is_a<idx>(s) && is_a<symbol>(s.op(0)))
+ return ex_to<symbol>(s.op(0)).get_name();
+ else
+ throw (std::runtime_error("get_symbol_name(): unexpected expression type"));
+}
+
+// Set the list of predefined symbols/indices
void set_lexer_symbols(ex l)
{
syms.clear();
if (!is_exactly_a<lst>(l))
return;
for (unsigned i=0; i<l.nops(); i++) {
- if (is_exactly_a<symbol>(l.op(i)))
- syms[ex_to<symbol>(l.op(i)).get_name()] = sym_def(l.op(i), true);
+ const ex &o = l.op(i);
+ if (is_a<symbol>(o) || (is_a<idx>(o) && is_a<symbol>(o.op(0))))
+ syms[get_symbol_name(o)] = sym_def(o, true);
}
}
-// Check whether symbol was predefined
+// Check whether symbol/index was predefined
bool is_lexer_symbol_predefined(const ex &s)
{
- sym_tab::const_iterator i = syms.find(ex_to<symbol>(s).get_name());
+ sym_tab::const_iterator i = syms.find(get_symbol_name(s));
if (i == syms.end())
return false;
else
#include "lst.h"
#include "power.h"
#include "exprseq.h"
+#include "idx.h"
+#include "indexed.h"
#include "matrix.h"
#include "inifcns.h"
// Last error message returned by parser
static std::string parser_error;
+
+// Prototypes
+ex attach_index(const ex & base, ex i, bool covariant);
%}
/* Tokens (T_LITERAL means a literal value returned by the parser, but not
%left '*' '/' '%'
%nonassoc NEG
%right '^'
+%left '.' '~'
%nonassoc '!'
%start input
if (is_lexer_symbol_predefined($1))
$$ = $1.eval();
else
- throw (std::runtime_error("unknown symbol '" + ex_to<symbol>($1).get_name() + "'"));
+ throw (std::runtime_error("unknown symbol '" + get_symbol_name($1) + "'"));
}
| T_LITERAL {$$ = $1;}
| T_DIGITS {$$ = $1;}
| T_SYMBOL '(' exprseq ')' {
- std::string n = ex_to<symbol>($1).get_name();
+ std::string n = get_symbol_name($1);
if (n == "sqrt") {
if ($3.nops() != 1)
throw (std::runtime_error("too many arguments to sqrt()"));
| '-' exp %prec NEG {$$ = -$2;}
| '+' exp %prec NEG {$$ = $2;}
| exp '^' exp {$$ = pow($1, $3);}
+ | exp '.' exp {$$ = attach_index($1, $3, true);}
+ | exp '~' exp {$$ = attach_index($1, $3, false);}
| exp '!' {$$ = factorial($1);}
| '(' exp ')' {$$ = $2;}
| '{' list_or_empty '}' {$$ = $2;}
*/
%%
+// Attach index to expression
+ex attach_index(const ex & base, ex i, bool covariant)
+{
+ // Toggle index variance if necessary
+ if (is_a<varidx>(i)) {
+ const varidx &vi = ex_to<varidx>(i);
+ if (vi.is_covariant() != covariant)
+ i = vi.toggle_variance();
+ } else if (!covariant)
+ throw (std::runtime_error("index '" + get_symbol_name(i) + "' is not a varidx and cannot be contravariant"));
+
+ // Add index to an existing indexed object, or create a new indexed
+ // object if there are no indices yet
+ if (is_a<indexed>(base)) {
+ const ex &b = base.op(0);
+ exvector iv;
+ for (unsigned n=1; n<base.nops(); n++)
+ iv.push_back(base.op(n));
+ iv.push_back(i);
+ return indexed(b, iv);
+ } else
+ return indexed(base, i);
+}
+
// Get last error encountered by parser
std::string get_parser_error(void)
{