这是我第一次破解解析器生成器,因此也破解了ANTLR。我正在使用ANTLR v4尝试为莫尔斯电码生成一个简单的练习解析器,其中包含以下额外规则:
- 一个字母(例如,
...
[字母的'])如果前面有'^',则可以表示为大写- 例如:
^...
表示大写"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 : [ trn]+ -> 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
之间的歧义似乎有问题?
在其他编程语言中,您的(@)
语法的行为似乎像一个带引号的字符串。我首先将SPECIAL
定义为:
SPECIAL : '(' .*? ')';
为了确保. .
和..
实际上不同,您可以使用以下方法:
SYMBOL : [.-]+;
然后您可以定义您的^
操作员:
CARET : '^';
有了这三个标记(并保持WS
不变),您可以显著简化解析器规则:
file
: entity* EOF
;
entity
: morse_char
| SPECIAL
;
morse_char
: CARET? SYMBOL
;