grammar Expr;
// parser rules
prog : ((decl_list expr | expr) ';' NEWLINE?)*;
decl_list : decl decl_list
| decl
;
decl : DEF fun var_list '=' expr ENDEF
| DEF fun '=' expr ENDEF
;
var_list : param var_list
| param
;
expr : LET var '=' expr IN # assignExpr
| fun '()' # callExpr
| fun '(' expr_list ')' # callExpr
| expr ('*'|'/') expr # infixExpr
| expr ('+'|'-') expr # infixExpr
| '(' expr ')' # parensExpr
| num # numberExpr
| '~' expr # negateExpr
| var # varExpr
;
expr_list : expr',' expr_list
| expr
;
num : '-'? INT
| '-'? FLOAT
;
var : STR ('_' | '-') var
| STR
;
fun : STR ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') fun
| STR
;
param : STR '_' param
| STR
;
// lexer rules
NEWLINE: [\r\n]+ ;
INT: [0-9]+ ; // should handle negatives
FLOAT: [0-9]+'.'[0-9]* ; // should handle signs(+/-)
WS: [ \t\r\n]+ -> skip;
DEF: 'def';
ENDEF: 'endef';
LET: 'let';
IN: 'in';
STR: [a-zA-Z]+;
我正在尝试使用antlr4制作f1vae解释器。 解析器以 prog 开始。 当我放置此内容时,decl_list 部分出现问题:
def f = 3 endef def g x y = x + y endef let x = f() in g(1,x);
line 1:8 no viable alternative at input 'deff=3'
line 1:6 mismatched input '=' expecting {';', '*', '/', '+', '-'}
为什么词法分析器将 def f = 3 视为“deff=3”,而不是 decl? 它没有捕获词法分析器规则中的 DEF = 'def' 。 问题是什么?似乎没有重叠的词法分析器规则。
您看到“deff=3”的原因是您跳过了空格,因此解析器看不到它们。 (这不是“错误”;这是很常见的做法,但它解释了错误消息)。
词法分析器可以很好地处理该输入。以下是前几个标记:
[@0,0:2='def',<'def'>,1:0]
[@1,4:4='f',<STR>,1:4]
[@2,6:6='=',<'='>,1:6]
[@3,8:8='3',<'3'>,1:8]
[@4,10:14='endef',<'endef'>,1:10]
这是没有可行替代方案的解析。
这个令牌流看起来确实应该与您的
DEF fun '=' expr ENDEF
规则的 decl
替代方案相匹配,但我收到了相同的错误消息。
为了简化
fun
规则,我添加了 DIGIT: [0-9];
词法分析器规则,并将 fun
规则更改为:
fun: STR DIGIT fun | STR;
(它也适用于定义为
DIGIT
的 DIGIT: ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9');
,因此,将其扩展不是问题。)
通过这一更改(并在输入中的“f() in”后面添加
;
),我获得了成功的解析。
诚然,对于我来说,为什么不能将数字字符用作解析器规则中的内联替代项,这并不是很明显,但无论如何,作为 LExer 规则,它可能更简单。
顺便说一句,您可以将
fun
规则更改为非递归版本,该版本接受相同的输入,并将产生更简单的解析树:
fun: STR (DIGIT STR)*;
(可以对您的
var
规则进行类似操作)