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:
parent
9fcf484826
commit
e162455ebb
10 changed files with 79 additions and 96 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
26
src/expr.cc
26
src/expr.cc
|
|
@ -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;
|
||||
|
|
|
|||
45
src/op.cc
45
src/op.cc
|
|
@ -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 << '@';
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
22
src/token.cc
22
src/token.cc
|
|
@ -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))
|
||||
|
|
|
|||
11
src/token.h
11
src/token.h
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue