我在 ANTLR 中使用词法分析器规则手动发出 token 时遇到了一些麻烦。我知道需要使用 emit() 函数,但似乎明显缺乏关于此的文档。有没有人有一个很好的例子来说明如何做到这一点?
ANTLR 一书提供了一个很好的示例,说明您需要如何执行此操作来解析 Python 的嵌套。例如,如果您看到一定数量的空格大于前一行的空格,则发出 INDENT 标记,但如果较少,则发出 DEDENT 标记。不幸的是,这本书掩盖了所需的实际语法。
编辑:这是我试图解析的一个例子。这是 Markdown 的嵌套块引用:
before blockquote
> text1
>
> > text2
>
> text3
outside blockquote
现在,到目前为止,我的方法基本上是计算每行的 > 符号。例如,上面似乎应该发出(大致......)PARAGRAPH_START、CDATA、PARAGRAPH_END、BQUOTE_START、CDATA、BQUOTE_START、CDATA、BQUOTE_END、CDATA、BQUOTE_END、PARAGRAPH_START、CDATA、PARAGRAPH_END。这里的困难是最后的 BQUOTE_END ,我认为它应该是一个虚构的标记,一旦找到非块引用元素(并且嵌套级别 >= 1)
最佳答案
好吧,如果您要发出的 token 不是由词法分析器规则定义的,那么您需要添加一个 token 部分,如下所示:
tokens
{
MYFAKETOKEN
}
在您的词法分析器中,您仍然需要一个规则来告诉词法分析器何时生成此标记。一个常见的例子是确定某物是整数、范围还是实数值。
NUMBERS_OR_RANGE
: INT
( { LA(1) == '.' && LA(2) == '.' }? { _ttype = INT; }
| { LA(1) == '.' || LA(1) == 'e' || LA(1) == 'E' }? { _ttype = REAL; }
)
| PERIOD
( PERIOD { _ttype = RANGE; }
INT (( 'e' | 'E' ) ( '-' | '+' )? INT )? { _ttype = REAL; }
)
;
在这里你可以看到我们匹配一个 INT 然后向前看,如果我们找到一个双周期,那么我们知道 INT 实际上是一个整数而不是一个真实的。在这种情况下,我们将变量 _ttype 设置为 INT。如果我们找到一个 PERIOD,然后找到一个 'e',我们就知道它是真实的。
第二种情况,我们匹配一个句点,我们知道如果下一个字符是一个句点,那么我们就有了一个范围,否则我们就有了一个实数。
我们可以使用
MYFAKETOKEN
如果合适,我们上面定义的类型分配给 _ttype。
关于parsing - 使用 ANTLR 手动发出 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2049569/