antlr4 - 解析 f1vae

问题描述 投票:0回答:1
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' 。 问题是什么?似乎没有重叠的词法分析器规则。

antlr antlr4
1个回答
0
投票

您看到“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
规则进行类似操作)

© www.soinside.com 2019 - 2024. All rights reserved.