X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fparser%2Fparser.cpp;h=6411ba1416e740a85705ceee3153815b33e9364f;hp=b33261c2c9ed1084ca3296c767d6c9a585a5d384;hb=1261c54df6548cf558405a118b2134805f63376d;hpb=1222eac51cee964961d2aad889dc4ceccb144a36 diff --git a/ginac/parser/parser.cpp b/ginac/parser/parser.cpp index b33261c2..6411ba14 100644 --- a/ginac/parser/parser.cpp +++ b/ginac/parser/parser.cpp @@ -30,7 +30,7 @@ ex parser::parse_identifier_expr() break; if (token != ',') - throw std::invalid_argument("Expected ')' or ',' in argument list"); + Parse_error("expected ')' or ',' in argument list"); get_next_tok(); } @@ -40,9 +40,8 @@ ex parser::parse_identifier_expr() prototype the_prototype = make_pair(name, args.size()); prototype_table::const_iterator reader = funcs.find(the_prototype); if (reader == funcs.end()) { - bail_out(std::invalid_argument, - "no function \"" << name << "\" with " << args.size() - << " arguments"); + Parse_error_("no function \"" << name << "\" with " << + args.size() << " arguments"); } ex ret = reader->second(args); return ret; @@ -55,30 +54,31 @@ ex parser::parse_paren_expr() ex e = parse_expression(); if (token != ')') - throw std::invalid_argument("parser::parse_paren_expr: expected ')'"); + Parse_error("expected ')'"); get_next_tok(); // eat ). return e; } extern numeric* _num_1_p; +extern ex _ex0; /// unary_expr: [+-] expression -ex parser::parse_unary_expr(const int s) +ex parser::parse_unary_expr() { - // consume '-' (or '+') - get_next_tok(); - ex v = parse_expression(); - switch (s) { - case '-': - return (new mul(v, *_num_1_p))->setflag(status_flags::dynallocated); - case '+': - return v; - default: - throw std::invalid_argument( - std::string(__func__) - + ": invalid unary operator \"" - + char(s) + "\""); - } + // Unlike most other parse_* method this one does NOT consume + // current token so parse_binop_rhs() knows what kind of operator + // is being parsed. + + // There are different kinds of expressions which need to be handled: + // -a+b + // -(a) + // +a + // +(a) + // Delegete the work to parse_binop_rhs(), otherwise we end up + // duplicating it here. + ex lhs = _ex0; // silly trick + ex e = parse_binop_rhs(0, lhs); + return e; } /// primary: identifier_expr | number_expr | paren_expr | unary_expr @@ -92,18 +92,13 @@ ex parser::parse_primary() case '(': return parse_paren_expr(); case '-': - return parse_unary_expr('-'); case '+': - return parse_unary_expr('+'); + return parse_unary_expr(); case lexer::token_type::literal: return parse_literal_expr(); case lexer::token_type::eof: - bail_out(std::invalid_argument, "got EOF while parsing the expression"); default: - bail_out(std::invalid_argument, "unknown token " << - token << " (\"" << - (token ? std::string("") + char(token) : "NULL") - << "\")"); + Parse_error("unexpected token"); } } @@ -126,6 +121,7 @@ ex parser::parse_number_expr() /// literal_expr: 'I' | 'Pi' | 'Euler' | 'Catalan' ex parser::parse_literal_expr() { + get_next_tok(); // consume the literal if (scanner->str == "I") return I; else if (scanner->str == "Pi") @@ -142,6 +138,13 @@ ex parser::operator()(std::istream& input) scanner->switch_input(&input); get_next_tok(); ex ret = parse_expression(); + // parse_expression() stops if it encounters an unknown token. + // This is not a bug: since the parser is recursive checking + // whether the next token is valid is responsibility of the caller. + // Hence make sure nothing is left in the stream: + if (token != lexer::token_type::eof) + Parse_error("expected EOF"); + return ret; } @@ -158,9 +161,9 @@ int parser::get_next_tok() return token; } -parser::parser(const symtab& syms_, const prototype_table& funcs_, - const bool strict_) : strict(strict_), funcs(funcs_), - syms(syms_) +parser::parser(const symtab& syms_, const bool strict_, + const prototype_table& funcs_) : strict(strict_), + funcs(funcs_), syms(syms_) { scanner = new lexer(); }