Parsing 操作员问题ANTLR
这似乎是我今天的第1000个问题:)我快完成语法了,如果前缀和中缀运算符共享同一个符号,我就遇到了一个问题。我正在解析一种叫做MathML的标记语言Parsing 操作员问题ANTLR,parsing,operators,expression,antlr,grammar,Parsing,Operators,Expression,Antlr,Grammar,这似乎是我今天的第1000个问题:)我快完成语法了,如果前缀和中缀运算符共享同一个符号,我就遇到了一个问题。我正在解析一种叫做MathML的标记语言 grammar MathMLOperators; options { output = AST; backtrack = true; memoize = true; } tokens { DOCUMENT; // The root of the parsed document. GROUP; OP; // any o
grammar MathMLOperators;
options
{
output = AST;
backtrack = true;
memoize = true;
}
tokens
{
DOCUMENT; // The root of the parsed document.
GROUP;
OP; // any operator
PREFIX_OP; // a prefix operator.
INFIX_OP; // an infix operator.
POSTFIX_OP; // a postfix operator.
NON_INFIX_OP; // a non-infix operator
}
// Start rule.
public document : math+ -> ^(DOCUMENT math+);
inFixTag : TAG_START_OPEN MO TAG_CLOSE ('-' | '+' | '=') TAG_END_OPEN MO TAG_CLOSE -> ^(INFIX_OP);
preFixTag : TAG_START_OPEN MO TAG_CLOSE ('+' | '-') TAG_END_OPEN MO TAG_CLOSE -> ^(PREFIX_OP);
// Use semantic predicate to only allow postfix expressions when at the end of an mrow.
postFixTag : TAG_START_OPEN MO TAG_CLOSE ('!' | '^') TAG_END_OPEN MO {input.LT(1).getType() == TAG_CLOSE && input.LT(2).getType() == TAG_END_OPEN && input.LT(3).getType() == MROW && input.LT(4).getType() == TAG_CLOSE}? TAG_CLOSE -> ^(POSTFIX_OP);
nonInfixTag : TAG_START_OPEN MO TAG_CLOSE ('!' | '^') TAG_END_OPEN MO TAG_CLOSE {$expressionList::count++;} -> ^(OP);
opTag: TAG_START_OPEN MO TAG_CLOSE ('-' | '+' | '^' |'=') TAG_END_OPEN MO TAG_CLOSE -> ^(NON_INFIX_OP);
//Expressions
infixExpression: grouping (inFixTag^ grouping)*;
grouping : nestedExpression+ -> ^(GROUP nestedExpression+);
prefixExpression : /* check that it's the first in the mrow*/ {$expressionList::count == 0}? (preFixTag^ (primaryExpression | nonInfixTag)) {$expressionList::count++;};
postfixExpression : (primaryExpression | prefixExpression| nonInfixTag) (postFixTag^)? ;
expressionList scope {int count} @init{$expressionList::count = 0;} : (infixExpression | opTag)+;
nestedExpression : postfixExpression;
primaryExpression : mrow | mn;
math : TAG_START_OPEN root=MATH TAG_CLOSE expressionList TAG_END_OPEN MATH TAG_CLOSE -> ^($root expressionList);
mrow : TAG_START_OPEN root=MROW TAG_CLOSE expressionList? TAG_END_OPEN MROW TAG_CLOSE -> ^($root expressionList?);
mn: TAG_START_OPEN root=MN TAG_CLOSE INT TAG_END_OPEN MN TAG_CLOSE -> ^($root INT);
MATH : 'math'; // root tag
MROW : 'mrow'; // row
MO : 'mo'; // operator
MN : 'mn'; // number
TAG_START_OPEN : '<';
TAG_END_OPEN : '</' ;
TAG_CLOSE : '>';
TAG_EMPTY_CLOSE : '/>';
INT : '0'..'9'+;
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
语法运算符;
选择权
{
输出=AST;
回溯=真;
memoize=true;
}
代币
{
DOCUMENT;//已解析文档的根。
组;
OP;//任何运算符
PREFIX_OP;//前缀运算符。
中缀_OP;//中缀运算符。
POSTFIX_OP;//后缀运算符。
非中缀运算;//非中缀运算符
}
//开始规则。
公共文档:数学+->^(文档数学+);
inFixTag:TAG_START_OPEN MO TAG_CLOSE(“-”|“+”|“=”)TAG_END_OPEN MO TAG_CLOSE->(中缀操作);
preFixTag:TAG_START_OPEN MO TAG_CLOSE(“+”|“-”)TAG_END_OPEN MO TAG_CLOSE->^(前缀_OP);
//使用语义谓词仅允许在mrow结束时使用后缀表达式。
postFixTag:TAG_START_OPEN MO TAG_CLOSE(“!”|“^”)TAG_END_OPEN MO{input.LT(1)。getType()==TAG_CLOSE&&input.LT(2)。getType()==TAG_END_OPEN&input.LT(3)。getType()==MROW&input.LT(4)。getType()==TAG\u CLOSE}?标记关闭->^(后缀操作);
NonixTag:TAG_START_OPEN MO TAG_CLOSE(“!”|“^”)TAG_END_OPEN MO TAG_CLOSE{$expressionList::count++}->(OP);
opTag:TAG_START_OPEN MO TAG_CLOSE('-'|'+'|'^'|'=')TAG_END_OPEN MO TAG_CLOSE->^(非中缀运算);
//表情
infixExpression:分组(inFixTag^grouping)*;
分组:nestedExpression+->^(组nestedExpression+;
prefixExpression://*检查它是否是mrow*/{$expressionList::count==0}中的第一个?(preFixTag^(primaryExpression | noniFixtag)){$expressionList::count++;};
postfixExpression:(primaryExpression | prefixExpression | nonixTag)(postFixTag^);
expressionList作用域{int count}@init{$expressionList::count=0;}:(infixExpression | opTag)+;
nestedExpression:postfix表达;
主要表达:mrow | mn;
数学:TAG_START_OPEN root=math TAG_CLOSE expressionList TAG_END_OPEN math TAG_CLOSE->^($root expressionList);
mrow:TAG\u START\u OPEN root=mrow TAG\u CLOSE expressionList?TAG\u END\u OPEN MROW TAG\u CLOSE->^($root expressionList?);
mn:TAG_START_OPEN root=mn TAG_CLOSE INT TAG_END_OPEN mn TAG_CLOSE->^($root INT);
数学:“数学”;//根标签
MROW:“MROW”;//一行
MO:‘MO’;//操作人员
MN:'MN';//数
标记\u开始\u打开:“”;
INT:'0'..'9'+;
WS:(“”|’\r’|’\t’|’\u000C’|’\n’{$channel=HIDDEN;};
这很好用
<math>
<mrow>
<mo>-</mo>
<mn>7</mn>
<mo>=</mo>
<mn>8</mn>
</mrow>
</math>
-
7.
=
8.
但这将失败
<math>
<mrow>
<mo>-</mo>
<mn>7</mn>
<mo>-</mo>
<mn>8</mn>
</mrow>
</math>
-
7.
-
8.
第一个“-”应该是“前缀”,第二个应该是“中缀”。从调试器中可以看出,规则分组
正在循环,即使无法匹配,也不会返回父规则infixExpression
我肯定我的EBNF操作符在什么地方出错了,但我不知道是哪一个。我曾尝试遵循C等语言中的标准表达式嵌套模式,但这是一种不常见的解析语言
你介意把语法书寄给我吗
这是我整理过的语法
警告:我无法解释问题中的解析器的行为(因此我清理了它),因此我不知道我无意中打破了/修复了原始解析器的哪些内容——告诉我AST或解析器现在是错误的对我来说没有任何意义,因为对我来说,它一开始看起来是错误的。;)
语法运算符;
选择权
{
输出=AST;
回溯=真;
memoize=true;
}
代币
{
DOCUMENT;//已解析文档的根。
组;
OP;//任何运算符
PREFIX_OP;//前缀运算符。
中缀_OP;//中缀运算符。
POSTFIX_OP;//后缀运算符。
非中缀运算;//非中缀运算符
}
//开始规则。
公共文件:数学+EOF->^(文件数学+);
inFixTag:(op=负| op=加| op=EQ)->中缀运算[$op.text];
preFixTag:(op=减| op=加)->前缀op[$op.text];
//使用语义谓词仅允许在mrow结束时使用后缀表达式。
postfix标签:(op=BANG | op=CARET){input.LA(1)=CMROW}?->后缀_OP[$OP.text];
noniFixTag:(op=BANG | op=CARET){$expressionList::count++}->NON_INFIX_op[$op.text];
opTag:(op=负| op=加| op=插入符号| op=EQ)->op[$op.text];
//表情
infixExpression:分组(inFixTag^grouping)*;
分组:nestedExpression+->^(组nestedExpression+;
prefixExpression:/*检查它是否是mrow中的第一个*/
{$expressionList::count==0}?
(preFixTag^(primaryExpression | nonifixtag))
{$expressionList::count++;}
;
postfixExpression:(primaryExpression | prefixExpression | nonixTag)(postFixTag^);
expressionList作用域{int count}@init{$expressionList::count=0;}:(infixExpression | opTag)+;
nestedExpression:postfix表达;
主要表达式:mrow | NUM;
数学:数学表达式列表CMATH->^(数学表达式列表);
mrow:mrow表达式列表?CMROW->^(MROW表达列表?);
///////雷克瑟///////
数学:标记\u开始\u打开WS*“数学”WS*标记\u关闭;//根标签
CMATH:TAG_END_OPEN WS*‘math’WS*TAG_CLOSE;
MROW:TAG_START_OPEN WS*'MROW'WS*TAG_CLOSE;//一行
CMROW:TAG_END_OPEN WS*“mrow”WS*TAG_CLOSE;
片段OMO:TAG_START_OPEN WS*'mo'WS*TAG_CLOSE;//操作人员
片段CMO:TAG_END_OPEN WS*‘mo’WS*TAG_CLOSE;
减:OMO'-'CMO{setText(“-”);};
加:OMO'+'CMO{setText(“+”);};
等式:OMO'='CMO{setText(“=”);};
砰:哦CMO{setText(!”;};
插入符号:OMO'^'CMO{setText(“^”);};
NUM:TAG\u START\u OPEN WS*'mn'WS*TAG\u CLOSE
国际的
标记\结束\打开WS*'mn'WS*标记\关闭
{setText($INT.text);}
;
片段标记\u开始\u打开:“”;
INT:'0'..'9'+;
WS:(“”|’\r’|’\t’|’\u000C’|’\n’{$channel=HIDDEN;};
测试C
grammar MathMLOperators;
options
{
output = AST;
backtrack = true;
memoize = true;
}
tokens
{
DOCUMENT; // The root of the parsed document.
GROUP;
OP; // any operator
PREFIX_OP; // a prefix operator.
INFIX_OP; // an infix operator.
POSTFIX_OP; // a postfix operator.
NON_INFIX_OP; // a non-infix operator
}
// Start rule.
public document : math+ EOF -> ^(DOCUMENT math+);
inFixTag : (op=MINUS | op=PLUS | op=EQ) -> INFIX_OP[$op.text];
preFixTag : (op=MINUS | op=PLUS) -> PREFIX_OP[$op.text];
// Use semantic predicate to only allow postfix expressions when at the end of an mrow.
postFixTag : (op=BANG | op=CARET) {input.LA(1) == CMROW}? -> POSTFIX_OP[$op.text];
nonInfixTag : (op=BANG | op=CARET) {$expressionList::count++;} -> NON_INFIX_OP[$op.text];
opTag : (op=MINUS | op=PLUS | op=CARET | op=EQ) -> OP[$op.text];
//Expressions
infixExpression : grouping (inFixTag^ grouping)*;
grouping : nestedExpression+ -> ^(GROUP nestedExpression+);
prefixExpression : /* check that it's the first in the mrow*/
{$expressionList::count == 0}?
(preFixTag^ (primaryExpression | nonInfixTag))
{$expressionList::count++;}
;
postfixExpression : (primaryExpression | prefixExpression| nonInfixTag) (postFixTag^)? ;
expressionList scope {int count} @init{$expressionList::count = 0;} : (infixExpression | opTag)+;
nestedExpression : postfixExpression;
primaryExpression : mrow | NUM;
math : MATH expressionList CMATH -> ^(MATH expressionList);
mrow : MROW expressionList? CMROW -> ^(MROW expressionList?);
/////// LEXER ///////
MATH : TAG_START_OPEN WS* 'math' WS* TAG_CLOSE; // root tag
CMATH : TAG_END_OPEN WS* 'math' WS* TAG_CLOSE;
MROW : TAG_START_OPEN WS* 'mrow' WS* TAG_CLOSE; // row
CMROW : TAG_END_OPEN WS* 'mrow' WS* TAG_CLOSE;
fragment OMO : TAG_START_OPEN WS* 'mo' WS* TAG_CLOSE; // operator
fragment CMO : TAG_END_OPEN WS* 'mo' WS* TAG_CLOSE;
MINUS : OMO '-' CMO {setText("-");};
PLUS : OMO '+' CMO {setText("+");};
EQ : OMO '=' CMO {setText("=");};
BANG : OMO '!' CMO {setText("!");};
CARET : OMO '^' CMO {setText("^");};
NUM : TAG_START_OPEN WS* 'mn' WS* TAG_CLOSE
INT
TAG_END_OPEN WS* 'mn' WS* TAG_CLOSE
{setText($INT.text);}
;
fragment TAG_START_OPEN : '<';
fragment TAG_END_OPEN : '</' ;
fragment TAG_CLOSE : '>';
fragment TAG_EMPTY_CLOSE: '/>';
INT : '0'..'9'+;
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
<math>
<mrow>
<mo>-</mo>
<mn>7</mn>
<mo>=</mo>
<mn>8</mn>
</mrow>
</math>
<math>
<mrow>
<mo>-</mo>
<mn>7</mn>
<mo>-</mo>
<mn>8</mn>
</mrow>
</math>
<math>
<mo>-</mo>
<mn>7</mn>
<mo>-</mo>
<mn>8</mn>
</math>