diff options
Diffstat (limited to 'parsexp.cc')
-rw-r--r-- | parsexp.cc | 1067 |
1 files changed, 0 insertions, 1067 deletions
diff --git a/parsexp.cc b/parsexp.cc deleted file mode 100644 index dcebbcd6..00000000 --- a/parsexp.cc +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * Copyright (c) 2003-2008, John Wiegley. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of New Artisans LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "parsexp.h" -#include "parser.h" - -namespace ledger { -namespace expr { - -void parser_t::token_t::parse_ident(std::istream& in) -{ - if (in.eof()) { - kind = TOK_EOF; - return; - } - assert(in.good()); - - char c = peek_next_nonws(in); - - if (in.eof()) { - kind = TOK_EOF; - return; - } - assert(in.good()); - - kind = IDENT; - length = 0; - - char buf[256]; - READ_INTO_(in, buf, 255, c, length, - std::isalnum(c) || c == '_' || c == '.' || c == '-'); - - switch (buf[0]) { - case 'a': - if (std::strcmp(buf, "and") == 0) - kind = KW_AND; - break; - case 'd': - if (std::strcmp(buf, "div") == 0) - kind = KW_DIV; - break; - case 'e': - if (std::strcmp(buf, "eq") == 0) - kind = EQUAL; - break; - case 'f': - if (std::strcmp(buf, "false") == 0) { - kind = VALUE; - value = false; - } - break; - case 'g': - if (std::strcmp(buf, "gt") == 0) - kind = GREATER; - else if (std::strcmp(buf, "ge") == 0) - kind = GREATEREQ; - break; - case 'i': - if (std::strcmp(buf, "is") == 0) - kind = EQUAL; - break; - case 'l': - if (std::strcmp(buf, "lt") == 0) - kind = LESS; - else if (std::strcmp(buf, "le") == 0) - kind = LESSEQ; - break; - case 'm': - if (std::strcmp(buf, "mod") == 0) - kind = KW_MOD; - break; - case 'n': - if (std::strcmp(buf, "ne") == 0) - kind = NEQUAL; - break; - case 'o': - if (std::strcmp(buf, "or") == 0) - kind = KW_OR; - break; - case 't': - if (std::strcmp(buf, "true") == 0) { - kind = VALUE; - value = true; - } - break; - } - - if (kind == IDENT) - value.set_string(buf); -} - -void parser_t::token_t::next(std::istream& in, const flags_t flags) -{ - if (in.eof()) { - kind = TOK_EOF; - return; - } - assert(in.good()); - - char c = peek_next_nonws(in); - - if (in.eof()) { - kind = TOK_EOF; - return; - } - assert(in.good()); - - symbol[0] = c; - symbol[1] = '\0'; - - length = 1; - - if (! (flags & EXPR_PARSE_RELAXED) && - (std::isalpha(c) || c == '_')) { - parse_ident(in); - return; - } - - switch (c) { - case '@': - in.get(c); - kind = AT_SYM; - break; - - case '&': - in.get(c); - kind = KW_AND; - break; - - case '(': - in.get(c); - kind = LPAREN; - break; - case ')': - in.get(c); - kind = RPAREN; - break; - - case '[': { - in.get(c); - if (! (flags & EXPR_PARSE_NO_DATES)) { - char buf[256]; - READ_INTO_(in, buf, 255, c, length, c != ']'); - if (c != ']') - unexpected(c, ']'); - in.get(c); - length++; - interval_t timespan(buf); - kind = VALUE; - value = timespan.first(); - } else { - kind = LBRACKET; - } - break; - } - - case ']': { - in.get(c); - kind = RBRACKET; - break; - } - - - case '\'': - case '"': { - char delim; - in.get(delim); - char buf[4096]; - READ_INTO_(in, buf, 4095, c, length, c != delim); - if (c != delim) - unexpected(c, delim); - in.get(c); - length++; - kind = VALUE; - value.set_string(buf); - break; - } - - case '{': { - in.get(c); - amount_t temp; - temp.parse(in, AMOUNT_PARSE_NO_MIGRATE); - in.get(c); - if (c != '}') - unexpected(c, '}'); - length++; - kind = VALUE; - value = temp; - break; - } - - case '!': - in.get(c); - c = in.peek(); - if (c == '=') { - in.get(c); - symbol[1] = c; - symbol[2] = '\0'; - kind = NEQUAL; - length = 2; - break; - } - kind = EXCLAM; - break; - - case '-': - in.get(c); - kind = MINUS; - break; - case '+': - in.get(c); - kind = PLUS; - break; - - case '*': - in.get(c); - kind = STAR; - break; - - case 'c': - case 'C': - case 'p': - case 'w': - case 'W': - case 'e': - case '/': { - bool code_mask = c == 'c'; - bool commodity_mask = c == 'C'; - bool payee_mask = c == 'p'; - bool note_mask = c == 'e'; - bool short_account_mask = c == 'w'; - - in.get(c); - if (c == '/') { - c = peek_next_nonws(in); - if (c == '/') { - in.get(c); - c = in.peek(); - if (c == '/') { - in.get(c); - c = in.peek(); - short_account_mask = true; - } else { - payee_mask = true; - } - } - } else { - in.get(c); - } - - // Read in the regexp - char buf[256]; - READ_INTO_(in, buf, 255, c, length, c != '/'); - if (c != '/') - unexpected(c, '/'); - in.get(c); - length++; - - if (short_account_mask) - kind = SHORT_ACCOUNT_MASK; - else if (code_mask) - kind = CODE_MASK; - else if (commodity_mask) - kind = COMMODITY_MASK; - else if (payee_mask) - kind = PAYEE_MASK; - else if (note_mask) - kind = NOTE_MASK; - else - kind = ACCOUNT_MASK; - - value.set_string(buf); - break; - } - - case '=': - in.get(c); - kind = EQUAL; - break; - - case '<': - in.get(c); - if (in.peek() == '=') { - in.get(c); - symbol[1] = c; - symbol[2] = '\0'; - kind = LESSEQ; - length = 2; - break; - } - kind = LESS; - break; - - case '>': - in.get(c); - if (in.peek() == '=') { - in.get(c); - symbol[1] = c; - symbol[2] = '\0'; - kind = GREATEREQ; - length = 2; - break; - } - kind = GREATER; - break; - - case ',': - in.get(c); - kind = COMMA; - break; - - case '.': - in.get(c); - c = in.peek(); - if (c == '.') { - in.get(c); - length++; - kind = DOTDOT; - break; - } - else if (! std::isdigit(c)) { - kind = DOT; - break; - } - in.unget(); // put the first '.' back - // fall through... - - default: - if (! (flags & EXPR_PARSE_RELAXED)) { - kind = UNKNOWN; - } else { - amount_t temp; - unsigned long pos = 0; - - // When in relaxed parsing mode, we want to migrate commodity - // flags so that any precision specified by the user updates the - // current maximum displayed precision. - pos = (long)in.tellg(); - - unsigned char parse_flags = 0; - if (flags & EXPR_PARSE_NO_MIGRATE) - parse_flags |= AMOUNT_PARSE_NO_MIGRATE; - if (flags & EXPR_PARSE_NO_REDUCE) - parse_flags |= AMOUNT_PARSE_NO_REDUCE; - - if (! temp.parse(in, parse_flags | AMOUNT_PARSE_SOFT_FAIL)) { - // If the amount had no commodity, it must be an unambiguous - // variable reference - - in.clear(); - in.seekg(pos, std::ios::beg); - - c = in.peek(); - assert(! (std::isdigit(c) || c == '.')); - parse_ident(in); - } else { - kind = VALUE; - value = temp; - } - } - break; - } -} - -void parser_t::token_t::rewind(std::istream& in) -{ - for (unsigned int i = 0; i < length; i++) - in.unget(); -} - - -void parser_t::token_t::unexpected() -{ - switch (kind) { - case TOK_EOF: - throw_(parse_error, "Unexpected end of expression"); - case IDENT: - throw_(parse_error, "Unexpected symbol '" << value << "'"); - case VALUE: - throw_(parse_error, "Unexpected value '" << value << "'"); - default: - throw_(parse_error, "Unexpected operator '" << symbol << "'"); - } -} - -void parser_t::token_t::unexpected(char c, char wanted) -{ - if ((unsigned char) c == 0xff) { - if (wanted) - throw_(parse_error, "Missing '" << wanted << "'"); - else - throw_(parse_error, "Unexpected end"); - } else { - if (wanted) - throw_(parse_error, "Invalid char '" << c << - "' (wanted '" << wanted << "')"); - else - throw_(parse_error, "Invalid char '" << c << "'"); - } -} - -ptr_op_t -parser_t::parse_value_term(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node; - - token_t& tok = next_token(in, tflags); - - switch (tok.kind) { - case token_t::VALUE: - node = new op_t(op_t::VALUE); - node->set_value(tok.value); - break; - - case token_t::SHORT_ACCOUNT_MASK: - node = new op_t(op_t::F_SHORT_ACCOUNT_MASK); - node->set_mask(tok.value.as_string()); - break; - case token_t::CODE_MASK: - node = new op_t(op_t::F_CODE_MASK); - node->set_mask(tok.value.as_string()); - break; - case token_t::COMMODITY_MASK: - node = new op_t(op_t::F_COMMODITY_MASK); - node->set_mask(tok.value.as_string()); - break; - case token_t::PAYEE_MASK: - node = new op_t(op_t::F_PAYEE_MASK); - node->set_mask(tok.value.as_string()); - break; - case token_t::NOTE_MASK: - node = new op_t(op_t::F_NOTE_MASK); - node->set_mask(tok.value.as_string()); - break; - case token_t::ACCOUNT_MASK: - node = new op_t(op_t::F_ACCOUNT_MASK); - node->set_mask(tok.value.as_string()); - break; - - case token_t::IDENT: { -#if 0 -#ifdef USE_BOOST_PYTHON - if (tok.value->as_string() == "lambda") // special - try { - char c, buf[4096]; - - std::strcpy(buf, "lambda "); - READ_INTO(in, &buf[7], 4000, c, true); - - ptr_op_t eval = new op_t(op_t::O_EVAL); - ptr_op_t lambda = new op_t(op_t::FUNCTION); - lambda->functor = new python_functor_t(python_eval(buf)); - eval->set_left(lambda); - ptr_op_t sym = new op_t(op_t::SYMBOL); - sym->name = new string("__ptr"); - eval->set_right(sym); - - node = eval; - - goto done; - } - catch(const boost::python::error_already_set&) { - throw_(parse_error, "Error parsing lambda expression"); - } -#endif /* USE_BOOST_PYTHON */ -#endif - - string ident = tok.value.as_string(); - - // An identifier followed by ( represents a function call - tok = next_token(in, tflags); - - if (tok.kind == token_t::LPAREN) { -#if 0 - node = new op_t(op_t::FUNC_NAME); - node->set_string(ident); - - ptr_op_t call_node(new op_t(op_t::O_CALL)); - call_node->set_left(node); - call_node->set_right(parse_value_expr(in, scope, - tflags | EXPR_PARSE_PARTIAL)); - - tok = next_token(in, tflags); - if (tok.kind != token_t::RPAREN) - tok.unexpected(0xff, ')'); - - node = call_node; -#endif - } else { - if (std::isdigit(ident[0])) { - node = new op_t(op_t::O_ARG); - node->set_long(lexical_cast<unsigned int>(ident.c_str())); - } else { - node = new op_t(op_t::O_LOOKUP); - node->set_string(ident); - } - push_token(tok); - } - break; - } - - case token_t::LPAREN: - node = new op_t(op_t::O_COMMA); - node->set_left(parse_value_expr(in, scope, tflags | EXPR_PARSE_PARTIAL)); - if (! node->left()) - throw_(parse_error, tok.symbol << " operator not followed by argument"); - - tok = next_token(in, tflags); - if (tok.kind != token_t::RPAREN) - tok.unexpected(0xff, ')'); - break; - - default: - push_token(tok); - break; - } - -#if 0 -#ifdef USE_BOOST_PYTHON - done: -#endif -#endif - return node; -} - -ptr_op_t -parser_t::parse_unary_expr(std::istream& in, scope_t& scope, - const flags_t tflags) const -{ - ptr_op_t node; - - token_t& tok = next_token(in, tflags); - - switch (tok.kind) { - case token_t::EXCLAM: { - ptr_op_t term(parse_value_term(in, scope, tflags)); - if (! term) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - - // A very quick optimization - if (term->kind == op_t::VALUE) { - term->as_value_lval().in_place_negate(); - node = term; - } else { - node = new op_t(op_t::O_NOT); - node->set_left(term); - } - break; - } - - case token_t::MINUS: { - ptr_op_t term(parse_value_term(in, scope, tflags)); - if (! term) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - - // A very quick optimization - if (term->kind == op_t::VALUE) { - term->as_value_lval().in_place_negate(); - node = term; - } else { - node = new op_t(op_t::O_NEG); - node->set_left(term); - } - break; - } - - default: - push_token(tok); - node = parse_value_term(in, scope, tflags); - break; - } - - return node; -} - -ptr_op_t -parser_t::parse_mul_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_unary_expr(in, scope, tflags)); - - if (node) { - token_t& tok = next_token(in, tflags); - if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) { - ptr_op_t prev(node); - node = new op_t(tok.kind == token_t::STAR ? - op_t::O_MUL : op_t::O_DIV); - node->set_left(prev); - node->set_right(parse_mul_expr(in, scope, tflags)); - if (! node->right()) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - - tok = next_token(in, tflags); - } - push_token(tok); - } - - return node; -} - -ptr_op_t -parser_t::parse_add_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_mul_expr(in, scope, tflags)); - - if (node) { - token_t& tok = next_token(in, tflags); - if (tok.kind == token_t::PLUS || - tok.kind == token_t::MINUS) { - ptr_op_t prev(node); - node = new op_t(tok.kind == token_t::PLUS ? - op_t::O_ADD : op_t::O_SUB); - node->set_left(prev); - node->set_right(parse_add_expr(in, scope, tflags)); - if (! node->right()) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - - tok = next_token(in, tflags); - } - push_token(tok); - } - - return node; -} - -ptr_op_t -parser_t::parse_logic_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_add_expr(in, scope, tflags)); - - if (node) { - op_t::kind_t kind = op_t::LAST; - flags_t _flags = tflags; - token_t& tok = next_token(in, tflags); - switch (tok.kind) { - case token_t::EQUAL: - if (tflags & EXPR_PARSE_NO_ASSIGN) - tok.rewind(in); - else - kind = op_t::O_EQ; - break; - case token_t::NEQUAL: - kind = op_t::O_NEQ; - break; - case token_t::LESS: - kind = op_t::O_LT; - break; - case token_t::LESSEQ: - kind = op_t::O_LTE; - break; - case token_t::GREATER: - kind = op_t::O_GT; - break; - case token_t::GREATEREQ: - kind = op_t::O_GTE; - break; - default: - push_token(tok); - break; - } - - if (kind != op_t::LAST) { - ptr_op_t prev(node); - node = new op_t(kind); - node->set_left(prev); - node->set_right(parse_add_expr(in, scope, _flags)); - - if (! node->right()) { - if (tok.kind == token_t::PLUS) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - else - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - } - } - } - - return node; -} - -ptr_op_t -parser_t::parse_and_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_logic_expr(in, scope, tflags)); - - if (node) { - token_t& tok = next_token(in, tflags); - if (tok.kind == token_t::KW_AND) { - ptr_op_t prev(node); - node = new op_t(op_t::O_AND); - node->set_left(prev); - node->set_right(parse_and_expr(in, scope, tflags)); - if (! node->right()) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - } else { - push_token(tok); - } - } - return node; -} - -ptr_op_t -parser_t::parse_or_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_and_expr(in, scope, tflags)); - - if (node) { - token_t& tok = next_token(in, tflags); - if (tok.kind == token_t::KW_OR) { - ptr_op_t prev(node); - node = new op_t(op_t::O_OR); - node->set_left(prev); - node->set_right(parse_or_expr(in, scope, tflags)); - if (! node->right()) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - } else { - push_token(tok); - } - } - return node; -} - -ptr_op_t -parser_t::parse_value_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_or_expr(in, scope, tflags)); - - if (node) { - token_t& tok = next_token(in, tflags); - if (tok.kind == token_t::COMMA) { - ptr_op_t prev(node); - node = new op_t(op_t::O_COMMA); - node->set_left(prev); - node->set_right(parse_value_expr(in, scope, tflags)); - if (! node->right()) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - tok = next_token(in, tflags); - } - - if (tok.kind != token_t::TOK_EOF) { - if (tflags & EXPR_PARSE_PARTIAL) - push_token(tok); - else - tok.unexpected(); - } - } - else if (! (tflags & EXPR_PARSE_PARTIAL)) { - throw_(parse_error, "Failed to parse value expression"); - } - - return node; -} - -bool op_t::print(std::ostream& out, print_context_t& context) const -{ - bool found = false; - - if (context.start_pos && this == context.op_to_find) { - *context.start_pos = (long)out.tellp() - 1; - found = true; - } - - string symbol; - - switch (kind) { - case VALUE: { - as_value().print(out, context.relaxed); - break; - } - -#if 0 - case FUNC_NAME: - out << as_string(); - break; - - case ATTR_NAME: - out << '@' << as_string(); - break; - - case VAR_NAME: - out << '$' << as_string(); - break; -#endif - - case FUNCTION: - out << "<FUNCTION>"; - break; - - case ARG_INDEX: - out << '@' << as_long(); - break; - - case O_NOT: - out << "!"; - if (left() && left()->print(out, context)) - found = true; - break; - case O_NEG: - out << "-"; - if (left() && left()->print(out, context)) - found = true; - break; - - case O_ADD: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " + "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_SUB: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " - "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_MUL: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " * "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_DIV: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " / "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_NEQ: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " != "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_EQ: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " == "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_LT: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " < "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_LTE: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " <= "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_GT: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " > "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_GTE: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " >= "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_AND: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " & "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_OR: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " | "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_COMMA: - if (left() && left()->print(out, context)) - found = true; - out << ", "; - if (right() && right()->print(out, context)) - found = true; - break; - -#if 0 - case O_CALL: - if (left() && left()->print(out, context)) - found = true; - out << "("; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; -#endif - - case LAST: - default: - assert(false); - break; - } - - if (! symbol.empty()) { - if (amount_t::current_pool->find(symbol)) - out << '@'; - out << symbol; - } - - if (context.end_pos && this == context.op_to_find) - *context.end_pos = (long)out.tellp() - 1; - - return found; -} - -void op_t::dump(std::ostream& out, const int depth) const -{ - out.setf(std::ios::left); - out.width(10); - out << this << " "; - - for (int i = 0; i < depth; i++) - out << " "; - - switch (kind) { - case VALUE: - out << "VALUE - " << as_value(); - break; - -#if 0 - case ATTR_NAME: - out << "ATTR_NAME - " << as_string(); - break; - - case FUNC_NAME: - out << "FUNC_NAME - " << as_string(); - break; - - case VAR_NAME: - out << "VAR_NAME - " << as_string(); - break; -#endif - - case ARG_INDEX: - out << "ARG_INDEX - " << as_long(); - break; - - case FUNCTION: - out << "FUNCTION"; - break; - -#if 0 - case O_CALL: out << "O_CALL"; break; -#endif - - case O_NOT: out << "O_NOT"; break; - case O_NEG: out << "O_NEG"; break; - - case O_ADD: out << "O_ADD"; break; - case O_SUB: out << "O_SUB"; break; - case O_MUL: out << "O_MUL"; break; - case O_DIV: out << "O_DIV"; break; - - case O_NEQ: out << "O_NEQ"; break; - case O_EQ: out << "O_EQ"; break; - case O_LT: out << "O_LT"; break; - case O_LTE: out << "O_LTE"; break; - case O_GT: out << "O_GT"; break; - case O_GTE: out << "O_GTE"; break; - - case O_AND: out << "O_AND"; break; - case O_OR: out << "O_OR"; break; - - case O_COMMA: out << "O_COMMA"; break; - - case LAST: - default: - assert(false); - break; - } - - out << " (" << refc << ')' << std::endl; - - if (kind > TERMINALS) { - if (left()) { - left()->dump(out, depth + 1); - if (right()) - right()->dump(out, depth + 1); - } else { - assert(! right()); - } - } -} - -} // namespace expr -} // namespace ledger |