Parsing 操作员问题ANTLR

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

这似乎是我今天的第1000个问题:)我快完成语法了,如果前缀和中缀运算符共享同一个符号,我就遇到了一个问题。我正在解析一种叫做MathML的标记语言

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>