title: Xtext Creating verbose error messages for expressions: how to get the rule trace on a syntax error?
body: <p>I am attempting to extend a SyntaxErrorMessageProvider in order to override the syntax error messages however I don't know how to get the stack trace of the rules which invoked this syntax error:</p>
  
  <pre><code>class MySyntaxErrorMessageProvider extends SyntaxErrorMessageProvider {
      def override SyntaxErrorMessage getSyntaxErrorMessage(ISyntaxErrorMessageProvider.IParserErrorContext context) {
          if(context.recognitionException != null) {
              handle(context.recognitionException)
          } else {
              handleException(context)
          }
  </code></pre>
  
  <p>What I would like to achieve is for instance when given the following text:</p>
  
  <pre><code>1. 1 +
  
  2. 1 + +
  
  3. 1 1
  
  4. 1 1 +
  </code></pre>
  
  <p>The error messages should be and give the following quickfix options:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>The quickfixes for these options could be (Addition or Removal):</p>
  
  <pre><code>1. Remove the + or Add in an expression
  
  2. Add in an operand/expression for both ends of + or remove leftmost token.
  </code></pre>
  
  <p>I am struggling to find a way to do this using the Xtext api. I have gotten the INode of the incorrect parse but what I'm getting from these nodes is not the complete input as I walk the tree using the .getAsTreeIterable(). It is only showing the text which would be valid in the model.</p>
  
  <ol>
  <li><p>Would I have to add in some error rules to the grammar that would capture these incorrect cases just to be able to identify them using the INode interface?</p></li>
  <li><p>Input:</p>
  
  <p>badinput = 1 + 2 + +</p></li>
  </ol>
  
  <p>I get the following nodes:</p>
  
  <pre><code>Start....
  
  Defsym_exprImpl@153802c5 (defSymbolName: badinput)
  
  AdditionImpl@1dc74ee0
  
  AdditionImpl@2335d787
  
  INTEGER_CONSTANTImpl@19816081 (value: 1)
  
  INTEGER_CONSTANTImpl@4cfa675e (value: 2)
  
  UNARY_PLUSImpl@6bed906f
  
  End....
  </code></pre>
  
  <p>of which I could iterate through them and check whether some of their corresponding values are Null, would this be the right way forward?</p>
  
  <p>Does anyone have any more suggestions to offer?</p>
  
  <p>The grammar for my implementation is below:</p>
  
  <pre><code>    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
  ;
  </code></pre>
  
  <p>Would I need to add in rules such as the following?</p>
  
  <pre><code>1. 1 +
  
  2. 1 + +
  
  3. 1 1
  
  4. 1 1 +
  </code></pre>
  
  <p>Case 1 could be handled by the direct AST</p>
  
  <p>For Case 2:</p>
  
  <pre><code>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 */
                               )*
  ;
  </code></pre>
  
  <p>For Case 3 I dont know that seems hard aswell as case 4.</p>