the input parser now handles (simple) indexed objects; the indices to be used
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 12 Jul 2002 18:08:49 +0000 (18:08 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 12 Jul 2002 18:08:49 +0000 (18:08 +0000)
have to be specified in the same list as the symbols

ginac/ex.h
ginac/input_lexer.h
ginac/input_lexer.ll
ginac/input_parser.yy

index f59cd7a..9f3dd6b 100644 (file)
@@ -89,10 +89,11 @@ public:
        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
index b7cc3c0..ed3f94c 100644 (file)
@@ -50,6 +50,9 @@ class ex;
 /** 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);
 
index 6396248..4a5a650 100644 (file)
@@ -39,6 +39,7 @@
 #include "numeric.h"
 #include "symbol.h"
 #include "lst.h"
+#include "idx.h"
 
 using namespace GiNaC;
 namespace GiNaC {
@@ -47,7 +48,7 @@ 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) {}
@@ -166,22 +167,34 @@ void set_lexer_string(const std::string &s)
        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
index d3ffd19..c5c78d2 100644 (file)
@@ -36,6 +36,8 @@
 #include "lst.h"
 #include "power.h"
 #include "exprseq.h"
+#include "idx.h"
+#include "indexed.h"
 #include "matrix.h"
 #include "inifcns.h"
 
@@ -48,6 +50,9 @@ ex parsed_ex;
 
 // 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
@@ -62,6 +67,7 @@ static std::string parser_error;
 %left '*' '/' '%'
 %nonassoc NEG
 %right '^'
+%left '.' '~'
 %nonassoc '!'
 
 %start input
@@ -89,12 +95,12 @@ exp : T_NUMBER              {$$ = $1;}
                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()"));
@@ -117,6 +123,8 @@ exp : T_NUMBER              {$$ = $1;}
        | '-' 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;}
@@ -149,6 +157,30 @@ row        : exp                   {$$ = lst($1);}
  */
 
 %%
+// 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)
 {