ANTLR:如何用lexer解析匹配括号内的区域
我想在我的lexer中解析如下内容:ANTLR:如何用lexer解析匹配括号内的区域,antlr,matching,lexer,brackets,Antlr,Matching,Lexer,Brackets,我想在我的lexer中解析如下内容: ( begin expression ) 其中表达式也用括号括起来。表达式中的内容并不重要,我只想将(begin和匹配的)之间的所有内容作为标记。例如: (begin (define x (+ 1 2))) 因此,令牌的文本应该是 (define x (+ 1 2))) 差不多 PROGRAM : LPAREN BEGIN .* RPAREN; (显然)不起作用,因为他一看到“)”,就认为规则结束了,但我需要匹配的括号 我该怎么做呢?在lexe
( begin expression )
其中表达式也用括号括起来。表达式中的内容并不重要,我只想将(begin
和匹配的)
之间的所有内容作为标记。例如:
(begin
(define x (+ 1 2)))
因此,令牌的文本应该是
(define x (+ 1 2)))
差不多
PROGRAM : LPAREN BEGIN .* RPAREN;
(显然)不起作用,因为他一看到“)”,就认为规则结束了,但我需要匹配的括号
我该怎么做呢?在lexer规则中,您可以递归调用规则。所以,这是解决这个问题的一种方法。另一种方法是跟踪开括号和闭括号的数量,只要计数器大于零,就允许循环 演示: T.g
语法T;
作语法分析
:BeginToken{System.out.println(“已解析::”+$BeginToken.text);}EOF
;
贝金托肯
@init{int open=1;}
:“(”开始“({open>0}?=>//只要open>0,就继续重复“(…)*”
(~('('|')//匹配除括号外的任何内容
|“({open++;}//在变量`open'中匹配一个“(”`
|“)”{open--;}//在变量“open”中匹配a')”`
)
)*
;
主类
import org.antlr.runtime.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
字符串输入=“(开始(定义x(+-13)2))”;
TLexer lexer=新的TLexer(新的AntlStringStream(输入));
TParser parser=newtparser(newcommontokenstream(lexer));
parser.parse();
}
}
java-cp antlr-3.3-complete.jar org.antlr.Tool T.g
javac-cp antlr-3.3-complete.jar*.java
java-cp.:antlr-3.3-complete.jar Main
已解析::(开始(定义x(+-13)2)))
请注意,您需要注意源代码中可能包含括号的字符串文字:
BeginToken
@init{int open=1;}
:“(”开始“({open>0}?=>/。。。
( ~('(' | ')' | '"') // ...
|“({open++;}//。。。
|“)”{open--;}/。。。
|“'”…//TODO:在此处定义字符串文字
)
)*
;
或可能包含括号的注释
谓词的建议使用一些特定于语言的代码(本例中为Java)。递归调用lexer规则的一个优点是,您的lexer中没有自定义代码:
BeginToken
:“(“空格?”开始“空格?嵌套的Parens空格”)”
;
片段嵌套排列
:“(-(“(”(“|”))|嵌套父母)*.”
;
片段空间
:(“|”\t”)+
;
如果您想识别(…)之间的所有内容,包括其他嵌套(…),那么您不能使用纯的、基于regexp的标准lexer(例如,我认为ANTLR),因为正则表达式不能计数-->无法确定括号何时平衡。您需要实现一个可以计数括号的词素识别器。@Ira,它是一个单词素。以大写字母开头的规则是ANTLR中的标记。我命名规则Root
可能是一个错误的选择,这让您相信我推了这个问题我是语法分析器…啊哈。是的,正如你可能猜到的,我不是一个真正的ANTLR专家。所以…这就是我希望你能提供的答案。我再也不会怀疑你了!@Bart:我刚刚注意到我在这方面的另一个问题:lexer不再正确识别像(bar…
)这样的语句,相反,他扔掉了(ba'并将r
作为标识符返回,尽管我想使用LPAREN标识符。我如何解决这个问题?我是否应该就此提出另一个问题并再次发布语法?是的,这是lexer不喜欢的。如果输入“看起来”像(b.
,lexer在备份到LPAREN标识符
而不是BeginToken
时遇到问题。这真的是您想要在lexer中处理的事情吗?在解析器中匹配BeginToken
比在lexer中匹配BeginToken
更容易。是的,创建新问题可能更容易(以防您真的想在lexer中执行此操作)。