我有非常简单的XML(HTML)解析ANTLR语法:
wiki: ggg+;
ggg: tag | text;
tag: '<' tx=TEXT { System.out.println($tx.getText()); } '>';
text: tx=TEXT { System.out.println($tx.getText()); };
CHAR: ~('<'|'>');
TEXT: CHAR+;
使用这样的输入:"<ggg> fff"
它可以正常工作。
但是当我开始处理空白时,它失败了。例如:
" <ggg> fff "
- 在beggining失败"<ggg> <hhh> "
- 在<ggg>
"<ggg> fff "
- 工作正常"<ggg> "
- 最后失败我不知道出了什么问题。也许有一些特殊的语法选项来处理这个问题。 ANTLRWorks给了我NoViableAltException
。
答案 0 :(得分:3)
ANTLR的词法分析规则尽可能匹配。仅当2(或更多)规则匹配相同数量的字符时,首先定义的规则将“赢”。因此,'<'
和'>'
以外的单个字符被标记为CHAR
标记,而不是TEXT
标记,无论解析器“需要”什么(词法分析器独立于解析器运行,请记住!)。只有'<'
和'>'
以外的两个或多个字符被标记为(单个)TEXT
令牌。
因此,输入" <ggg> fff "
会创建以下5个标记:
type | text
--------+-----------
CHAR | ' '
'<' | '<'
TEXT | 'ggg'
'>' | '>'
TEXT | ' fff '
由于解析器规则中未考虑令牌CHAR
,因此解析失败。
只需删除CHAR
并执行:
TEXT : ~('<'|'>')+;
答案 1 :(得分:1)
你没有处理空间的令牌。词法分析器的空间与它可能遇到的任何其他角色没有区别。
如果空格不重要,您只需使用:
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
如果空白对您很重要:
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+
CHAR: ~('<'|'>');
TEXT: (CHAR|WHITESPACE)+;