这是我在解析器生成器上的第一次破解,因此是ANTLR。我正在使用ANTLR v4尝试使用以下额外规则为摩尔斯电码生成一个简单的练习解析器:
...
[字母's'])表示为大写
^...
表示首都'S'(@)
所以我可以编码以下句子:
ABC a@b.com
as(下面显示相应的字母):
^.- ^-... ^-.-. ( ) ._ (@) -... (.) -.-. --- --
A B C ' ' a '@' b '.' c o m
特别注意以下两个实体:( )
(表示空格)和(.)
(表示句点。
我发现主要有一件事我很难理解:同样的标记可以采用不同的含义,取决于它是否在括号中。也就是说,我想告诉ANTLR我想丢弃空格,但不是( )
的情况。此外,摩尔斯电码字符可以由点划线(句点和短划线)组成,但是,我不想将(.)
中的句号视为“任何字符”。
这是我到目前为止的语法:
grammar MorseCode;
file: entity*;
entity:
special
| morse_char;
special: '(' SPECIAL ')';
morse_char: '^'? (DOT_OR_DASH)+;
SPECIAL : .; // match any character
DOT_OR_DASH : ('.' | '-');
WS : [ \t\r\n]+ -> skip; // we don't care about whitespace (or do we?)
当我针对以下输入进行尝试时:
^... --- ...(@)
我得到以下输出(来自grun ... -tokens
):
[@0,0:0='^',<1>,1:0]
[@1,1:1='.',<4>,1:1]
...
[@15,15:14='<EOF>',<-1>,1:15]
line 1:1 mismatched input '.' expecting DOT_OR_DASH
似乎SPECIAL
和DOT_OR_DASH
之间存在歧义问题?
答案 0 :(得分:1)
似乎您的(@)
语法在其他编程语言中的行为类似于带引号的字符串。我首先将SPECIAL
定义为:
SPECIAL : '(' .*? ')';
为确保. .
和..
实际上不同,您可以使用此功能:
SYMBOL : [.-]+;
然后您可以定义^
运算符:
CARET : '^';
使用这三个令牌(并保持WS
原样),您可以显着简化解析器规则:
file
: entity* EOF
;
entity
: morse_char
| SPECIAL
;
morse_char
: CARET? SYMBOL
;