Minor simplifications to valexpr parser

The most significant change is the way CONS sequences are parsed, and
that now instead of =/:=, the operators are ==/=.
This commit is contained in:
John Wiegley 2010-09-05 01:38:47 -04:00
parent 9fcf484826
commit e162455ebb
10 changed files with 79 additions and 96 deletions

View file

@ -998,7 +998,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
if (! symbol.empty())
comm_flags |= COMMODITY_STYLE_SUFFIXED;
if (! in.eof() && ((n = static_cast<char>(in.peek())) != '\n'))
if (! flags.has_flags(PARSE_NO_ANNOT) &&
! in.eof() && ((n = static_cast<char>(in.peek())) != '\n'))
details.parse(in);
}
} else {
@ -1010,7 +1011,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
parse_quantity(in, quant);
if (! quant.empty() && ! in.eof() &&
if (! flags.has_flags(PARSE_NO_ANNOT) &&
! quant.empty() && ! in.eof() &&
((n = static_cast<char>(in.peek())) != '\n'))
details.parse(in);
}

View file

@ -72,7 +72,7 @@ enum parse_flags_enum_t {
PARSE_NO_MIGRATE = 0x04,
PARSE_NO_REDUCE = 0x08,
PARSE_NO_ASSIGN = 0x10,
PARSE_NO_DATES = 0x20,
PARSE_NO_ANNOT = 0x20,
PARSE_OP_CONTEXT = 0x40,
PARSE_SOFT_FAIL = 0x80
};

View file

@ -42,8 +42,10 @@ void push_sort_value(std::list<sort_value_t>& sort_values,
expr_t::ptr_op_t node, scope_t& scope)
{
if (node->kind == expr_t::op_t::O_CONS) {
push_sort_value(sort_values, node->left(), scope);
push_sort_value(sort_values, node->right(), scope);
while (node && node->kind == expr_t::op_t::O_CONS) {
push_sort_value(sort_values, node->left(), scope);
node = node->right();
}
} else {
bool inverted = false;
@ -54,7 +56,7 @@ void push_sort_value(std::list<sort_value_t>& sort_values,
sort_values.push_back(sort_value_t());
sort_values.back().inverted = inverted;
sort_values.back().value = expr_t(node).calc(scope).simplified();
sort_values.back().value = expr_t(node).calc(scope).simplified();
if (sort_values.back().value.is_null())
throw_(calc_error,

View file

@ -167,22 +167,38 @@ value_t source_command(call_scope_t& args)
{
std::istream * in = NULL;
scoped_ptr<ifstream> stream;
string pathname;
if (args.has(0)) {
stream.reset(new ifstream(path(args.get<string>(0))));
pathname = args.get<string>(0);
stream.reset(new ifstream(path(pathname)));
in = stream.get();
} else {
pathname = "<stdin>";
in = &std::cin;
}
symbol_scope_t file_locals(args);
symbol_scope_t file_locals(args);
std::size_t linenum = 0;
char buf[4096];
istream_pos_type pos;
while (in->good() && ! in->eof()) {
char buf[4096];
pos = in->tellg();
in->getline(buf, 4095);
linenum++;
if (buf[0] != ';')
expr_t(buf).calc(file_locals);
char * p = skip_ws(buf);
if (*p && *p != ';') {
try {
expr_t(p).calc(file_locals);
}
catch (const std::exception&) {
add_error_context(_("While parsing value expression on line %1:")
<< linenum);
add_error_context(source_context(pathname, pos, in->tellg(), "> "));
}
}
}
return true;

View file

@ -191,8 +191,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
assert(left()->kind == O_CALL);
ptr_op_t sym = left()->right();
if (sym->kind == O_SEQ)
sym = sym->left();
symbol_scope_t call_scope(call_args);
@ -242,8 +240,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
case O_CALL: {
call_scope_t call_args(scope, locus, depth);
if (has_right())
call_args.set_args(split_cons_expr(right()->kind == O_SEQ ?
right()->left() : right()));
call_args.set_args(split_cons_expr(right()));
ptr_op_t func = left();
const string& name(func->as_ident());
@ -474,6 +471,9 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
string symbol;
if (kind > TERMINALS && (kind != O_CALL && kind != O_DEFINE))
out << '(';
switch (kind) {
case VALUE:
as_value().dump(out, context.relaxed);
@ -488,118 +488,94 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
break;
case O_NOT:
out << "!(";
out << "! ";
if (left() && left()->print(out, context))
found = true;
out << ")";
break;
case O_NEG:
out << "-(";
out << "- ";
if (left() && left()->print(out, context))
found = true;
out << ")";
break;
case O_ADD:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " + ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_SUB:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " - ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_MUL:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " * ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_DIV:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " / ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_EQ:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " == ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_LT:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " < ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_LTE:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " <= ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_GT:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " > ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_GTE:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " >= ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_AND:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " & ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_OR:
out << "(";
if (left() && left()->print(out, context))
found = true;
out << " | ";
if (has_right() && right()->print(out, context))
found = true;
out << ")";
break;
case O_QUERY:
@ -623,15 +599,13 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
break;
case O_SEQ:
out << "(";
found = print_seq(out, this, context);
out << ")";
break;
case O_DEFINE:
if (left() && left()->print(out, context))
found = true;
out << " := ";
out << " = ";
if (has_right() && right()->print(out, context))
found = true;
break;
@ -648,7 +622,7 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
if (left() && left()->print(out, context))
found = true;
if (has_right()) {
if (right()->kind == O_SEQ) {
if (right()->kind == O_CONS) {
if (right()->print(out, context))
found = true;
} else {
@ -676,6 +650,9 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
break;
}
if (kind > TERMINALS && (kind != O_CALL && kind != O_DEFINE))
out << ')';
if (! symbol.empty()) {
if (commodity_pool_t::current_pool->find(symbol))
out << '@';

View file

@ -65,9 +65,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
push_token(tok); // let the parser see it again
node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE)));
if (node->has_right() && node->right()->kind == op_t::O_CONS)
node->set_right(node->right()->left());
} else {
push_token(tok);
}
@ -78,12 +75,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL)
.minus_flags(PARSE_SINGLE));
tok = next_token(in, tflags, ')');
if (node && node->kind == op_t::O_CONS) {
ptr_op_t prev(node);
node = new op_t(op_t::O_SEQ);
node->set_left(prev);
}
break;
default:
@ -437,33 +428,37 @@ expr_t::parser_t::parse_value_expr(std::istream& in,
ptr_op_t node(parse_querycolon_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
ptr_op_t next;
while (true) {
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
if (tok.kind == token_t::COMMA || tok.kind == token_t::SEMI) {
bool comma_op = tok.kind == token_t::COMMA;
if (tok.kind == token_t::COMMA || tok.kind == token_t::SEMI) {
bool comma_op = tok.kind == token_t::COMMA;
ptr_op_t prev(node);
node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
node->set_left(prev);
node->set_right(parse_value_expr(in, tflags));
if (! node->right())
throw_(parse_error,
_("%1 operator not followed by argument") << tok.symbol);
if (! next) {
ptr_op_t prev(node);
node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
node->set_left(prev);
tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
}
next = node;
}
if (tok.kind != token_t::TOK_EOF) {
if (tflags.has_flags(PARSE_PARTIAL))
token_t& ntok = next_token(in, tflags);
push_token(ntok);
if (ntok.kind == token_t::RPAREN)
break;
ptr_op_t chain(new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ));
chain->set_left(parse_querycolon_expr(in, tflags));
next->set_right(chain);
next = chain;
} else {
push_token(tok);
else
tok.unexpected();
break;
}
}
}
else if (! tflags.has_flags(PARSE_PARTIAL) &&
! tflags.has_flags(PARSE_SINGLE)) {
throw_(parse_error, _("Failed to parse value expression"));
}
return node;
}

View file

@ -295,7 +295,6 @@ internal precision."))
.value("NoMigrate", PARSE_NO_MIGRATE)
.value("NoReduce", PARSE_NO_REDUCE)
.value("NoAssign", PARSE_NO_ASSIGN)
.value("NoDates", PARSE_NO_DATES)
.value("OpContext", PARSE_OP_CONTEXT)
.value("SoftFail", PARSE_SOFT_FAIL)
;

View file

@ -561,6 +561,7 @@ value_t report_t::fn_print(call_scope_t& args)
{
for (std::size_t i = 0; i < args.size(); i++)
args[i].print(output_stream);
static_cast<std::ostream&>(output_stream) << std::endl;
return true;
}

View file

@ -60,8 +60,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 'd':
if (std::strcmp(buf, "div") == 0) {
symbol[0] = '/';
symbol[1] = '/';
symbol[2] = '\0';
symbol[1] = '\0';
kind = KW_DIV;
return 1;
}
@ -69,9 +68,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 'e':
if (std::strcmp(buf, "else") == 0) {
symbol[0] = 'L';
symbol[1] = 'S';
symbol[2] = '\0';
std::strcpy(symbol, "else");
kind = KW_ELSE;
return 1;
}
@ -79,6 +76,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 'f':
if (std::strcmp(buf, "false") == 0) {
std::strcpy(symbol, "false");
kind = VALUE;
value = false;
return 1;
@ -115,6 +113,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 't':
if (std::strcmp(buf, "true") == 0) {
std::strcpy(symbol, "true");
kind = VALUE;
value = true;
return 1;
@ -231,6 +230,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
break;
}
#if 0
case '{': {
in.get(c);
amount_t temp;
@ -243,6 +243,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
value = temp;
break;
}
#endif
case '!':
in.get(c);
@ -287,14 +288,6 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
case ':':
in.get(c);
c = static_cast<char>(in.peek());
if (c == '=') {
in.get(c);
symbol[1] = c;
symbol[2] = '\0';
kind = DEFINE;
length = 2;
break;
}
kind = COLON;
break;
@ -336,7 +329,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
length = 2;
break;
}
kind = EQUAL;
kind = DEFINE;
break;
case '<':
@ -403,6 +396,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
// maximum displayed precision.
parse_flags_t parse_flags;
parse_flags.add_flags(PARSE_NO_ANNOT);
if (pflags.has_flags(PARSE_NO_MIGRATE))
parse_flags.add_flags(PARSE_NO_MIGRATE);
if (pflags.has_flags(PARSE_NO_REDUCE))

View file

@ -94,7 +94,7 @@ struct expr_t::token_t : public noncopyable
} kind;
char symbol[3];
char symbol[6];
value_t value;
std::size_t length;
@ -113,13 +113,10 @@ struct expr_t::token_t : public noncopyable
}
void clear() {
kind = UNKNOWN;
length = 0;
value = NULL_VALUE;
kind = UNKNOWN;
length = 0;
value = NULL_VALUE;
symbol[0] = '\0';
symbol[1] = '\0';
symbol[2] = '\0';
}
int parse_reserved_word(std::istream& in);