Search code examples
xtextxtend

How to simulate a user's input (only internally)?


I need to parse something during the runtime of my eclipse plugin (created with Xtext) which would then be treated as if the user has typed it in but without actually popping up and beeing visible for the user as an input of himself.
For exmample I have this input:

for "i" from 1 to 3 do {};

My problem woth this input is that the variable i is not declared as a normal declaration with a "=" but I need the parser to tell that it is one. So I want to let the parser parse

i = 1;

so it recognizes it as a normal declaration and allows cross-references to it.

Greeting Krzmbrzl

EDIT:
All in all the thing I want is to add a statement i=1; to the AST

I just want to have eclipse support for an existing language so I'm not writing an interpreter nor a generator. The problem is that when I have a for-loop like above the actual interpreter of that language declares a variable i (or however it's named in the loop header) and therefore this variable is available in the loop body. In my case my parser doesn't recognise i as a variable because it only knows that a declaration is done via "=" so I can't use i in the loop body (if I try so I get the error that the declaration i cannot be resolved). This is why I want to add this declaration manually when such a loop is created. I don't need to worry about any compiling or interpreting difficulties because I don't do this myself. As I already said I just want to have all the cool eclipse features for this language.


Solution

  • Ok, now I understand your problem. It is still no good idea to add any element to the AST to resolve any cross reference! You don't do that! Instead you should try to refactor your grammar in a way that "i" in for "i" from ... is a compatible declaration of a variable. There are several tricks to do that. Have you completely read the Xtext documentation? Have also read the Xtext book? Both documents tell a lot about how to make Xtext do things you will not expect.

    Anyway, two tricks I often use are:

    1. Introduce an unused, abstract Parser Rule which you can then use as destination of a cross reference, but which is never used as an attribute (containment reference).

      AbstractDecl:
          VarDecl | ForVarDecl;
      VarDecl:
          name=ID ...;
      ForVarDecl:
          '"' name=ID '"';
      For:
          'for' decl=ForVarDecl 'from' from=INT 'to' to=INT 'do' block=Block;
      ...
      StatementWithCR:
          ref=[AbstractDecl] ...;
      
    2. Define any ParserRule, which returns an other type.

      ForDecl returns VarDecl:
           '"' name=ID '"';
      

    If you would post the grammar which corresponds to this specific problem, we could develop a solution which is safe. Adding anything to the AST during live processing content of the editor will lead to a faulty state which can destroy your document.