X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Finput_parser.yy;h=b28e63a1e552b34241b9cf1d5060047f922c3fc7;hp=9c4ffd971ac66b89902631818862e949368f7900;hb=ff09c4f8103f53fe3b7a51eb3c33eff2e5a243f0;hpb=08d556dc3ac3fbf2b0ad3acd37016a1f925d7c02 diff --git a/ginac/input_parser.yy b/ginac/input_parser.yy index 9c4ffd97..b28e63a1 100644 --- a/ginac/input_parser.yy +++ b/ginac/input_parser.yy @@ -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-2008 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 @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -29,19 +29,20 @@ %{ #include -#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,24 @@ 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(*($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 if (n == "pow" || n == "power") { + if ($3.nops() != 2) + throw std::invalid_argument("wrong number of arguments to pow()"); + $$ = power($3.op(0), $3.op(0)); + } else { + unsigned i = function::find_function(n, $3.nops()); + $$ = function(i, ex_to($3)).eval(1); + } } | exp T_EQUAL exp {$$ = $1 == $3;} | exp T_NOTEQ exp {$$ = $1 != $3;} @@ -112,14 +127,16 @@ 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;} - | T_MATRIX_BEGIN matrix T_MATRIX_END {$$ = lst_to_matrix(ex_to_lst($2));} + | '{' list_or_empty '}' {$$ = $2;} + | '[' matrix ']' {$$ = lst_to_matrix(ex_to($2));} ; exprseq : exp {$$ = exprseq($1);} - | exprseq ',' exp {exprseq es(static_cast(*($1.bp))); $$ = es.append($3);} + | exprseq ',' exp {exprseq es(ex_to($1)); $$ = es.append($3);} ; list_or_empty: /* empty */ {$$ = *new lst;} @@ -127,15 +144,15 @@ list_or_empty: /* empty */ {$$ = *new lst;} ; list : exp {$$ = lst($1);} - | list ',' exp {lst l(static_cast(*($1.bp))); $$ = l.append($3);} + | list ',' exp {lst l(ex_to($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(*($1.bp))); $$ = l.append($4);} +matrix : '[' row ']' {$$ = lst($2);} + | matrix ',' '[' row ']' {lst l(ex_to($1)); $$ = l.append($4);} ; row : exp {$$ = lst($1);} - | row ',' exp {lst l(static_cast(*($1.bp))); $$ = l.append($3);} + | row ',' exp {lst l(ex_to($1)); $$ = l.append($3);} ; @@ -144,21 +161,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(i)) { + const varidx &vi = ex_to(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(base)) { + const ex &b = base.op(0); + exvector iv; + for (unsigned n=1; n