Antlr Xtext为表达式创建详细错误消息:如何获取语法错误的规则跟踪?

Antlr Xtext为表达式创建详细错误消息:如何获取语法错误的规则跟踪?,antlr,xtext,Antlr,Xtext,我试图扩展SyntaxErrorMessageProvider以覆盖语法错误消息,但是我不知道如何获取调用此语法错误的规则的堆栈跟踪: class MySyntaxErrorMessageProvider extends SyntaxErrorMessageProvider { def override SyntaxErrorMessage getSyntaxErrorMessage(ISyntaxErrorMessageProvider.IParserErrorContext cont

我试图扩展SyntaxErrorMessageProvider以覆盖语法错误消息,但是我不知道如何获取调用此语法错误的规则的堆栈跟踪:

class MySyntaxErrorMessageProvider extends SyntaxErrorMessageProvider {
    def override SyntaxErrorMessage getSyntaxErrorMessage(ISyntaxErrorMessageProvider.IParserErrorContext context) {
        if(context.recognitionException != null) {
            handle(context.recognitionException)
        } else {
            handleException(context)
        }
例如,当给出以下文本时,我希望实现以下目标:

1. 1 +

2. 1 + +

3. 1 1

4. 1 1 +
错误消息应为,并提供以下快速修复选项:

1. 1 + is an incomplete expression, mainly + has no right hand operand

2. 1 + + is an incomplete expression, mainly 1 + in (1 +) + has no right operand or expression and + in 1 + (+) has no left or right operands or expressions
这些选项的快速修复方法可以是(添加或删除):

我正在努力找到一种使用XTEXTAPI实现这一点的方法。我得到了不正确解析的INode,但当我使用.getAstreeTerable()遍历树时,从这些节点得到的不是完整的输入。它只显示在模型中有效的文本

  • 我是否需要在语法中添加一些错误规则来捕获这些不正确的情况,以便使用INode接口识别它们

  • 输入:

    badinput=1+2++

  • 我得到以下节点:

    Start....
    
    Defsym_exprImpl@153802c5 (defSymbolName: badinput)
    
    AdditionImpl@1dc74ee0
    
    AdditionImpl@2335d787
    
    INTEGER_CONSTANTImpl@19816081 (value: 1)
    
    INTEGER_CONSTANTImpl@4cfa675e (value: 2)
    
    UNARY_PLUSImpl@6bed906f
    
    End....
    
    其中我可以遍历它们并检查它们的一些对应值是否为Null,这是正确的方法吗

    有人还有什么建议吗

    我的实现语法如下:

        Expression returns Expression:
        Assignment
    ;
    
    Assignment returns Expression:
        Ternary (
                ( ({AndEquals.left=current} AND EQUALS)
                | ({OrEquals.left=current} OR EQUALS)
                | ({PlusEquals.left=current} PLUS EQUALS)
                | ({MinusEquals.left=current} MINUS EQUALS)
                | ({MultiplyEquals.left=current} MULTIPLY EQUALS)
                | ({DivideEquals.left=current} DIVIDE EQUALS)
                | ({Equals.left=current} EQUALS)
                | ({LeftShiftEquals.left=current} LEFT_SHIFT EQUALS)
                | ({RightShiftEquals.left=current} RIGHT_SHIFT EQUALS)
                )
            right=Ternary
        )*
    ;
    
    Ternary returns Expression:
         OrOr ({Ternar.left=current} SEMICOLON rightTrue=OrOr QUESTION rightFalse=OrOr)*
    ;
    
    OrOr returns Expression:
        AndAnd ({OrOr.left=current} OR_OR right=AndAnd)*
    ;
    
    AndAnd returns Expression:
        BitwiseOr ({AndAnd.left=current} AND_AND right=BitwiseOr)*
    ;
    
    BitwiseOr returns Expression:
        BitwiseXOR ({Or.left=current} OR right=BitwiseXOR)*
    ;
    
    BitwiseXOR returns Expression:
        BitwiseAnd ({XOr.left=current} XOR right=BitwiseAnd)*
    ;
    
    BitwiseAnd returns Expression:
        Comparisons ({And.left=current} AND right=Comparisons)*
    ;
    
    Comparisons returns Expression:
        Shifting (( ( {EqualsEquals.left=current} EQUALS_EQUALS) 
                 | ( {NotEquals.left=current} NOT_EQUALS)
                 | ( {GreaterThan.left=current} GREATER_THAN)
                 | ( {LessThan.left=current} LESS_THAN)
                 | ( {LessThanEquals.left=current} LESS_THAN_EQUALS)
                 | ( {GreaterEquals.left=current} GREATER_EQUALS)
                 )
                 right=Shifting
        )*
    ;
    
    Shifting returns Expression:
        AdditionOrSubtraction (  ( {LeftShift.left=current} LEFT_SHIFT 
                                 | {RightShift.left=current} RIGHT_SHIFT
                                 ) right=AdditionOrSubtraction)*
    ;
    
    AdditionOrSubtraction returns Expression:
        MultiplicationOrDivision (   ( {Addition.left=current} PLUS 
                                     | {Subtraction.left=current} MINUS
                                   ) (right=MultiplicationOrDivision))*
    ;
    
    MultiplicationOrDivision returns Expression: 
        UnaryOperations ( ( {Multiplication.left=current} MULTIPLY 
                          | {Division.left=current} DIVIDE 
                          | {Modulus.left=current} MOD
                          ) right=UnaryOperations)*
    ;
    
    UnaryOperations returns Expression:
        ({UNARY_MINUS} MINUS value=UnaryOperations)
        /* +(1 + 2) is not supported in the original LD*/
        | ({UNARY_PLUS} PLUS value=UnaryOperations)
        | ({UNARY_BITWISE_NOT} BITWISE_NOT value=UnaryOperations)
        | ({UNARY_LOGICAL_NOT} LOGICAL_NOT value=UnaryOperations)
        | Primary
    ;
    
    Primary returns Expression:
        RecursiveExpressions
        | AtomicExpressions
        | Constants
        | Atom
    ;
    
    RecursiveExpressions returns Expression:
        OPEN_BRACKET Expression CLOSE_BRACKET
        | {NEXT_BUILT_IN} NEXT OPEN_BRACKET value=Expression CLOSE_BRACKET
        | {LOG2CEIL_BUILT_IN} LOG2CEIL OPEN_BRACKET value=Expression CLOSE_BRACKET
        | {ABSOLUTE_BUILT_IN} ABSOLUTE OPEN_BRACKET value=Expression CLOSE_BRACKET
        | {ALIGN_BUILT_IN} ALIGN OPEN_BRACKET left=Expression (COMMA right=Expression)? CLOSE_BRACKET
        | {SEGMENT_ALIGN_BUILT_IN} DATA_SEGMENT_ALIGN OPEN_BRACKET left=Expression COMMA right=Expression CLOSE_BRACKET
        | {SEGMENT_RELRO_END_BUILT_IN} DATA_SEGMENT_RELRO_END OPEN_BRACKET left=Expression COMMA right=Expression CLOSE_BRACKET
        | {SEGMENT_BUILT_IN} DATA_SEGMENT_END OPEN_BRACKET value=Expression CLOSE_BRACKET
        | {START_BUILT_IN} SEGMENT_START OPEN_BRACKET name=ID COMMA value=Expression CLOSE_BRACKET
        | {BLOCK_BUILT_IN} BLOCK OPEN_BRACKET value=Expression CLOSE_BRACKET
        | {MAX_DOUBLE_BUILT_IN} MAX OPEN_BRACKET left=Expression COMMA right=Expression CLOSE_BRACKET
        | {MIN_DOUBLE_BUILT_IN} MIN OPEN_BRACKET left=Expression COMMA right=Expression CLOSE_BRACKET
        | {ASSERT_E_BUILT_IN} ASSERT OPEN_BRACKET value=Expression COMMA name=ID CLOSE_BRACKET
    ;
    
    Constants returns Expression:
        /* Constants */
        {COUNTER} LOCATION_COUNTER
        | {SIZE_OF_HEADER} SIZEOF_HEADERS   
    ;
    
    AtomicExpressions returns Expression:
        {ATOMIC_DEFINED} DEFINED OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_ALIGN_OF} ALIGN_OF OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_SIZE_OF} SIZEOF OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_ADDR} ADDR OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_LOAD_ADDR} LOADADDR OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_CONSTANT} CONSTANT OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_ORIGIN} ORIGIN OPEN_BRACKET value=ID CLOSE_BRACKET
        | {ATOMIC_LENGTH} LENGTH OPEN_BRACKET value=ID CLOSE_BRACKET    
    ;
    
    Atom returns Expression:
        {INTEGER_CONSTANT} value=INT
    ;
    
    我是否需要添加如下规则

    1. 1 +
    
    2. 1 + +
    
    3. 1 1
    
    4. 1 1 +
    
    案例1可由直接AST处理

    对于案例2:

    Operators:
       '+' | '-' | '*' | '/' etc...;
    
    AdditionOrSubtraction returns Expression:
        MultiplicationOrDivision (   ( {Addition.left=current} PLUS 
                                     | {Subtraction.left=current} MINUS
                                     ) 
                                     (right=MultiplicationOrDivision)
                                     | Operators  /* however how do I flag/paraphrase this to be of type Error of some sort? this may also be ambiguous grammar */
                                 )*
    ;
    

    对于案例3,我不知道这似乎和案例4一样困难。

    请查看
    识别异常的
    节点和
    标记的字段
    ,我的节点总是空的。我目前正在检查EOObject类型,以确定它是否为表达式,但是,我不能100%确定这是否正确。我想这取决于错误的情况,如果以及填写了哪些字段,以便我更好地理解:您想向上迭代您的AST,以找到任何不包含元素的节点,而该节点应该包含元素?@Joko我认为这是一个方面,然而,输入可能并不总是以我想象的方式被捕获,这就是为什么我认为AST可能不是我想要的。i、 1+++中的最后一个“+”是一元加号,而我假设它是二进制+。这让我觉得使用解析器的堆栈跟踪更自然(我想我没有),但我不确定。我只使用Xtext中的AST来解决任何问题,没有任何异常。。。你是完全使用自己的语法还是重复使用任何Xbase规则?@Joko这都是我的语法Xbase没有规则OK,也许发布你的语法会有帮助。如果您在问题涉及的规则中添加注释,这将有助于更好地理解您的问题。
    Operators:
       '+' | '-' | '*' | '/' etc...;
    
    AdditionOrSubtraction returns Expression:
        MultiplicationOrDivision (   ( {Addition.left=current} PLUS 
                                     | {Subtraction.left=current} MINUS
                                     ) 
                                     (right=MultiplicationOrDivision)
                                     | Operators  /* however how do I flag/paraphrase this to be of type Error of some sort? this may also be ambiguous grammar */
                                 )*
    ;