xo-reader2: bugfix: need pattern match to fix operator precedence

This commit is contained in:
Roland Conybeare 2026-02-23 07:04:54 +11:00
commit d6456ce921
3 changed files with 192 additions and 10 deletions

View file

@ -5,6 +5,7 @@
#include "ExpectExprSsm.hpp"
#include "ParserStateMachine.hpp"
#include "ParserStack.hpp"
#include "SyntaxStateMachine.hpp"
#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp"
#include "DSequenceSsm.hpp"
@ -28,15 +29,10 @@
#include "paren_xs.hpp"
#include "sequence_xs.hpp"
#include "progress_xs.hpp"
#include "xo/expression/Lambda.hpp"
#include "xo/expression/Constant.hpp"
#include "xo/expression/pretty_expression.hpp"
#endif
namespace xo {
#ifdef NOT_YET
using xo::scm::Constant;
#endif
using xo::scm::DFloat;
using xo::mm::AGCObject;
@ -372,6 +368,32 @@ namespace xo {
auto expr = DConstant::make(p_psm->expr_alloc(), i64o);
// Consider parser stack, with control here at b
//
// a * b - c
// ^
//
// [1] ExpectExpr <-- this
// [0] ProgressSsm :lhs k(b) :op * :rhs _
//
// if parent is ProgressSsm [0], need to deliver k(b) to it;
// Then let that ProgressSsm [0] establish whether next token
// is operator.
//
assert((void*)p_psm->stack()->top().data() == (void*)this);
if (p_psm->stack()->parent()) {
auto parent_ssm = (obj<ASyntaxStateMachine,DProgressSsm>::from
(p_psm->stack()->parent()->top()));
if (parent_ssm) {
// parent is-a DProgressSsm instance
p_psm->pop_ssm();
p_psm->on_parsed_expression(expr);
return;
}
}
// DProgressSsm responsible for resolving cases like
// 1,
// 1;

View file

@ -125,13 +125,13 @@ namespace xo {
return optype::op_add;
case tokentype::tk_minus: // [-]
return optype::op_subtract;
case tokentype::tk_star: // [*]
case tokentype::tk_star: // [*]
return optype::op_multiply;
case tokentype::tk_slash: // [/]
case tokentype::tk_slash: // [/]
return optype::op_divide;
case tokentype::tk_cmpeq: // [==]
case tokentype::tk_cmpeq: // [==]
return optype::op_equal;
case tokentype::tk_cmpne:
case tokentype::tk_cmpne: // [!=]
return optype::op_not_equal;
case tokentype::tk_leftangle:
return optype::op_less;
@ -362,7 +362,12 @@ namespace xo {
ParserStateMachine * p_psm)
{
if (op_type_ == optype::invalid) {
// tk is the operator this instance was waiting for
// tk is the operator this instance was waiting for.
// But need to consider precedence.
// possibly need to take lhs_ expression and rotate it into new lhs of
// surrounding ProgressSsm
this->op_type_ = tk2op(tk.tk_type());
DExpectExprSsm::start(p_psm);
@ -393,6 +398,7 @@ namespace xo {
lhs2,
op_type2,
p_psm);
DExpectExprSsm::start(p_psm);
return;
} else {
/* associate to the right
@ -512,6 +518,19 @@ namespace xo {
log && log("accepting expr1");
this->lhs_ = expr;
return;
}
assert (op_type_ != optype::invalid);
if (!rhs_) {
this->rhs_ = expr;
// need next token before we know whether this DProgressSsm
// is complete. Consider input like 7 + 2 * 3 vs 7 * 2 + 3
//
return;
}