[antlr-interest] C and #define

Andy Tripp antlr at jazillian.com
Mon May 21 06:42:19 PDT 2007


Here's what I've got for handling C/C++ preprocessor directives:

protected RestOfPP :
(
        '\\'! Newline!          // note the "!"s to delete escaped newlines
        | Comment
        | CharLiteral                                                   
//avoid matching '"' as StringLiteral
        | StringLiteral                                                 
// without this, "//" inside string gets processed
        | {LA(2) != '*' && LA(2) != '/'}? '/'
        | '#'                   // "stringification"
        | ~('\r' | '\n' | '/')
)+
;

// note: I have one pass that removes any spaces after "#" (e.g. 
converts "# define" to "#define").
// That pass looks for PPspace tokens and removes the space. Then all 
other passes
// use the other PP rules below
PPspace         : "#" (Whitespace)+ RestOfPP
;

PPdefine        : "#define" (Whitespace)+ RestOfPP
;
PPif            : "#if" (Whitespace)+ RestOfPP
;
PPelse          : "#else"
;
PPelif          : "#elif" (Whitespace)+ RestOfPP
;
PPendif         : "#endif"
;
// Note the "*" instead of "+" here, to handle "#include<whatever.h>"
PPinclude       : "#include" (Whitespace)* RestOfPP
;
PPifdef         : "#ifdef" (Whitespace)+ RestOfPP
;
PPifndef        : "#ifndef" (Whitespace)+ RestOfPP
;
PPundef         : "#undef" (Whitespace)+ RestOfPP
;
PPpragma        : "#pragma" RestOfPP
;
PPerror         : "#error" (RestOfPP)?
;
PPline          : "#line" RestOfPP
;

Paul Keir wrote:
> Hi,
>
> I'm building on the C grammar from the examples, and would like to 
> modify the lexer rule which ignores lines starting with #; I'd like 
> not to ignore #define, but ignore the rest. Currently the rule is:
>
> // ignore #line info for now
> LINE_COMMAND
>    : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
>    ;
>
> Remembering that the # can be separated from the define, I've tried a 
> few things like this:
>
> // ignore #line info for now
> LINE_COMMAND
>    :  ~( '#' 'define' | '#define' ) ~('\n'|'\r')* '\r'? '\n' 
> {$channel=HIDDEN;}
>    ;
>
> but I can't get it to work as intended. Can anyone offer a suggestion?
>
> Best regards,
> Paul
>
>



More information about the antlr-interest mailing list