基本上,我需要预见知道某个令牌是否存在,但是没有匹配它(即,这样另一个解析器规则仍然可以匹配它).
问题的确切细节是"END-ALL"条款.该语言具有类似"IF"(由"END-IF"关闭),"FOR"(由"END-FOR"关闭)等结构.
但是可以选择使用"END-ALL"全局关闭所有这样的开环(因此不需要实际的"END-IF"或"END-FOR"子句).
无论如何我能正确实现吗?
你如何将ANTLR 3中编写的这部分代码翻译成ANTLR 4?
expr: (Identifier '.')=> (refIdentifier)
| (Identifier '!')=> (refIdentifier)
| (Identifier '=>')=> (lambdaExpression);
Run Code Online (Sandbox Code Playgroud)
我的意思是这种语义谓词现在似乎不存在.我可以用什么呢?
在什么是ANTLR3中的"语义谓词"?Bart Kiers非常清楚地概述了Antlr3中的不同语义谓词.
太糟糕了,Antlr4中的语法/语义似乎有所改变,所以这不会编译:
end_of_statement
: ';'
| EOF
| {input.LT(1).getType() == RBRACE}? =>
;
RBRACE
: '}'
;
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我如何处理end_of_statement的第三种情况:如果下一个标记是'}'但不消耗它,则接受.
我试图让我的头围绕ANTLR中的树构造运算符(^和!).
我有一个flex字节数组的语法(一个UINT16,用于描述数组中的字节数,后跟那么多字节).我已经注释掉所有语义谓词及其相关代码,这些代码确实证明了数组中的字节数与前两个字节所指示的一样多......那部分不是我遇到的问题.
我的问题是解析一些输入后生成的树.所有发生的事情是每个角色都是兄弟节点.我期望生成的AST与您在ANTLRWorks 1.4的Interpreter窗口中可以看到的树类似.一旦我尝试使用^字符更改树的制作方式,我就会得到一个例外:
Unhandled Exception: System.SystemException: more than one node as root (TODO: make exception hierarchy)
Run Code Online (Sandbox Code Playgroud)
这是语法(目前针对C#):
grammar FlexByteArray_HexGrammar;
options
{
//language = 'Java';
language = 'CSharp2';
output=AST;
}
expr
: array_length remaining_data
//the amount of remaining data must be equal to the array_length (times 2 since 2 hex characters per byte)
// need to check if the array length is zero first to avoid checking $remaining_data.text (null reference) in that situation.
//{ ($array_length.value == 0 && $remaining_data.text == …Run Code Online (Sandbox Code Playgroud) 我知道'+','?' 和'*'.但是,如果我想要一些东西重复,比如5次呢?例如,如果标识符必须是长度为5的十六进制数字的字符串?
更具体地说,我正在考虑定义一个无限长度的一般词法分析器规则,然后,在解析时计算它重复的时间,如果等于5,则将其重命名为另一种类型的令牌,但怎么能我这样做?还是有一些简单的方法?
当antlr v3.1编译此规则时,我收到警告
sentence
:
(CAPITAL_LETTERS_AND_NUMBERS | INT | ANY_WORD )
(
INT
| CAPITAL_LETTERS_AND_NUMBERS
| ANY_WORD
)*;
Run Code Online (Sandbox Code Playgroud)
警告是:
5:2: Decision can match input such as "CAPITAL_LETTERS_AND_NUMBERS" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
Semantic predicates were present but were hidden by actions.
Decision can match input such as "INT" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
Semantic predicates were present but were hidden by …Run Code Online (Sandbox Code Playgroud) 我想在我的词法分析器中解析这样的东西:
( begin expression )
Run Code Online (Sandbox Code Playgroud)
其中表达式也用括号括起来。表达式中的内容并不重要,我只想将(begin和 匹配之间的所有内容)作为标记。一个例子是:
(begin
(define x (+ 1 2)))Run Code Online (Sandbox Code Playgroud)
所以令牌的文本应该是
(define x (+ 1 2)))Run Code Online (Sandbox Code Playgroud)
就像是
PROGRAM : LPAREN BEGIN .* RPAREN;
Run Code Online (Sandbox Code Playgroud)
确实(显然)不起作用,因为一旦他看到“)”,他就认为规则已经结束,但我需要匹配的括号。
我怎样才能做到这一点?
我一直在研究HTML(FreeMarker)中嵌入的一些模板语言的解析器,这里有一个例子:
${abc}
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>
Welcome ${user}<#if user == "Big Joe">, our beloved
leader</#if>!
</h1>
<p>Our latest product:
<a href="${latestProduct}">${latestProduct}</a>!
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
模板语言介于某些特定标签之间,例如'$ {''}','<#''>'.中间的其他原始文本可以被视为相同的令牌(RAW).
这里的关键点是相同的文本,例如整数,对于解析器来说意味着不同的东西取决于它是否在这些标记之间,因此需要被视为不同的标记.
我尝试过以下丑陋的实现,并使用自定义状态来指示它是否在这些标记中.如你所见,我必须在每条规则中检查状态,这让我发疯...
我还想到了以下两种解决方案:
使用多个词法分析器.我可以在这些标签的内部/外部切换两个词法分析器.但是,ANTLR3的文档很差.我不知道如何让一个解析器共享两个不同的词法分析器并在它们之间切换.
在NUMERICAL_ESCAPE规则之后向上移动RAW规则.检查那里的状态,如果它在标签中,则放回令牌并继续尝试左边的规则.这将节省大量的状态检查.但是,我没有找到任何"回放"功能,而ANTLR抱怨一些规则永远无法匹配......
有一个优雅的解决方案吗?
grammar freemarker_simple;
@lexer::members {
int freemarker_type = 0;
}
expression
: primary_expression ;
primary_expression
: number_literal | identifier | parenthesis | builtin_variable
;
parenthesis
: OPEN_PAREN expression CLOSE_PAREN ;
number_literal
: INTEGER | DECIMAL
;
identifier
: ID
;
builtin_variable
: DOT ID
;
string_output
: OUTPUT_ESCAPE …Run Code Online (Sandbox Code Playgroud) 似乎有时Antlr词法分析器在对字符流进行标记时使用哪个规则做出了错误的选择......我正在试图弄清楚如何帮助Antlr做出明显的人性化选择.我想解析这样的文字:
d/dt(x)=a
a=d/dt
d=3
dt=4
Run Code Online (Sandbox Code Playgroud)
这是一种现有语言使用的不幸语法,我正在尝试编写解析器."d/dt(x)"表示微分方程的左侧.如果必须,请忽略行话,只要知道它不是"d"除以"dt".然而,第二次出现的"d/dt"确实是"d"除以"dt".
这是我的语法:
grammar diffeq_grammar;
program : (statement? NEWLINE)*;
statement
: diffeq
| assignment;
diffeq : DDT ID ')' '=' ID;
assignment
: ID '=' NUMBER
| ID '=' ID '/' ID
;
DDT : 'd/dt(';
ID : 'a'..'z'+;
NUMBER : '0'..'9'+;
NEWLINE : '\r\n'|'\r'|'\n';
Run Code Online (Sandbox Code Playgroud)
当使用这个语法时,词法分析器抓住第一个"d/dt("并将其转换为令牌DDT.完美!现在,词法分析器看到第二个"d"后跟一个"/"并说"嗯,我可以匹配这个作为一个ID和一个'/',或者我可以贪婪并匹配DDT".词法分析器选择贪婪...但它知之甚少,没有"("输入流后面的几个字符.当lexer查找缺少的"("它会抛出MismatchedTokenException!
到目前为止我找到的唯一解决方案是将所有规则移到解析器中,语法如下:
grammar diffeq_grammar;
program : (statement? NEWLINE)*;
statement
: diffeq
| assignment;
diffeq : ddt id ')' '=' id;
assignment
: id '=' number
| id '=' id '/' id …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用antlr编写一种简单的交互式(使用System.in作为源代码)语言,但我遇到了一些问题。我在网上找到的示例都是按行周期使用的,例如:
while(readline)
result = parse(line)
doStuff(result)
Run Code Online (Sandbox Code Playgroud)
但是,如果我写的是pascal / smtp / etc之类的东西,并且带有“第一行”,看起来像X需求,该怎么办?我知道可以在doStuff中检查它,但是从逻辑上讲,它是语法的一部分。
还是将命令分成多行怎么办?我可以试试
while(readline)
lines.add(line)
try
result = parse(lines)
lines = []
doStuff(result)
catch
nop
Run Code Online (Sandbox Code Playgroud)
但是与此同时,我也隐藏了真正的错误。
或者我可以每次重新分析所有行,但是:
可以使用ANTLR完成此操作吗?
在ANTLR中,我想定义一个这样的规则:
规则:(abc | acb | bac | bca | cab | cba);
但在我的情况下,我有10个规则而不是3个,我想要置换,因此它变得非常不切实际.有没有办法在ANTLR中表达这一点而不必写出所有的排列?
鉴于语法
test : 'test' ID '\n' 'begin' '\n' 'end' '\n' -> ^(TEST ID);
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
Run Code Online (Sandbox Code Playgroud)
和测试字符串
"test blah\n begin\n end\n"
Run Code Online (Sandbox Code Playgroud)
导致
line 1:0 mismatched input 'test blah\\n begin\\n end\\n' expecting 'test'
<mismatched token: [@0,0:21='test blah\\n begin\\n end\\n',<12>,1:0], resync=test blah
begin
end
>
Run Code Online (Sandbox Code Playgroud)
这里出了什么问题?
在Antlr中,如果我有一个例子:
someRule : TOKENA TOKENB;
Run Code Online (Sandbox Code Playgroud)
它会接受:"tokena tokenb"
如果我希望TOKENA是可选的,我可以说,
someRule : TOKENA* TOKENB;
Run Code Online (Sandbox Code Playgroud)
那么我可以:"tokena tokenb"或"tokenb"或"tokena tokena tokenb"
但这也意味着它可以重复一次.无论如何我可以说这个令牌可以有1次或更少但不超过1次吗?所以它会接受:
"tokena tokenb"或"tokenb"但不是"tokena tokena tokenb"?
非常感谢