Reputation: 3374
i'm trying to write a rule for preprocessor instructions in XText. currently i implemented it like this way:
preproc:
type=PREPROCESSOR_INCLUDE_TYPE val=(STRING | PREPROCESSOR_INCLUDE_VAL)|
type=PREPROCESSOR_DEFINE_TYPE |
type=PREPROCESSOR_SINGLE_PARAM_TYPE val=ID|
type=PREPROCESSOR_NONE_PARAM_TYPE
;
terminal PREPROCESSOR_INCLUDE_TYPE: '#include'| '#import';
terminal PREPROCESSOR_INCLUDE_VAL: ' '+ '<'->'>';
terminal PREPROCESSOR_DEFINE_TYPE: '#define' -> '\n';
terminal PREPROCESSOR_SINGLE_PARAM_TYPE: '#undef' |'#ifdef' |'#ifndef' |'#pragma';
terminal PREPROCESSOR_NONE_PARAM_TYPE: '#else' | '#endif';
I do not really like this solution, but it is the only one that works of all the ones I tried. There is a smarter way to write a rule for preprocessor instructions?
How could i split the PREPROCESSOR_DEFINE_TYPE rule to separate the preprocessor instruction type(#define) from its value?
thanks a lot
EDIT
what I want to capture with these rules are the typical preprocessor instructions. For example:
#include "fileName"
#import <fileName>
#define IDENTIFIER
#define IDENTIFIER WHATEVER + YOU - WANT !
#undef IDENTIFIER
#else
#endif
What would be nice to have is to split the preprocessor type from its value in all the different cases
Raffaello.
Upvotes: 0
Views: 849
Reputation: 927
Basically you can't (out of the box) create languages that do pre-processing with XText. XText generates it's code for one grammar. Preprocessing requires 2 fitting grammars.
Here are the challenges http://www.eclipse.org/forums/index.php/mv/msg/366839/894493/#msg_894493
Just think for the case:
a = 1
#ifdef something
+1
#endif
;
So it is very inefficient to express all these in one grammar, hence makes it impractical in xtext. So without its support for multi-step, languages like C, make are out of its scope.
Upvotes: 1
Reputation: 13858
If I understand your question, you want an AST node for define rules, that has an attribute with the rest of the rule, but does not contain the #define
keyword.
The problem with the until
rule or the possible negation (!
) rules are, that they cause conflicts with the whitespace characters between the #define
and the instruction, so that could not be solved easily.
However, you could define a new terminal, that starts e.g. with a letter or _
, and ends with a newline, that could be added to your language, something as follows:
PREPROCESSOR_DEFINE_TYPE: '#define' instruction=Content
;
terminal Content:
('a'..'z'|'A'..'Z'|'_') -> '\n'
;
I did not test the solution, but it throws no errors in my Xtext editor, and is quite similar to the definition of ID parameters from Terminals.xtext
, so I believe it should be close to what you need.
Additionally, I don't think you have to define all the preprocessor types as terminals, as this way they become much more low-level constructs; I'd define as much as them as non-terminal rules as possible.
Upvotes: 0