我正在尝试为旧的ELIZA聊天机器人程序的DOCTOR脚本创建一个解析器。
DOCTOR脚本,这里简化为一个简单的欢迎行,后面是一行定义如何"医生"响应用户输入的"如果我瘦一点就好了";:
(I AM THE DOCTOR.)
(IF 3 ((0 IF 0)(DO YOU 3)(YOU WISH THAT 3)))
Lexer:
ALL_CHARS: [0-9A-Z, .];
KEY_CHARS: [A-Z];
LPAREN: '(';
RPAREN: ')';
NUM: [0-9];
SPACE: ' ';
WS: ('n')+ -> skip;
和解析器:
main: item* EOF;
item: (rWelcome | rKeyDecompReAssy );
rKeyDecompReAssy: LPAREN rKeyPri rDecompReAssy RPAREN;
rKeyPri: rKey SPACE rPri;
rKey: KEY_CHARS+;
rPri: NUM+;
rDecompReAssy: LPAREN rDecomp rReAssyList RPAREN;
rDecomp: LPAREN ALL_CHARS+ RPAREN;
rReAssyList: (rReAssy)+;
rReAssy: LPAREN reAssy RPAREN;
reAssy: ALL_CHARS+;
rWelcome: LPAREN reAssy RPAREN;
定义了Welcome的规则。线(rWelcome)和一个用于IF线(rDecompReAssy),它尝试匹配4个组件:Key, Pri, Decomp和ReAssyList。
我使用Android Studio的ANTLR预览。
问题是这两行都匹配到rWelcome
欢迎行当然没问题,但是第二行的错误消息是:
line 2:6 missing ')' at '('
line 2:45 mismatched input ')' expecting {<EOF>, '('}
我如何使这两个规则明确?
正如评论中提到的,您的词法分析器从未创建KEY_CHARS
-,SPACE
-和NUM
-令牌。这是因为ALL_CHARS
令牌也匹配那些令牌中定义的字符。当两个或多个词法分析器规则匹配相同字符时,首先定义的规则"获胜"。无论解析器规则是否尝试匹配KEY_CHARS
令牌,词法分析器都会简单地创建一个ALL_CHARS
令牌:词法分析器独立于解析器工作。
你可以这样做:
main : item* EOF;
item : (rWelcome | rKeyDecompReAssy );
rKeyDecompReAssy : LPAREN rKeyPri rDecompReAssy RPAREN;
rKeyPri : rKey SPACE rPri SPACE; // Note: I added the last `SPACE`
rKey : KEY_CHARS+;
rPri : NUM+;
rDecompReAssy : LPAREN rDecomp rReAssyList RPAREN;
rDecomp : LPAREN all_chars+ RPAREN;
rReAssyList : (rReAssy)+;
rReAssy : LPAREN reAssy RPAREN;
reAssy : all_chars+;
rWelcome : LPAREN reAssy RPAREN;
all_chars : NUM | KEY_CHARS | SPACE | OTHER_CHAR;
KEY_CHARS : [A-Z];
LPAREN : '(';
RPAREN : ')';
NUM : [0-9];
SPACE : ' ';
WS : ('n')+ -> skip;
OTHER_CHAR : [.,];