You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JISON编写简单语法时解析'('报Syntax error问题咨询

问题根因

该报错是语法产生式设计缺陷导致,和词法规则无关——既然你已经确认词法分析可以正确输出所有token(对应序列为{、CALL、IDENTIFIER(add)、(、NUMBER(2)、,、NUMBER(3)、)、}),就不需要在词法逻辑上浪费时间。
核心问题是语法规则没有覆盖「被调用对象(标识符/表达式)后跟左括号」的函数调用结构:解析器处理到add标识符时,会按照现有规则将其归约为合法的表达式/语句片段,之后读取到下一个token(时,会检查当前语法状态下(是否为合法的后续token——如果你的语法里没有定义任何匹配Xxx '(' ...的产生式,解析器没有可用的移进/归约动作,就会直接在(位置抛出语法错误,和你遇到的报错位置完全吻合。

常见错误场景与修复方案

1. call语句规则设计错误

如果你的语法中把call关键字的调用规则写成了直接跟参数列表,就会出现这个问题:

// 错误写法:期望call后直接接左括号,和`call add(2,3)`的结构不匹配
stmt: CALL '(' argList ')'

修复方案:调整规则,让call后接实际的调用表达式:

stmt: CALL call_expr
;
// 如果仅支持直接调用标识符函数,用这个规则即可
call_expr: IDENTIFIER '(' argList? ')'

2. 通用表达式规则缺失后缀调用产生式(90%以上同类报错的原因)

如果你把call设计为通用的调用关键字,后面可以接任意表达式,大概率是表达式规则漏写了函数调用的后缀匹配:

// 错误写法:expr仅支持字面量、标识符、call后跟expr,没有定义expr后接(的结构
expr:
    NUMBER
  | STRING
  | IDENTIFIER
  | CALL expr
;

修复方案:用左递归补全后缀函数调用规则,同时在优先级声明部分把函数调用的优先级设为最高(放在所有运算符声明的最前面),避免LALR解析出现移进/归约冲突:

// 优先级声明,越靠上优先级越高
%left '(' ')'
%left '*' '/'
%left '+' '-'

expr:
    NUMBER
  | STRING
  | IDENTIFIER
  | expr '(' argList? ')' // 补全这行,支持任意表达式后跟括号的调用形式
  | CALL expr
;

// 参数列表规则
argList:
    expr (',' expr)*
;

3. 左括号优先级配置错误

如果你已经写了上述函数调用规则,但JISON编译语法文件时出现shift/reduce冲突,通常是(的优先级配置过低,导致解析器无法判断是要做函数调用归约还是做其他表达式运算,把'(' ')'的优先级声明移到所有运算符优先级声明的最顶部即可解决。

验证方式

修复后重新生成解析器,只要你的块规则是block: '{' stmt* '}',即可正常解析测试文本:

{
    call add(2, 3)
}

解析后的结构为:代码块 -> call语句 -> 函数调用add -> 参数2、参数3。

内容的提问来源于stack exchange,提问作者user18303981

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:00:58