]> www.ginac.de Git - ginac.git/blobdiff - ginac/input_parser.yy
mention the "dummy()" function option
[ginac.git] / ginac / input_parser.yy
index 561b0693ed3038d25cc827ca2775181d3e145157..9f22814dc95a38350082083c151c8914351fde21 100644 (file)
@@ -4,7 +4,7 @@
  *  This file must be processed with yacc/bison. */
 
 /*
- *  GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 %{
 #include <stdexcept>
 
-#include "input_lexer.h"
 #include "ex.h"
+#include "input_lexer.h"
 #include "relational.h"
+#include "operators.h"
 #include "symbol.h"
 #include "lst.h"
 #include "power.h"
 #include "exprseq.h"
+#include "idx.h"
+#include "indexed.h"
 #include "matrix.h"
 #include "inifcns.h"
 
-#ifndef NO_NAMESPACE_GINAC
 namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
 
 #define YYERROR_VERBOSE 1
 
@@ -50,11 +51,14 @@ 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
    of class numeric or symbol (e.g. a constant or the FAIL object)) */
-%token T_NUMBER T_SYMBOL T_LITERAL T_DIGITS T_EQUAL T_NOTEQ T_LESSEQ T_GREATEREQ T_MATRIX_BEGIN T_MATRIX_END
+%token T_EOF T_NUMBER T_SYMBOL T_LITERAL T_DIGITS T_EQUAL T_NOTEQ T_LESSEQ T_GREATEREQ
 
 /* Operator precedence and associativity */
 %right '='
@@ -64,6 +68,7 @@ static std::string parser_error;
 %left '*' '/' '%'
 %nonassoc NEG
 %right '^'
+%left '.' '~'
 %nonassoc '!'
 
 %start input
@@ -74,7 +79,7 @@ static std::string parser_error;
  */
 
 %%
-input  : exp {
+input  : exp T_EOF {
                try {
                        parsed_ex = $1;
                        YYACCEPT;
@@ -83,7 +88,6 @@ input : exp {
                        YYERROR;
                }
        }
-       | error         {yyclearin; yyerrok;}
        ;
 
 exp    : T_NUMBER              {$$ = $1;}
@@ -91,13 +95,20 @@ exp : T_NUMBER              {$$ = $1;}
                if (is_lexer_symbol_predefined($1))
                        $$ = $1.eval();
                else
-                       throw (std::runtime_error("unknown symbol '" + ex_to_symbol($1).getname() + "'"));
+                       throw (std::runtime_error("unknown symbol '" + get_symbol_name($1) + "'"));
        }
        | T_LITERAL             {$$ = $1;}
        | T_DIGITS              {$$ = $1;}
        | T_SYMBOL '(' exprseq ')' {
-               unsigned i = function::find_function(ex_to_symbol($1).getname(), $3.nops());
-               $$ = function(i, static_cast<const exprseq &>(*($3.bp))).eval(1);
+               std::string n = get_symbol_name($1);
+               if (n == "sqrt") {
+                       if ($3.nops() != 1)
+                               throw (std::runtime_error("too many arguments to sqrt()"));
+                       $$ = sqrt($3.op(0));
+               } else {
+                       unsigned i = function::find_function(n, $3.nops());
+                       $$ = function(i, ex_to<exprseq>($3)).eval(1);
+               }
        }
        | exp T_EQUAL exp       {$$ = $1 == $3;}
        | exp T_NOTEQ exp       {$$ = $1 != $3;}
@@ -109,18 +120,19 @@ exp       : T_NUMBER              {$$ = $1;}
        | exp '-' exp           {$$ = $1 - $3;}
        | exp '*' exp           {$$ = $1 * $3;}
        | exp '/' exp           {$$ = $1 / $3;}
-       | exp '%' exp           {$$ = $1 % $3;}
        | '-' 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;}
-       | T_MATRIX_BEGIN matrix T_MATRIX_END    {$$ = lst_to_matrix($2);}
+       | '{' list_or_empty '}' {$$ = $2;}
+       | '[' matrix ']'        {$$ = lst_to_matrix(ex_to<lst>($2));}
        ;
 
 exprseq        : exp                   {$$ = exprseq($1);}
-       | exprseq ',' exp       {exprseq es(static_cast<exprseq &>(*($1.bp))); $$ = es.append($3);}
+       | exprseq ',' exp       {exprseq es(ex_to<exprseq>($1)); $$ = es.append($3);}
        ;
 
 list_or_empty: /* empty */     {$$ = *new lst;}
@@ -128,15 +140,15 @@ list_or_empty: /* empty */        {$$ = *new lst;}
        ;
 
 list   : exp                   {$$ = lst($1);}
-       | list ',' exp          {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
+       | list ',' exp          {lst l(ex_to<lst>($1)); $$ = l.append($3);}
        ;
 
-matrix : T_MATRIX_BEGIN row T_MATRIX_END               {$$ = lst($2);}
-       | matrix ',' T_MATRIX_BEGIN row T_MATRIX_END    {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($4);}
+matrix : '[' row ']'           {$$ = lst($2);}
+       | matrix ',' '[' row ']' {lst l(ex_to<lst>($1)); $$ = l.append($4);}
        ;
 
 row    : exp                   {$$ = lst($1);}
-       | row ',' exp           {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
+       | row ',' exp           {lst l(ex_to<lst>($1)); $$ = l.append($3);}
        ;
 
 
@@ -145,20 +157,41 @@ 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)
 {
        return parser_error;
 }
 
-#ifndef NO_NAMESPACE_GINAC
 } // namespace GiNaC
 
-using GiNaC::parser_error;
-#endif // ndef NO_NAMESPACE_GINAC
-
 // Error print routine (store error string in parser_error)
 int ginac_yyerror(char *s)
 {
-       parser_error = std::string(s) + " at " + std::string(ginac_yytext);
+       GiNaC::parser_error = std::string(s) + " at " + std::string(ginac_yytext);
+       return 0;
 }