这可能是一个新问题,因为我没有很多ANTLR经验,但我做了很多研究和故障排除,并没有找到解决方案,所以求助。我正在尝试为一个非常奇怪的格式文件(PCGEN开源角色扮演游戏角色编辑器)编写一个解析器,我计划将其用于多种用途,其中最重要的是学习ANTLR。我知道我有想要在LEX和Parse上工作的所有东西,除了它在空白行时会停止解析。我知道我可以添加一行来丢弃所有空格,但文件格式是这样的,字符串没有真正引用,并且空格通常很重要,所以应该忽略的唯一空格是一个完全空白的行。当我运行Lexer时,它会为整个文件提供令牌,所以我认为Parser会处理令牌而不关心它们来自哪里,所以我错过了一些简单的东西。这是我的意见的开始:
PCGVERSION:2.0
# System Information
CAMPAIGN:Advanced Player's Guide|CAMPAIGN:Ultimate Magic|CAMPAIGN:Ultimate Combat
VERSION:6.07.05
ROLLMETHOD:3|EXPRESSION:2d6+6
PURCHASEPOINTS:N
grammar PCG;
pcgFile : lines=line+;
line : statement (NEWLINE | EOF)
;
statement : KEYWORD ASSIGN
| KEYWORD ASSIGN YES_NO
| KEYWORD ASSIGN TEXT
| KEYWORD ASSIGN VERSIONNUM
| KEYWORD ( ASSIGN INT )+
| KEYWORD ASSIGN INT
| KEYWORD ASSIGN SUB_START statement SUB_END
| statement SEP statement
;
NEWLINE : '\r\n' | 'r' | '\n' ;
YES_NO : ('Y'|'N');
KEYWORD : [A-Z]+;
INT : [0-9]+;
TEXT : ~(':'|'|'|'\r'|'\n'|'['|']')+;
ASSIGN : ':';
SEP : '|';
COMMENT : '#' ~[\r\n]*->skip ;
VERSIONNUM : ([0-9]+ ('.' [0-9]+)?)
| ('.' [0-9]+)
| ([0-9]+ ('.' [0-9]+) ('.' [0-9]+)?)
;
ROLL : INT [dD] INT (('+'|'-') INT)?;
SUB_START : '[';
SUB_END : ']';
任何帮助都将不胜感激。
答案 0 :(得分:0)
您需要在语句之间允许超过1个新行。通过删除rule and rewriting
来执行此操作:
pcgFile : NEWLINE* statement ( NEWLINE+ statement )* NEWLINE* EOF;
主要问题是您的词法分析器将# System Information
与TEXT
令牌匹配。每当2个或更多规则匹配相同数量的字符时,首先定义的规则将" win" * 。这就是TEXT
。当您在COMMENT
之前放置TEXT
时,它会起作用:
grammar PCG;
pcgFile : NEWLINE* statement ( NEWLINE+ statement )* NEWLINE* EOF;
statement : KEYWORD ASSIGN
| KEYWORD ASSIGN YES_NO
| KEYWORD ASSIGN TEXT
| KEYWORD ASSIGN VERSIONNUM
| KEYWORD ( ASSIGN INT )+
| KEYWORD ASSIGN INT
| KEYWORD ASSIGN SUB_START statement SUB_END
| statement SEP statement
;
NEWLINE : '\r\n' | 'r' | '\n' ;
YES_NO : ('Y'|'N');
KEYWORD : [A-Z]+;
INT : [0-9]+;
COMMENT : '#' ~[\r\n]* ->skip ;
TEXT : ~(':'|'|'|'\r'|'\n'|'['|']')+;
ASSIGN : ':';
SEP : '|';
VERSIONNUM : ([0-9]+ ('.' [0-9]+)?)
| ('.' [0-9]+)
| ([0-9]+ ('.' [0-9]+) ('.' [0-9]+)?)
;
ROLL : INT [dD] INT (('+'|'-') INT)?;
SUB_START : '[';
SUB_END : ']';
请注意~(':'|'|'|'\r'|'\n'|'['|']')+
是危险的:它可以轻松匹配很多角色。
* 因为词法分析器的工作原理如此,12
之类的输入将永远不会被标记为VERSIONNUM
标记,因为INT
匹配此标记也会{ {1}}。通过这样做来修复它:
VERSIONNUM