use strict;
use warnings FATAL => 'all';
package MarpaX::Languages::C::AST::Grammar::ISO_ANSI_C_2011;
use MarpaX::Languages::C::AST::Grammar::ISO_ANSI_C_2011::Actions;
use Carp qw/croak/;
use IO::String;
# ABSTRACT: ISO ANSI C 2011 grammar written in Marpa BNF
our $VERSION = '0.48'; # VERSION
our %DEFAULT_PAUSE = (
TYPEDEF_NAME => 'before',
ENUMERATION_CONSTANT => 'before',
IDENTIFIER => 'before',
SEMICOLON => 'after',
LCURLY_SCOPE => 'after',
LCURLY_REENTERSCOPE => 'after',
RCURLY_SCOPE => 'after',
COMMA => 'after',
EQUAL => 'after',
LPAREN_SCOPE => 'after',
RPAREN_SCOPE => 'after',
ANY_ASM => 'after',
);
our $DEFAULTACTIONOBJECT = sprintf('%s::%s', __PACKAGE__, 'Actions');
our $DEFAULTNONTERMINALSEMANTIC = ':default ::= action => [values] bless => ::lhs';
our $DEFAULTTERMINALSEMANTIC = 'lexeme default = action => [start,length,value,name] forgiving => 1';
our $DATA = do {local $/; <DATA>};
sub new {
my ($class, $pausep, $start, $actionObject, $nonTerminalSemantic, $terminalSemantic) = @_;
$actionObject //= $DEFAULTACTIONOBJECT;
my $self = {
_grammar_option => {},
_recce_option => {semantics_package => $actionObject, ranking_method => 'high_rule_only'},
};
#
# Rework the grammar to have the pauses:
# Those in %DEFAULT_PAUSE cannot be altered.
# The other lexemes given in argument will get a pause => after eventually
#
my %pause = ();
if (defined($pausep)) {
if (ref($pausep) ne 'HASH') {
croak 'pausep must be a reference to HASH';
}
map {$pause{$_} = 'after'} keys %{$pausep};
}
map {$pause{$_} = $DEFAULT_PAUSE{$_}} keys %DEFAULT_PAUSE;
$self->{_content} = '';
my $allb = exists($pause{__ALL__});
my $pragmas = '';
if (defined($start) && "$start") {
#
# User gave a custom start, we assume he will hit inaccessible symbols
#
$pragmas = "\ninaccessible is ok by default\n";
} else {
$start = 'translationUnit';
}
my $data = IO::String->new($DATA);
while (defined($_ = <$data>)) {
my $line = $_;
if ($line =~ /^\s*:lexeme\s*~\s*<(\w+)>/) {
my $lexeme = substr($line, $-[1], $+[1] - $-[1]);
#
# Doing this test first will make sure DEFAULT_PAUSE lexemes
# will always get the correct 'pause' value (i.e. after or before)
#
if (exists($pause{$lexeme})) {
if (! ($line =~ /\bpause\b/)) {
substr($line, -1, 1) = " pause => $pause{$lexeme}\n";
}
} elsif ($allb) {
if (! ($line =~ /\bpause\b/)) {
#
# Hardcoded to 'after'
#
substr($line, -1, 1) = " pause => after\n";
}
}
}
$self->{_content} .= $line;
}
$nonTerminalSemantic //= $DEFAULTNONTERMINALSEMANTIC;
$terminalSemantic //= $DEFAULTTERMINALSEMANTIC;
$self->{_content} =~ s/\$PRAGMAS\n/$pragmas/;
$self->{_content} =~ s/\$START\n/$start/;
$self->{_content} =~ s/\$NONTERMINALSEMANTIC\b/$nonTerminalSemantic/;
$self->{_content} =~ s/\$TERMINALSEMANTIC\b/$terminalSemantic/;
bless($self, $class);
return $self;
}
sub content {
my ($self) = @_;
return $self->{_content};
}
sub grammar_option {
my ($self) = @_;
return $self->{_grammar_option};
}
sub recce_option {
my ($self) = @_;
return $self->{_recce_option};
}
1;
=pod
=encoding UTF-8
=head1 NAME
MarpaX::Languages::C::AST::Grammar::ISO_ANSI_C_2011 - ISO ANSI C 2011 grammar written in Marpa BNF
=head1 VERSION
version 0.48
=head1 SYNOPSIS
use strict;
use warnings FATAL => 'all';
use MarpaX::Languages::C::AST::Grammar::ISO_ANSI_C_2011;
my $grammar = MarpaX::Languages::C::AST::Grammar::ISO_ANSI_C_2011->new();
my $grammar_content = $grammar->content();
my $grammar_option = $grammar->grammar_option();
my $recce_option = $grammar->recce_option();
=head1 DESCRIPTION
This modules contains the ISO ANSI C 2011 C grammar written in Marpa BNF, as of L<http://www.quut.com/c/ANSI-C-grammar-y-2011.html> and L<http://www.quut.com/c/ANSI-C-grammar-l.html>.
=head1 SUBROUTINES/METHODS
=head2 new([$pausep, $start, $actionObject, $nonTerminalSemantic, $terminalSemantic])
Instance a new object. Takes an eventual reference to a HASH for lexemes for which a pause after is requested, followed by an eventual start rule, an eventual action object, an eventual default non-terminal semantic action, a default terminal semantic action. Default paused lexemes is hardcoded to a list of lexeme that must always be paused, and this list cannot be altered. Default start rule is 'translationUnit'. Default action object is hardcoded to __PACKAGE__::Actions module. Default non-terminal semantic is hardcoded to ':default ::= action => [values] bless => ::lhs'. Default terminal semantic is hardcoded to :'lexeme default = action => [start,length,value] forgiving => 1'.
=head2 content()
Returns the content of the grammar. Takes no argument.
=head2 grammar_option()
Returns recommended option for Marpa::R2::Scanless::G->new(), returned as a reference to a hash.
=head2 recce_option()
Returns recommended option for Marpa::R2::Scanless::R->new(), returned as a reference to a hash.
=head1 AUTHOR
Jean-Damien Durand <jeandamiendurand@free.fr>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by Jean-Damien Durand.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
__DATA__
################################################################################################################
# grammar
#
# 2011 ISO C, as of http://www.quut.com/c/ANSI-C-grammar-l.html
# http://www.quut.com/c/ANSI-C-grammar-y-2011.html
#
################################################################################################################
$PRAGMAS
#
# Defaults
#
$NONTERMINALSEMANTIC
$TERMINALSEMANTIC
#
# G1 (grammar), c.f. http://www.quut.com/c/ANSI-C-grammar-y-2011.html
#
:start ::= $START
primaryExpression
::= IDENTIFIER
| constant
| string
| LPAREN expression RPAREN
| genericSelection
| gccStatementExpression
constant
::= I_CONSTANT # includes character_constant
| F_CONSTANT
| ENUMERATION_CONSTANT # after it has been defined as such
event 'enumerationConstantIdentifier$' = completed <enumerationConstantIdentifier>
enumerationConstantIdentifier # before it has been defined as such
::= IDENTIFIER_UNAMBIGUOUS
enumerationConstant # before it has been defined as such
::= enumerationConstantIdentifier
stringLiteral ::= STRING_LITERAL_UNIT+
string
::= stringLiteral
| FUNC_NAME
genericSelection
::= GENERIC LPAREN assignmentExpression COMMA genericAssocList RPAREN
genericAssocList ::= genericAssociation+ separator => COMMA proper => 1
genericAssociation
::= typeName COLON assignmentExpression
| DEFAULT COLON assignmentExpression
postfixExpression
::= primaryExpression
| postfixExpression LBRACKET expression RBRACKET
| postfixExpression LPAREN RPAREN
| postfixExpression LPAREN argumentExpressionList RPAREN
| gccBuiltinVaStart
| gccBuiltinVaEnd
| gccBuiltinVaArg
| gccBuiltinOffsetof
| postfixExpression DOT IDENTIFIER_UNAMBIGUOUS
| postfixExpression PTR_OP IDENTIFIER_UNAMBIGUOUS
| postfixExpression INC_OP
| postfixExpression DEC_OP
| LPAREN typeName RPAREN LCURLY initializerList RCURLY
| LPAREN typeName RPAREN LCURLY initializerList COMMA RCURLY
argumentExpressionList
::= assignmentExpression
| argumentExpressionList COMMA assignmentExpression
| argumentExpressionList COMMA
gccAlignofExpression ::= GCC_ALIGNOF unaryExpression
| GCC_ALIGNOF LPAREN typeName RPAREN
unaryExpression
::= postfixExpression
| gccExtension postfixExpression
| INC_OP unaryExpression
| DEC_OP unaryExpression
| unaryOperator castExpression
| SIZEOF unaryExpression
| SIZEOF LPAREN typeName RPAREN
| ALIGNOF LPAREN typeName RPAREN
| gccAlignofExpression
unaryOperator
::= AMPERSAND
| STAR
| PLUS
| HYPHEN
| TILDE
| EXCLAMATION
castExpression
::= unaryExpression
| LPAREN typeName RPAREN castExpression
multiplicativeExpression
::= castExpression
| multiplicativeExpression STAR castExpression
| multiplicativeExpression SLASH castExpression
| multiplicativeExpression PERCENT castExpression
additiveExpression
::= multiplicativeExpression
| additiveExpression PLUS multiplicativeExpression
| additiveExpression HYPHEN multiplicativeExpression
shiftExpression
::= additiveExpression
| shiftExpression LEFT_OP additiveExpression
| shiftExpression RIGHT_OP additiveExpression
relationalExpression
::= shiftExpression
| relationalExpression LESS_THAN shiftExpression
| relationalExpression GREATER_THAN shiftExpression
| relationalExpression LE_OP shiftExpression
| relationalExpression GE_OP shiftExpression
equalityExpression
::= relationalExpression
| equalityExpression EQ_OP relationalExpression
| equalityExpression NE_OP relationalExpression
andExpression
::= equalityExpression
| andExpression AMPERSAND equalityExpression
exclusiveOrExpression
::= andExpression
| exclusiveOrExpression CARET andExpression
inclusiveOrExpression
::= exclusiveOrExpression
| inclusiveOrExpression VERTICAL_BAR exclusiveOrExpression
logicalAndExpression
::= inclusiveOrExpression
| logicalAndExpression AND_OP inclusiveOrExpression
logicalOrExpression
::= logicalAndExpression
| logicalOrExpression OR_OP logicalAndExpression
#
# Following yafce: in C grammar they put conditionalExpression, but in fact it must be
# assignmentExpression, otherwise pnp ? x : x = 0x388;
# C.f. http://padator.org/software/project-yacfe/
#
conditionalExpression
::= logicalOrExpression
| logicalOrExpression QUESTION_MARK expression COLON assignmentExpression
| logicalOrExpression QUESTION_MARK COLON assignmentExpression # GCC Extension
#
# Following yafce: in C grammar they put unaryExpression, but in fact it must be
# castExpression, otherwise (int * ) xxx = &yy; is not allowed
# C.f. http://padator.org/software/project-yacfe/
#
assignmentExpression
::= conditionalExpression
| castExpression assignmentOperator assignmentExpression
assignmentOperator
::= EQUAL
| MUL_ASSIGN
| DIV_ASSIGN
| MOD_ASSIGN
| ADD_ASSIGN
| SUB_ASSIGN
| LEFT_ASSIGN
| RIGHT_ASSIGN
| AND_ASSIGN
| XOR_ASSIGN
| OR_ASSIGN
expression
::= assignmentExpression
| expression COMMA assignmentExpression
constantExpression
::= conditionalExpression # with constraints
# ###############################################################################################
# A directDeclarator introduces a typedefName only when it eventually participates in the grammar
# rule:
# declaration ::= declarationSpecifiers initDeclaratorList SEMICOLON
# ###############################################################################################
event 'declarationCheckdeclarationSpecifiers$' = completed <declarationCheckdeclarationSpecifiers>
declarationCheckdeclarationSpecifiers ::= declarationSpecifiers
event 'declarationCheckinitDeclaratorList$' = completed <declarationCheckinitDeclaratorList>
declarationCheckinitDeclaratorList ::= initDeclaratorList
event 'declarationCheck$' = completed <declarationCheck>
declarationCheck ::= declarationCheckdeclarationSpecifiers declarationCheckinitDeclaratorList SEMICOLON
declaration
::= declarationSpecifiers SEMICOLON
| declarationCheck
| staticAssertDeclaration
gccExtension ::= GCC_EXTENSION
#declarationSpecifiersUnit ::= storageClassSpecifier
# | typeSpecifier
# | typeQualifier
# | functionSpecifier
# | alignmentSpecifier
# | gccExtension
declarationSpecifiers ::= declarationSpecifiers0
| declarationSpecifiers1
| declarationSpecifiers2
declarationSpecifiers0 ::= # List without type specifiers
storageClassSpecifier
| declarationSpecifiers0 storageClassSpecifier
| typeQualifier
| declarationSpecifiers0 typeQualifier
| functionSpecifier
| declarationSpecifiers0 functionSpecifier
| alignmentSpecifier
| declarationSpecifiers0 alignmentSpecifier
| gccExtension
| declarationSpecifiers0 gccExtension
declarationSpecifiers1 ::= # List with a single typeSpecifier1
typeSpecifier1
| declarationSpecifiers0 typeSpecifier1
| declarationSpecifiers1 storageClassSpecifier
| declarationSpecifiers1 typeQualifier
| declarationSpecifiers1 functionSpecifier
| declarationSpecifiers1 alignmentSpecifier
| declarationSpecifiers1 gccExtension
declarationSpecifiers2 ::= # List with one or more typeSpecifier2
typeSpecifier2
| declarationSpecifiers0 typeSpecifier2
| declarationSpecifiers2 typeSpecifier2
| declarationSpecifiers2 storageClassSpecifier
| declarationSpecifiers2 typeQualifier
| declarationSpecifiers2 functionSpecifier
| declarationSpecifiers2 alignmentSpecifier
| declarationSpecifiers2 gccExtension
# declarationSpecifiers ::= declarationSpecifiersUnit+
initDeclaratorList ::= initDeclarator+ separator => COMMA proper => 1
initDeclarator
::= declarator EQUAL initializer
| declarator
event 'storageClassSpecifierTypedef$' = completed <storageClassSpecifierTypedef>
storageClassSpecifierTypedef
::= TYPEDEF
storageClassSpecifier
::= storageClassSpecifierTypedef # identifiers must be flagged as TYPEDEF_NAME
| EXTERN
| STATIC
| THREAD_LOCAL
| AUTO
| REGISTER
#
# Following advice at http://eli-project.sourceforge.net/c_html/c.html, typeSpecifier is
# divided into two parts: those than only appear in lists of one element, those that can be
# be used to form lists of one or more elements
#
typeSpecifier1
::= VOID
| FLOAT
| structOrUnionSpecifier
| enumSpecifier
| TYPEDEF_NAME # after it has been defined as such
typeSpecifier2
::= CHAR
| SHORT
| INT
| LONG
| DOUBLE
| SIGNED
| UNSIGNED
| BOOL
| LABEL
| COMPLEX
| IMAGINARY # non-mandated extension
| atomicTypeSpecifier
| msvsBuiltinType
| gccBuiltinType
event 'structContextStart[]' = nulled <structContextStart>
structContextStart ::=
event 'structContextEnd[]' = nulled <structContextEnd>
structContextEnd ::=
structOrUnionSpecifier
::= structOrUnion LCURLY (<structContextStart>) structDeclarationList RCURLY (<structContextEnd>)
| structOrUnion IDENTIFIER_UNAMBIGUOUS LCURLY (<structContextStart>) structDeclarationList RCURLY (<structContextEnd>)
| structOrUnion IDENTIFIER_UNAMBIGUOUS
structOrUnion
::= STRUCT
| UNION
structDeclarationList ::= structDeclaration+
structDeclaration
::= specifierQualifierList SEMICOLON # for anonymous struct/union
| specifierQualifierList structDeclaratorList SEMICOLON
| SEMICOLON # GCC extension
#specifierQualifierListUnit ::= typeSpecifier
# | typeQualifier
# | gccExtension
# specifierQualifierList ::= specifierQualifierListUnit+
specifierQualifierList ::= specifierQualifierList0
| specifierQualifierList1
| specifierQualifierList2
specifierQualifierList0 ::= # List without type specifiers
typeQualifier
| specifierQualifierList0 typeQualifier
| gccExtension
| specifierQualifierList0 gccExtension
specifierQualifierList1 ::= # List with a single typeSpecifier1
typeSpecifier1
| specifierQualifierList0 typeSpecifier1
| specifierQualifierList1 typeQualifier
| specifierQualifierList1 gccExtension
specifierQualifierList2 ::= # List with one or more typeSpecifier2
typeSpecifier2
| specifierQualifierList0 typeSpecifier2
| specifierQualifierList2 typeSpecifier2
| specifierQualifierList2 typeQualifier
| specifierQualifierList2 gccExtension
structDeclaratorList ::= structDeclarator+ separator => COMMA proper => 1
structDeclarator
::= COLON constantExpression
| declarator COLON constantExpression
| declarator
enumSpecifier
::= ENUM LCURLY enumeratorList RCURLY
| ENUM IDENTIFIER_UNAMBIGUOUS LCURLY enumeratorList RCURLY
| ENUM IDENTIFIER_UNAMBIGUOUS
#
# Saying 0 allow to have a final COMMA after the list
#
enumeratorList ::= enumerator+ separator => COMMA proper => 0
enumerator # identifiers must be flagged as ENUMERATION_CONSTANT
::= enumerationConstant EQUAL constantExpression
| enumerationConstant
atomicTypeSpecifier
::= ATOMIC LPAREN typeName RPAREN
typeQualifier
::= CONST
| RESTRICT
| VOLATILE
| ATOMIC
| MSVS_W64
| MSVS_PTR32
| MSVS_PTR64
| MSVS_UNALIGNED
| MSVS_SPTR
| MSVS_UPTR
functionSpecifier
::= INLINE
| NORETURN
alignmentSpecifier
::= ALIGNAS LPAREN typeName RPAREN
| ALIGNAS LPAREN constantExpression RPAREN
msvsAttributeAny ::= msvsAttribute*
declarator
::= pointer msvsAttributeAny directDeclarator
| pointer msvsAttributeAny directDeclarator gccAsmExpression
| msvsAttributeAny directDeclarator
| msvsAttributeAny directDeclarator gccAsmExpression
#
# It is VERY important that directDeclaratorIdentifier remains forever an LHS
# with a single RHS: IDENTIFIER, c.f. comment in AST.pm
#
event 'directDeclaratorIdentifier$' = completed <directDeclaratorIdentifier>
directDeclaratorIdentifier
::= IDENTIFIER
directDeclarator
::= directDeclaratorIdentifier
| LPAREN declarator RPAREN
| directDeclarator LBRACKET RBRACKET
| directDeclarator LBRACKET STAR RBRACKET
| directDeclarator LBRACKET STATIC typeQualifierList assignmentExpression RBRACKET
| directDeclarator LBRACKET STATIC assignmentExpression RBRACKET
| directDeclarator LBRACKET typeQualifierList STAR RBRACKET
| directDeclarator LBRACKET typeQualifierList STATIC assignmentExpression RBRACKET
| directDeclarator LBRACKET typeQualifierList assignmentExpression RBRACKET
| directDeclarator LBRACKET typeQualifierList RBRACKET
| directDeclarator LBRACKET assignmentExpression RBRACKET
| directDeclarator LPAREN_SCOPE parameterTypeList RPAREN_SCOPE
| directDeclarator LPAREN_SCOPE RPAREN_SCOPE
| directDeclarator LPAREN_SCOPE identifierList RPAREN_SCOPE
pointerQualifier ::= typeQualifier
pointerQualifierList ::= pointerQualifier+
pointer
::= msvsAttributeAny STAR pointerQualifierList pointer
| msvsAttributeAny STAR pointerQualifierList
| msvsAttributeAny STAR pointer
| msvsAttributeAny STAR
typeQualifierList ::= typeQualifier+
#typeQualifierList
# ::= typeQualifier
# | typeQualifierList typeQualifier
parameterTypeList
::= parameterList COMMA ELLIPSIS
| parameterList
parameterList ::= parameterDeclaration+ separator => COMMA proper => 1
event 'parameterDeclarationdeclarationSpecifiers$' = completed <parameterDeclarationdeclarationSpecifiers>
parameterDeclarationdeclarationSpecifiers ::= declarationSpecifiers
event 'parameterDeclarationCheck$' = completed <parameterDeclarationCheck>
parameterDeclarationCheck ::= parameterDeclarationdeclarationSpecifiers parameterDeclarationCheckDeclarator
event 'parameterDeclarationCheckDeclarator$' = completed <parameterDeclarationCheckDeclarator>
parameterDeclarationCheckDeclarator ::= declarator
parameterDeclaration
::= parameterDeclarationCheck rank => 0
| declarationSpecifiers abstractDeclarator rank => -1
| declarationSpecifiers rank => -2
identifierList ::= IDENTIFIER+ separator => COMMA proper => 1
typeName
::= specifierQualifierList abstractDeclarator
| specifierQualifierList
abstractDeclarator
::= pointer msvsAttributeAny directAbstractDeclarator
| pointer msvsAttributeAny directAbstractDeclarator gccAsmExpression
| pointer msvsAttributeAny
| directAbstractDeclarator
| directAbstractDeclarator gccAsmExpression
directAbstractDeclarator
::= LPAREN abstractDeclarator RPAREN
| LBRACKET RBRACKET
| LBRACKET STAR RBRACKET
| LBRACKET STATIC typeQualifierList assignmentExpression RBRACKET
| LBRACKET STATIC assignmentExpression RBRACKET
| LBRACKET typeQualifierList STATIC assignmentExpression RBRACKET
| LBRACKET typeQualifierList assignmentExpression RBRACKET
| LBRACKET typeQualifierList RBRACKET
| LBRACKET assignmentExpression RBRACKET
| directAbstractDeclarator LBRACKET RBRACKET
| directAbstractDeclarator LBRACKET STAR RBRACKET
| directAbstractDeclarator LBRACKET STATIC typeQualifierList assignmentExpression RBRACKET
| directAbstractDeclarator LBRACKET STATIC assignmentExpression RBRACKET
| directAbstractDeclarator LBRACKET typeQualifierList assignmentExpression RBRACKET
| directAbstractDeclarator LBRACKET typeQualifierList STATIC assignmentExpression RBRACKET
| directAbstractDeclarator LBRACKET typeQualifierList RBRACKET
| directAbstractDeclarator LBRACKET assignmentExpression RBRACKET
| LPAREN RPAREN
| LPAREN parameterTypeList RPAREN
| directAbstractDeclarator LPAREN RPAREN
| directAbstractDeclarator LPAREN parameterTypeList RPAREN
initializer
::= LCURLY initializerList RCURLY
| LCURLY initializerList COMMA RCURLY
| assignmentExpression
initializerList
::= designation initializer
| initializer
| IDENTIFIER COLON initializer
| initializerList COMMA designation initializer
| initializerList COMMA initializer
designation
::= designatorList EQUAL
designatorList ::= designator+
designator
::= LBRACKET constantExpression RBRACKET
| DOT IDENTIFIER_UNAMBIGUOUS
| LBRACKET constantExpression ELLIPSIS constantExpression RBRACKET # GCC Extension
staticAssertDeclaration
::= STATIC_ASSERT LPAREN constantExpression COMMA stringLiteral RPAREN SEMICOLON
statement
::= labeledStatement
| compoundStatement
| expressionStatement
| selectionStatement
| iterationStatement
| jumpStatement
| opaqueAsmStatement
| gccAsmStatement
labeledStatement
::= IDENTIFIER COLON statement
| CASE constantExpression COLON statement
| CASE constantExpression (WS_MANY) COLON statement
| CASE constantExpression (WS_MANY) ELLIPSIS (WS_MANY) constantExpression COLON statement
| DEFAULT COLON statement
compoundStatement
::= LCURLY_SCOPE RCURLY_SCOPE
| LCURLY_SCOPE blockItemList RCURLY_SCOPE
blockItemList ::= blockItem+
blockItem
::= declaration
| statement
expressionStatement
::= SEMICOLON
| expression SEMICOLON
selectionStatement
::= IF LPAREN expression RPAREN statement ELSE statement
| IF LPAREN expression RPAREN statement rank => 1
| SWITCH LPAREN expression RPAREN statement
iterationStatement
::= WHILE LPAREN expression RPAREN statement
| DO statement WHILE LPAREN expression RPAREN SEMICOLON
| FOR LPAREN expressionStatement expressionStatement RPAREN statement
| FOR LPAREN expressionStatement expressionStatement expression RPAREN statement
| FOR LPAREN declaration expressionStatement RPAREN statement
| FOR LPAREN declaration expressionStatement expression RPAREN statement
jumpStatement
::= GOTO IDENTIFIER_UNAMBIGUOUS SEMICOLON
| CONTINUE SEMICOLON
| BREAK SEMICOLON
| RETURN SEMICOLON
| RETURN expression SEMICOLON
event 'translationUnit$' = completed <translationUnit>
translationUnit ::= externalDeclaration*
event '^externalDeclaration' = predicted <externalDeclaration>
externalDeclaration
::= functionDefinition
| declaration
| SEMICOLON
compoundStatementReenterScope ::= LCURLY_REENTERSCOPE RCURLY_SCOPE
| LCURLY_REENTERSCOPE blockItemList RCURLY_SCOPE
functionDefinition
::= functionDefinitionCheck1
| functionDefinitionCheck2
event 'fileScopeDeclarator$' = completed <fileScopeDeclarator>
fileScopeDeclarator ::= declarator
event 'functionDefinitionCheck1$' = completed <functionDefinitionCheck1>
functionDefinitionCheck1 ::= functionDefinitionCheck1declarationSpecifiers fileScopeDeclarator functionDefinitionCheck1declarationList compoundStatementReenterScope
event 'functionDefinitionCheck2$' = completed <functionDefinitionCheck2>
functionDefinitionCheck2 ::= functionDefinitionCheck2declarationSpecifiers fileScopeDeclarator compoundStatementReenterScope
event 'functionDefinitionCheck1declarationSpecifiers$' = completed <functionDefinitionCheck1declarationSpecifiers>
functionDefinitionCheck1declarationSpecifiers ::= declarationSpecifiers
event 'functionDefinitionCheck2declarationSpecifiers$' = completed <functionDefinitionCheck2declarationSpecifiers>
functionDefinitionCheck2declarationSpecifiers ::= declarationSpecifiers
event 'functionDefinitionCheck1declarationList$' = completed <functionDefinitionCheck1declarationList>
functionDefinitionCheck1declarationList ::= declarationList
declarationList ::= declaration+
#
# G0 (tokens), c.f. http://www.quut.com/c/ANSI-C-grammar-l.html
#
# Intermediary tokens
O ~ [0-7]
O_any ~ O*
D ~ [0-9]
D_any ~ D*
D_many ~ D+
NZ ~ [1-9]
L ~ [a-zA-Z_]
A ~ [a-zA-Z_0-9]
A_any ~ A*
H ~ [a-fA-F0-9]
H_any ~ H*
H_many ~ H+
HP ~ '0' [xX]
B ~ [0-1]
B_many ~ B+
BP ~ '0' [bB]
SIGN_maybe ~ [+-]
SIGN_maybe ~
E ~ [Ee] SIGN_maybe D_many
E_maybe ~ E
E_maybe ~
P ~ [Pp] SIGN_maybe D_many
FS ~ [fFlL]
FS_maybe ~ FS
FS_maybe ~
LL ~ 'll' | 'LL' | [lL]
LL_maybe ~ LL
LL_maybe ~
U ~ [uU]
U_maybe ~ U
U_maybe ~
IS ~ U LL_maybe | LL U_maybe
IS_maybe ~ IS
IS_maybe ~
CP ~ [uUL]
CP_maybe ~ CP
CP_maybe ~
SP ~ 'u8' | [uUL]
SP_maybe ~ SP
SP_maybe ~
ES_AFTERBS ~ [\'\"\?\\abfnrtve]
| O
| O O
| O O O
| 'x' H_many
ES ~ BS ES_AFTERBS
WS ~ [ \t\v\n\f]
WS_any ~ WS*
WS_many ~ WS+
WS_MANY ~ WS+
# Lexemes
:lexeme ~ <AUTO> priority => -1
AUTO ~ 'auto'
:lexeme ~ <BREAK> priority => -2
BREAK ~ 'break'
:lexeme ~ <CASE> priority => -3
CASE ~ 'case'
:lexeme ~ <CHAR> priority => -4
CHAR ~ 'char'
:lexeme ~ <CONST> priority => -5
CONST ~ 'const'
CONST ~ '__const'
CONST ~ 'const__'
CONST ~ '__const__'
:lexeme ~ <CONTINUE> priority => -6
CONTINUE ~ 'continue'
:lexeme ~ <DEFAULT> priority => -7
DEFAULT ~ 'default'
:lexeme ~ <DO> priority => -8
DO ~ 'do'
:lexeme ~ <DOUBLE> priority => -9
DOUBLE ~ 'double'
:lexeme ~ <ELSE> priority => -10
ELSE ~ 'else'
:lexeme ~ <ENUM> priority => -11
ENUM ~ 'enum'
:lexeme ~ <EXTERN> priority => -12
EXTERN ~ 'extern'
:lexeme ~ <FLOAT> priority => -13
FLOAT ~ 'float'
:lexeme ~ <FOR> priority => -14
FOR ~ 'for'
:lexeme ~ <GOTO> priority => -15
GOTO ~ 'goto'
:lexeme ~ <IF> priority => -16
IF ~ 'if'
:lexeme ~ <INLINE> priority => -17
INLINE ~ 'inline'
INLINE ~ '__inline__'
INLINE ~ 'inline__'
INLINE ~ '__inline'
INLINE ~ '__forceinline' # MSVS
INLINE ~ '_inline' # MSVS backward compatbility
:lexeme ~ <INT> priority => -18
INT ~ 'int'
:lexeme ~ <LONG> priority => -19
LONG ~ 'long'
:lexeme ~ <REGISTER> priority => -20
REGISTER ~ 'register'
:lexeme ~ <RESTRICT> priority => -21
RESTRICT ~ 'restrict'
RESTRICT ~ '__restrict'
RESTRICT ~ 'restrict__'
RESTRICT ~ '__restrict__' # gcc
:lexeme ~ <RETURN> priority => -22
RETURN ~ 'return'
:lexeme ~ <SHORT> priority => -23
SHORT ~ 'short'
:lexeme ~ <SIGNED> priority => -24
SIGNED ~ 'signed'
SIGNED ~ '__signed'
SIGNED ~ '__signed__'
:lexeme ~ <SIZEOF> priority => -25
SIZEOF ~ 'sizeof'
:lexeme ~ <STATIC> priority => -26
STATIC ~ 'static'
:lexeme ~ <STRUCT> priority => -27
STRUCT ~ 'struct'
:lexeme ~ <SWITCH> priority => -28
SWITCH ~ 'switch'
:lexeme ~ <TYPEDEF> priority => -29
TYPEDEF ~ 'typedef'
:lexeme ~ <UNION> priority => -30
UNION ~ 'union'
:lexeme ~ <UNSIGNED> priority => -31
UNSIGNED ~ 'unsigned'
UNSIGNED ~ '__unsigned'
UNSIGNED ~ '__unsigned__'
:lexeme ~ <VOID> priority => -32
VOID ~ 'void'
:lexeme ~ <VOLATILE> priority => -33
VOLATILE ~ 'volatile'
VOLATILE ~ '__volatile'
VOLATILE ~ 'volatile__'
VOLATILE ~ '__volatile__'
:lexeme ~ <WHILE> priority => -34
WHILE ~ 'while'
:lexeme ~ <ALIGNAS> priority => -35
ALIGNAS ~ '_Alignas'
:lexeme ~ <ALIGNOF> priority => -36
ALIGNOF ~ '_Alignof'
:lexeme ~ <ATOMIC> priority => -37
ATOMIC ~ '_Atomic'
:lexeme ~ <BOOL> priority => -38
BOOL ~ '_Bool'
:lexeme ~ <LABEL> priority => -38
LABEL ~ '__label__'
:lexeme ~ <COMPLEX> priority => -39
COMPLEX ~ '_Complex'
COMPLEX ~ '__complex'
COMPLEX ~ '__complex__'
:lexeme ~ <GENERIC> priority => -40
GENERIC ~ '_Generic'
:lexeme ~ <IMAGINARY> priority => -41
IMAGINARY ~ '_Imaginary'
:lexeme ~ <NORETURN> priority => -42
NORETURN ~ '_Noreturn'
:lexeme ~ <STATIC_ASSERT> priority => -43
STATIC_ASSERT ~ '_Static_assert'
:lexeme ~ <THREAD_LOCAL> priority => -44
THREAD_LOCAL ~ '_Thread_local'
THREAD_LOCAL ~ '__thread' # gcc
:lexeme ~ <FUNC_NAME> priority => -45
FUNC_NAME ~ '__func__'
#
## DETERMINED AT RUN TIME
#
:lexeme ~ <TYPEDEF_NAME> priority => -100
:lexeme ~ <ENUMERATION_CONSTANT> priority => -100
:lexeme ~ <IDENTIFIER> priority => -100
:lexeme ~ <IDENTIFIER_UNAMBIGUOUS> priority => -100
_IDENTIFIER ~ L A_any
TYPEDEF_NAME ~ _IDENTIFIER
ENUMERATION_CONSTANT ~ _IDENTIFIER
IDENTIFIER ~ _IDENTIFIER
IDENTIFIER_UNAMBIGUOUS ~ _IDENTIFIER
:lexeme ~ <I_CONSTANT> priority => -101
I_CONSTANT ~ HP H_many IS_maybe
| BP B_many IS_maybe # Gcc extension: binary constants
| NZ D_any IS_maybe
| '0' O_any IS_maybe
| CP_maybe QUOTE I_CONSTANT_INSIDE_many QUOTE
:lexeme ~ <F_CONSTANT> priority => -102
F_CONSTANT ~ D_many E FS_maybe
| D_any '.' D_many E_maybe FS_maybe
| D_many '.' E_maybe FS_maybe
| HP H_many P FS_maybe
| HP H_any '.' H_many P FS_maybe
| HP H_many '.' P FS_maybe
:lexeme ~ <STRING_LITERAL_UNIT> priority => -103
STRING_LITERAL_INSIDE ~ [^"\\\n]
STRING_LITERAL_INSIDE ~ ES
STRING_LITERAL_INSIDE_any ~ STRING_LITERAL_INSIDE*
STRING_LITERAL_UNIT ~ SP_maybe '"' STRING_LITERAL_INSIDE_any '"' WS_any
:lexeme ~ <ELLIPSIS> priority => -104
ELLIPSIS ~ '...'
:lexeme ~ <RIGHT_ASSIGN> priority => -105
RIGHT_ASSIGN ~ '>>='
:lexeme ~ <LEFT_ASSIGN> priority => -106
LEFT_ASSIGN ~ '<<='
:lexeme ~ <ADD_ASSIGN> priority => -107
ADD_ASSIGN ~ '+='
:lexeme ~ <SUB_ASSIGN> priority => -108
SUB_ASSIGN ~ '-='
:lexeme ~ <MUL_ASSIGN> priority => -109
MUL_ASSIGN ~ '*='
:lexeme ~ <DIV_ASSIGN> priority => -110
DIV_ASSIGN ~ '/='
:lexeme ~ <MOD_ASSIGN> priority => -111
MOD_ASSIGN ~ '%='
:lexeme ~ <AND_ASSIGN> priority => -112
AND_ASSIGN ~ '&='
:lexeme ~ <XOR_ASSIGN> priority => -113
XOR_ASSIGN ~ '^='
:lexeme ~ <OR_ASSIGN> priority => -114
OR_ASSIGN ~ '|='
:lexeme ~ <RIGHT_OP> priority => -115
RIGHT_OP ~ '>>'
:lexeme ~ <LEFT_OP> priority => -116
LEFT_OP ~ '<<'
:lexeme ~ <INC_OP> priority => -117
INC_OP ~ '++'
:lexeme ~ <DEC_OP> priority => -118
DEC_OP ~ '--'
:lexeme ~ <PTR_OP> priority => -119
PTR_OP ~ '->'
:lexeme ~ <AND_OP> priority => -120
AND_OP ~ '&&'
:lexeme ~ <OR_OP> priority => -121
OR_OP ~ '||'
:lexeme ~ <LE_OP> priority => -122
LE_OP ~ '<='
:lexeme ~ <GE_OP> priority => -123
GE_OP ~ '>='
:lexeme ~ <EQ_OP> priority => -124
EQ_OP ~ '=='
:lexeme ~ <NE_OP> priority => -125
NE_OP ~ '!='
:lexeme ~ <SEMICOLON> priority => -126
SEMICOLON ~ ';'
#
# LCURLY factorization
#
_LCURLY ~ '{' | '<%'
:lexeme ~ <LCURLY> priority => -127
:lexeme ~ <LCURLY_SCOPE> priority => -127
:lexeme ~ <LCURLY_REENTERSCOPE> priority => -127
LCURLY ~ _LCURLY
LCURLY_SCOPE ~ _LCURLY
LCURLY_REENTERSCOPE ~ _LCURLY
#
# LCURLY factorization
#
_RCURLY ~ '}' | '%>'
:lexeme ~ <RCURLY> priority => -128
:lexeme ~ <RCURLY_SCOPE> priority => -128
RCURLY ~ _RCURLY
RCURLY_SCOPE ~ _RCURLY
:lexeme ~ <COMMA> priority => -129
COMMA ~ ','
:lexeme ~ <COLON> priority => -130
COLON ~ ':'
:lexeme ~ <EQUAL> priority => -131
EQUAL ~ '='
#
# LPAREN factorization
#
_LPAREN ~ '('
:lexeme ~ <LPAREN> priority => -132
:lexeme ~ <LPAREN_SCOPE> priority => -132
LPAREN ~ _LPAREN
LPAREN_SCOPE ~ _LPAREN
#
# RPAREN factorization
#
_RPAREN ~ ')'
:lexeme ~ <RPAREN> priority => -133
:lexeme ~ <RPAREN_SCOPE> priority => -133
RPAREN ~ _RPAREN
RPAREN_SCOPE ~ _RPAREN
:lexeme ~ <LBRACKET> priority => -134
LBRACKET ~ '[' | '<:'
:lexeme ~ <RBRACKET> priority => -135
RBRACKET ~ ']' | ':>'
:lexeme ~ <DOT> priority => -136
DOT ~ '.'
:lexeme ~ <AMPERSAND> priority => -137
AMPERSAND ~ '&'
:lexeme ~ <EXCLAMATION> priority => -138
EXCLAMATION ~ '!'
:lexeme ~ <TILDE> priority => -139
TILDE ~ '~'
:lexeme ~ <HYPHEN> priority => -140
HYPHEN ~ '-'
:lexeme ~ <PLUS> priority => -141
PLUS ~ '+'
:lexeme ~ <STAR> priority => -142
STAR ~ '*'
:lexeme ~ <SLASH> priority => -143
SLASH ~ '/'
:lexeme ~ <PERCENT> priority => -144
PERCENT ~ '%'
:lexeme ~ <LESS_THAN> priority => -145
LESS_THAN ~ '<'
:lexeme ~ <GREATER_THAN> priority => -146
GREATER_THAN ~ '>'
:lexeme ~ <CARET> priority => -147
CARET ~ '^'
:lexeme ~ <VERTICAL_BAR> priority => -148
VERTICAL_BAR ~ '|'
:lexeme ~ <QUESTION_MARK> priority => -149
QUESTION_MARK ~ '?'
############################################################################
# Discard of a C comment, c.f. https://gist.github.com/jeffreykegler/5015057
############################################################################
<C style comment> ~ '/*' <comment interior> '*/'
<comment interior> ~
<optional non stars>
<optional star prefixed segments>
<optional pre final stars>
<optional non stars> ~ [^*]*
<optional star prefixed segments> ~ <star prefixed segment>*
<star prefixed segment> ~ <stars> [^/*] <optional star free text>
<stars> ~ [*]+
<optional star free text> ~ [^*]*
<optional pre final stars> ~ [*]*
##########################
# Discard of a C++ comment
##########################
<Cplusplus style comment> ~ '//' <Cplusplus comment interior>
<Cplusplus comment interior> ~ [^\n]*
##############################################
# Discard of some simple annotation directives
##############################################
<MSVS annotation directive start> ~ '[source_annotation_attribute'
<MSVS annotation directive interior single line> ~ [^\n]*
<MSVS annotation directive> ~ <MSVS annotation directive start> <MSVS annotation directive interior single line>
#
# Internal tokens added
#
QUOTE ~ [']
I_CONSTANT_INSIDE ~ [^'\\\n]
I_CONSTANT_INSIDE ~ ES
I_CONSTANT_INSIDE_many ~ I_CONSTANT_INSIDE+
BS ~ '\'
ANYTHING_ELSE ~ [.]
:discard ~ <Cplusplus style comment>
:discard ~ <C style comment>
:discard ~ <MSVS annotation directive>
:discard ~ WS_many # whitespace separates tokens
:discard ~ ANYTHING_ELSE # discard bad characters
#
# ASM Stuff. We explicitely support the full GCC Inline Assembly.
# For any other case, you have to cross your fingers:
# Either:
# - the asm keyword is followed by '{'. In this case we eat
# all characters up to a matching '}'. Careful handling is
# done for strings, and comments, where comments are:
# * MSASM styles:
# ; anythingUpToEndOfLine
# COMMENT delimiter ... delimiter anythingUpToEndOfLine
# * C/C++ styles
# and where strings do not support escape character, as in MSASM, i.e.:
# * "..." without \" in it
# " '...' without \' in it
# In this case the ASM_OPAQUE lexeme is hooked
# to the full asm statement, i.e. { ... }
# - the asm keyword is not followed by '{'. Then:
# * it is followed by a '(': this is either a normal C statement
# or assumed to be a GCC-style inline assembly. We let the BNF
# take care of it
# * it is followed by a typeQualifier and again by a '(': same
# situation
# * else it is assumed to be a single ASM statement on the whole line.
# In this case the ASM_OPAQUE statement is also hooked and explicitely "lexeme_read"ed
# with a length corresponding to the full remaining characters,i.e.:
# [anything up to but not including newline]
#
#
# ASM HOOK
#
:lexeme ~ <GCC_ASM> priority => -60
:lexeme ~ <ANY_ASM> priority => -60
_ASM ~ 'asm__'
_ASM ~ '__asm'
_ASM ~ '__asm__'
_ASM ~ 'asm'
GCC_ASM ~ _ASM
ANY_ASM ~ _ASM
ASM_OPAQUE ~ [^\s\S]
#
# GCC C LEXEMES
#
:lexeme ~ <GCC_EXTENSION> priority => -60
GCC_EXTENSION ~ 'extension__'
GCC_EXTENSION ~ '__extension'
GCC_EXTENSION ~ '__extension__'
:lexeme ~ <GCC_BUILTIN_VA_START> priority => -60
GCC_BUILTIN_VA_START ~ '__builtin_va_start'
:lexeme ~ <GCC_BUILTIN_VA_END> priority => -60
GCC_BUILTIN_VA_END ~ '__builtin_va_end'
:lexeme ~ <GCC_BUILTIN_VA_ARG> priority => -60
GCC_BUILTIN_VA_ARG ~ '__builtin_va_arg'
:lexeme ~ <GCC_TYPEOF> priority => -60
GCC_TYPEOF ~ 'typeof'
GCC_TYPEOF ~ '__typeof'
GCC_TYPEOF ~ '__typeof__'
:lexeme ~ <GCC_BUILTIN_OFFSETOF> priority => -60
GCC_BUILTIN_OFFSETOF ~ '__builtin_offsetof'
:lexeme ~ <GCC_BUILTIN_VA_LIST> priority => -60
GCC_BUILTIN_VA_LIST ~ '__builtin_va_list'
GCC_ALIGNOF ~ '__alignof__'
GCC_ALIGNOF ~ 'alignof__'
GCC_ALIGNOF ~ '__alignof'
GCC_ALIGNOF ~ 'alignof'
#
# MSVS C LEXEMES
#
:lexeme ~ <MSVS_FASTCALL> priority => -60
MSVS_FASTCALL ~ '__fastcall'
:lexeme ~ <MSVS_THISCALL> priority => -60
MSVS_THISCALL ~ '__thiscall'
:lexeme ~ <MSVS_BASED> priority => -60
MSVS_BASED ~ '__based'
:lexeme ~ <MSVS_CDECL> priority => -60
MSVS_CDECL ~ '__cdecl'
:lexeme ~ <MSVS_CLRCALL> priority => -60
MSVS_CLRCALL ~ '__clrcall'
:lexeme ~ <MSVS_STDCALL> priority => -60
MSVS_STDCALL ~ '__stdcall'
:lexeme ~ <MSVS_INT8> priority => -60
MSVS_INT8 ~ '__int8'
:lexeme ~ <MSVS_INT16> priority => -60
MSVS_INT16 ~ '__int16'
:lexeme ~ <MSVS_INT32> priority => -60
MSVS_INT32 ~ '__int32'
:lexeme ~ <MSVS_INT64> priority => -60
MSVS_INT64 ~ '__int64'
:lexeme ~ <MSVS_W64> priority => -60
MSVS_W64 ~ '__w64'
:lexeme ~ <MSVS_PTR32> priority => -60
MSVS_PTR32 ~ '__ptr32'
:lexeme ~ <MSVS_PTR64> priority => -60
MSVS_PTR64 ~ '__ptr64'
:lexeme ~ <MSVS_UNALIGNED> priority => -60
MSVS_UNALIGNED ~ '__unaligned'
:lexeme ~ <MSVS_SPTR> priority => -60
MSVS_SPTR ~ '__sptr'
:lexeme ~ <MSVS_UPTR> priority => -60
MSVS_UPTR ~ '__uptr'
##########################################################
# GCC EXTENSIONS
#
# Copyright 2002-2009 ISP RAS (http://www.ispras.ru), UniTESK Lab (http://www.unitesk.com)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# @author <A href="mailto:demakov@ispras.ru">Alexey Demakov</A>
# @author <A href="mailto:hed@ispras.ru">Alexey Khoroshilov</A>
# @version $Id$
#
##########################################################
gccBuiltinType ::= gccTypeof
| GCC_BUILTIN_VA_LIST
gccAsmStatement ::= gccAsmExpression SEMICOLON
gccAsmExpression ::= GCC_ASM LPAREN expression RPAREN
| GCC_ASM LPAREN RPAREN
| GCC_ASM LPAREN expression gccAsmInnerOperandList RPAREN
| GCC_ASM typeQualifier LPAREN expression RPAREN
| GCC_ASM typeQualifier LPAREN expression gccAsmInnerOperandList RPAREN
| GCC_ASM GOTO LPAREN expression gccAsmInnerOperandList gccAsmInnerLabelList RPAREN
gccAsmClobberList ::= gccAsmClobber | gccAsmClobberList COMMA gccAsmClobber
gccAsmOperandList ::= gccAsmOperand | gccAsmOperandList COMMA gccAsmOperand
gccAsmInnerClobberList ::= COLON
| COLON gccAsmClobberList
gccAsmInnerOperandList2 ::= COLON
| COLON gccAsmInnerClobberList
| COLON gccAsmOperandList
| COLON gccAsmOperandList gccAsmInnerClobberList
gccAsmInnerOperandList ::= COLON
| COLON gccAsmInnerOperandList2
| COLON gccAsmOperandList
| COLON gccAsmOperandList gccAsmInnerOperandList2
gccAsmInnerLabelList ::= COLON
| COLON IDENTIFIER_UNAMBIGUOUS
| gccAsmInnerLabelList COMMA IDENTIFIER_UNAMBIGUOUS
gccAsmOperandPrefix ::= LBRACKET IDENTIFIER_UNAMBIGUOUS RBRACKET
gccAsmOperand ::= string LPAREN expression RPAREN
| gccAsmOperandPrefix string LPAREN expression RPAREN
gccAsmClobber ::= string
gccStatementExpression ::= LPAREN compoundStatement RPAREN
# @since 2.6.264
# for error handling: second assignmentExpression is always last parameter name
gccBuiltinVaStart ::= GCC_BUILTIN_VA_START
LPAREN
assignmentExpression
COMMA
assignmentExpression
RPAREN
# @since 2.6.264
gccBuiltinVaEnd ::= GCC_BUILTIN_VA_END
LPAREN
assignmentExpression
RPAREN
gccBuiltinVaArg ::= GCC_BUILTIN_VA_ARG
LPAREN
assignmentExpression
COMMA
typeName
RPAREN
gccTypeof ::= GCC_TYPEOF LPAREN typeName RPAREN
| GCC_TYPEOF LPAREN assignmentExpression RPAREN
gccBuiltinOffsetof ::= GCC_BUILTIN_OFFSETOF LPAREN typeName COMMA offsetofMemberDesignator RPAREN
offsetofMemberDesignator ::= IDENTIFIER_UNAMBIGUOUS
| offsetofMemberDesignator DOT IDENTIFIER_UNAMBIGUOUS
| offsetofMemberDesignator LBRACKET expression RBRACKET
######################
# Microsoft Extensions
######################
msvsAttribute ::= MSVS_FASTCALL | MSVS_BASED | MSVS_CDECL | MSVS_CLRCALL | MSVS_STDCALL | MSVS_THISCALL
msvsBuiltinType ::= MSVS_INT8
| MSVS_INT16
| MSVS_INT32
| MSVS_INT64
######################
# Opaque ASM Statement
######################
opaqueAsmStatement ::= ANY_ASM ASM_OPAQUE
###############################################################################################
# Discard simple preprocessor directives (on one line - cpp output persist to get some of them)
###############################################################################################
<Cpp style directive start> ~ '#'
<Cpp style directive interior single line> ~ [^\n]*
<Cpp style directive> ~ <Cpp style directive start> <Cpp style directive interior single line>
:discard ~ <Cpp style directive>
#####################
# G0 specific "tools"
#####################
<G0 identifier> ~ WS_any _IDENTIFIER WS_any
<_G0 number> ~ [\d]+
<G0 number> ~ WS_any <_G0 number> WS_any
<G0 string unit> ~ WS_any '"' STRING_LITERAL_INSIDE_any '"' WS_any
<G0 string> ~ <G0 string unit>+
<_G0 word> ~ [\w]+
<G0 word> ~ WS_any <_G0 word> WS_any
<G0 words> ~ <G0 word>+
#
# Same thing as <G0 string> but with <> instead of "
#
STRING_LITERAL_INSIDE2 ~ [^<>\\\n]
STRING_LITERAL_INSIDE2 ~ ES
STRING_LITERAL_INSIDE2_any ~ STRING_LITERAL_INSIDE2*
<G0 string unit 2> ~ WS_any '<' STRING_LITERAL_INSIDE2_any '>' WS_any
<G0 string 2> ~ <G0 string unit 2>
#
# G0 operators
#
<G0 mul assign> ~ WS_any '*=' WS_any
<G0 div assign> ~ WS_any '/=' WS_any
<G0 mod assign> ~ WS_any '%=' WS_any
<G0 add assign> ~ WS_any '+=' WS_any
<G0 sub assign> ~ WS_any '-=' WS_any
<G0 left assign> ~ WS_any '<<=' WS_any
<G0 right assign> ~ WS_any '>>=' WS_any
<G0 and assign> ~ WS_any '&=' WS_any
<G0 xor assign> ~ WS_any '^=' WS_any
<G0 or assign> ~ WS_any '|=' WS_any
<G0 or op> ~ WS_any '||' WS_any
<G0 and op> ~ WS_any '&&' WS_any
<G0 vertical bar> ~ WS_any '|' WS_any
<G0 caret> ~ WS_any '^' WS_any
<G0 ampersand> ~ WS_any '&' WS_any
<G0 eq op> ~ WS_any '==' WS_any
<G0 ne op> ~ WS_any '!=' WS_any
<G0 less than> ~ WS_any '<' WS_any
<G0 greater than> ~ WS_any '>' WS_any
<G0 le op> ~ WS_any '<=' WS_any
<G0 ge op> ~ WS_any '>=' WS_any
<G0 left op> ~ WS_any '<<' WS_any
<G0 right op> ~ WS_any '>>' WS_any
<G0 plus> ~ WS_any '+' WS_any
<G0 hyphen> ~ WS_any '-' WS_any
<G0 star> ~ WS_any '*' WS_any
<G0 slash> ~ WS_any '/' WS_any
<G0 percent> ~ WS_any '%' WS_any
<G0 lparen> ~ WS_any '(' WS_any
<G0 rparen> ~ WS_any ')' WS_any
<G0 lcurly> ~ WS_any '{' WS_any
<G0 rcurly> ~ WS_any '}' WS_any
<G0 lbracket> ~ WS_any '[' WS_any
<G0 rbracket> ~ WS_any ']' WS_any
<G0 inc op> ~ WS_any '++' WS_any
<G0 dec op> ~ WS_any '--' WS_any
<G0 ptr op> ~ WS_any '->' WS_any
<G0 dot> ~ WS_any '.' WS_any
<G0 exclamation> ~ WS_any '!' WS_any
<G0 tilde> ~ WS_any '~' WS_any
<G0 generic> ~ WS_any '_Generic' WS_any
<G0 default> ~ WS_any 'default' WS_any
<G0 ellipsis> ~ WS_any '...' WS_any
<G0 sizeof> ~ WS_any 'sizeof' WS_any
<G0 alignof> ~ WS_any '_Alignof' WS_any
| WS_any '__alignof__' WS_any
| WS_any 'alignof__' WS_any
| WS_any '__alignof' WS_any
| WS_any 'alignof' WS_any
#
# G0 "separators"
#
<G0 comma> ~ WS_any ',' WS_any
<G0 equal> ~ WS_any '=' WS_any
<G0 colon> ~ WS_any ':' WS_any
<G0 semicolon> ~ WS_any ';' WS_any
<G0 question mark> ~ WS_any '?' WS_any
#
# G0 "constants"
#
<G0 I_CONSTANT> ~ HP H_many IS_maybe
| BP B_many IS_maybe # Gcc extension: binary constants
| NZ D_any IS_maybe
| '0' O_any IS_maybe
| CP_maybe QUOTE I_CONSTANT_INSIDE_many QUOTE
<G0 F_CONSTANT> ~ D_many E FS_maybe
| D_any '.' D_many E_maybe FS_maybe
| D_many '.' E_maybe FS_maybe
| HP H_many P FS_maybe
| HP H_any '.' H_many P FS_maybe
| HP H_many '.' P FS_maybe
<G0 constant> ~ <G0 I_CONSTANT>
| <G0 F_CONSTANT>
| <G0 identifier>
#############################################################################################
# Discard MSVS __pragma stuff. It can happen in a lot of place, even in places not compatible
# with the C grammar
#############################################################################################
<MSVS pragma> ~ '__pragma' <G0 lparen> <MSVS pragma directive> <G0 rparen>
<MSVS pragma directive> ~ <MSVS pragma directive alloc_text>
| <MSVS pragma directive auto_inline>
| <MSVS pragma directive common seg>
| <MSVS pragma directive check_stack>
| <MSVS pragma directive comment>
| <MSVS pragma directive component>
| <MSVS pragma directive conform>
| <MSVS pragma directive deprecated>
| <MSVS pragma directive detect_mismatch>
| <MSVS pragma directive fenv_access>
| <MSVS pragma directive float_control>
| <MSVS pragma directive fp_contract>
| <MSVS pragma directive function>
| <MSVS pragma directive hdrstop>
| <MSVS pragma directive include_alias>
| <MSVS pragma directive inline_depth>
| <MSVS pragma directive inline_recursion>
| <MSVS pragma directive intrinsic>
| <MSVS pragma directive loop>
| <MSVS pragma directive make_public>
| <MSVS pragma directive managed>
| <MSVS pragma directive unmanaged>
| <MSVS pragma directive message>
# TODO - only the parallel if() is causing trouble
# | <MSVS pragma directive omp>
| <MSVS pragma directive once>
| <MSVS pragma directive optimize>
| <MSVS pragma directive pack>
| <MSVS pragma directive pointers_to_members>
| <MSVS pragma directive pop_macro>
| <MSVS pragma directive push_macro>
| <MSVS pragma directive region>
| <MSVS pragma directive endregion>
| <MSVS pragma directive runtime_checks>
| <MSVS pragma directive section>
| <MSVS pragma directive setlocale>
| <MSVS pragma directive strict_gs_check>
| <MSVS pragma directive vtordisp>
| <MSVS pragma directive warning>
# alloc_text( "textsection", function1, ... )
<MSVS pragma directive alloc_text> ~ 'alloc_text' <G0 lparen> <MSVS pragma directive alloc_text interior> <G0 rparen>
<MSVS pragma directive alloc_text interior> ~ <G0 string>
| <MSVS pragma directive alloc_text interior> <G0 comma> <MSVS pragma directive alloc_text identifier list>
<MSVS pragma directive alloc_text identifier list> ~ <G0 identifier>
| <MSVS pragma directive alloc_text identifier list> <G0 comma> <G0 identifier>
# auto_inline( [{on | off}] )
<MSVS pragma directive auto_inline> ~ 'auto_inline' <G0 lparen> <G0 rparen>
| 'auto_inline' <G0 lparen> <MSVS pragma directive auto_inline interior> <G0 rparen>
<MSVS pragma directive auto_inline interior> ~ 'on' | 'off'
# warning( warning-specifier : warning-number-list [; warning-specifier : warning-number-list...] )
# warning( push[ ,n ] )
# warning( pop )
<MSVS pragma directive warning> ~ 'warning' <G0 lparen> <MSVS pragma directive warning interior> <G0 rparen>
<MSVS pragma directive warning interior> ~ <MSVS pragma directive warning interior specifier list>
| <MSVS pragma directive warning interior push>
| <MSVS pragma directive warning interior pop>
<MSVS pragma directive warning interior specifier list> ~ <MSVS pragma directive warning interior specifier>
| <MSVS pragma directive warning interior specifier list> <G0 semicolon> <MSVS pragma directive warning interior specifier>
<MSVS pragma directive warning interior specifier keyword> ~ '1' | '2' | '3' | '4'
| 'default'
| 'disable'
| 'error'
| 'once'
| 'suppress'
<MSVS pragma directive warning interior specifier> ~ <MSVS pragma directive warning interior specifier keyword> <G0 colon> <MSVS pragma directive warning interior specifier number list>
<MSVS pragma directive warning interior specifier number list> ~ <G0 number>
| <MSVS pragma directive warning interior specifier number list> WS_many <G0 number>
<MSVS pragma directive warning interior push> ~ 'push'
| 'push' <G0 comma> <G0 number>
<MSVS pragma directive warning interior pop> ~ 'pop'
# [bss|code]_seg( [ [ { push | pop }, ] [ identifier, ] ] [ "segment-name" [, "segment-class" ] )
<MSVS pragma directive common seg push or pop> ~ 'push' | 'pop'
<MSVS pragma directive common seg interior 1> ~ <MSVS pragma directive common seg push or pop>
| <MSVS pragma directive common seg push or pop> <G0 comma> <G0 identifier>
| <G0 identifier>
<MSVS pragma directive common seg interior 2> ~ <G0 string>
| <G0 string> <G0 comma> <G0 string>
<MSVS pragma directive common seg interior> ~ <MSVS pragma directive common seg interior 1>
| <MSVS pragma directive common seg interior 2>
| <MSVS pragma directive common seg interior 1> <G0 comma> <MSVS pragma directive common seg interior 2>
<MSVS pragma directive common seg> ~ <MSVS pragma directive common seg keyword> <G0 lparen> <G0 rparen>
| <MSVS pragma directive common seg keyword> <G0 lparen> <MSVS pragma directive common seg interior> <G0 rparen>
<MSVS pragma directive common seg keyword> ~ 'bss_seg' | 'code_seg' | 'const_seg' | 'data_seg'
# check_stack([ {on | off}] )
# check_stack{+|-}
<MSVS pragma directive check_stack interior> ~ 'on' | 'off' | '+' | '-'
<MSVS pragma directive check_stack> ~ 'check_stack' <G0 lparen> <G0 rparen>
| 'check_stack' <G0 lparen> <MSVS pragma directive check_stack interior> <G0 rparen>
# comment( comment-type [,"commentstring"] )
<MSVS pragma directive comment interior type> ~ 'compiler' | 'exestr' | 'lib' | 'linker' | 'user'
<MSVS pragma directive comment interior> ~ <MSVS pragma directive comment interior type>
| <MSVS pragma directive comment interior type> <G0 comma> <G0 string>
<MSVS pragma directive comment> ~ 'comment' <G0 lparen> <MSVS pragma directive comment interior> <G0 rparen>
# component( browser, { on | off }[, references [, name ]] )
# component( minrebuild, on | off )
# component( mintypeinfo, on | off )
# Note: we use <G0 identifier> for name, which is ok, since it refers a storage type, that matches <G0 identifier>
<MSVS pragma directive component interior name> ~ <G0 identifier>
| <G0 string>
<MSVS pragma directive component interior browser on off> ~ 'on' | 'off'
<MSVS pragma directive component interior browser> ~ 'browser' <G0 comma> <MSVS pragma directive component interior browser on off>
| 'browser' <G0 comma> <MSVS pragma directive component interior browser on off> <G0 comma> 'references'
| 'browser' <G0 comma> <MSVS pragma directive component interior browser on off> <G0 comma> 'references' <G0 comma> <MSVS pragma directive component interior name>
<MSVS pragma directive component interior minrebuild> ~ 'minrebuild' <G0 comma> <MSVS pragma directive component interior browser on off>
<MSVS pragma directive component interior mintypeinfo> ~ 'mintypeinfo' <G0 comma> <MSVS pragma directive component interior browser on off>
<MSVS pragma directive component interior> ~ <MSVS pragma directive component interior browser>
| <MSVS pragma directive component interior minrebuild>
| <MSVS pragma directive component interior mintypeinfo>
<MSVS pragma directive component> ~ 'component' <G0 lparen> <MSVS pragma directive component interior> <G0 rparen>
# conform(name [, show ] [, on | off ] [ [, push | pop ] [, identifier ] ] )
# Note: the examples do not conform to this specification, i.e.:
# conform(forScope, push, x, on)
# Therefore we consider that the components show, on/off, push/pop and identifier could appear in any order (and in fact as many times as needed)
<MSVS pragma directive conform interior name> ~ 'forScope'
<MSVS pragma directive conform interior show> ~ 'show'
<MSVS pragma directive conform interior on off> ~ 'on' | 'off'
<MSVS pragma directive conform interior push pop> ~ 'push' | 'pop'
<MSVS pragma directive conform interior> ~ <MSVS pragma directive conform interior name>
| <MSVS pragma directive conform interior name> <G0 comma> <MSVS pragma directive conform interior optional>
<MSVS pragma directive conform interior optional unit> ~ <MSVS pragma directive conform interior show>
| <MSVS pragma directive conform interior on off>
| <MSVS pragma directive conform interior push pop>
| <G0 identifier>
<MSVS pragma directive conform interior optional> ~ <MSVS pragma directive conform interior optional unit>
| <MSVS pragma directive conform interior optional> <G0 comma> <MSVS pragma directive conform interior optional unit>
<MSVS pragma directive conform> ~ 'conform' <G0 lparen> <MSVS pragma directive conform interior> <G0 rparen>
# deprecated( identifier1 [,identifier2, ...] )
<MSVS pragma directive deprecated interior> ~ <G0 identifier>
| <MSVS pragma directive deprecated interior> <G0 comma> <G0 identifier>
<MSVS pragma directive deprecated> ~ 'deprecated' <G0 lparen> <MSVS pragma directive deprecated interior> <G0 rparen>
# detect_mismatch( "name", "value")
<MSVS pragma directive detect_mismatch interior> ~ <G0 string> <G0 comma> <G0 string>
<MSVS pragma directive detect_mismatch> ~ 'detect_mismatch' <G0 lparen> <MSVS pragma directive detect_mismatch interior> <G0 rparen>
# fenv_access [ON | OFF]
# Are the parenthesis necessary ? don't know - assume not
# on or ON, off or OFF ? Assume all.
<MSVS pragma directive fenv_access interior> ~ 'on' | 'ON' | 'off' | 'OFF'
<MSVS pragma directive fenv_access> ~ 'fenv_access'
| 'fenv_access' <G0 lparen> <G0 rparen>
| 'fenv_access' <G0 lparen> <MSVS pragma directive fenv_access interior> <G0 rparen>
# float_control( value,setting [push] | push | pop )
<MSVS pragma directive float_control interior value> ~ 'precise' | 'except'
<MSVS pragma directive float_control interior setting> ~ 'on' | 'off'
<MSVS pragma directive float_control interior> ~ <MSVS pragma directive float_control interior value> <G0 comma> <MSVS pragma directive float_control interior setting>
| <MSVS pragma directive float_control interior value> <G0 comma> <MSVS pragma directive float_control interior setting> WS_any 'push'
| 'push'
| 'pop'
<MSVS pragma directive float_control> ~ 'float_control' <G0 lparen> <MSVS pragma directive float_control interior> <G0 rparen>
# fp_contract [ON | OFF]
# Are the parenthesis necessary ? don't know - assume not
# on or ON, off or OFF ? Assume all.
<MSVS pragma directive fp_contract interior> ~ 'on' | 'ON' | 'off' | 'OFF'
<MSVS pragma directive fp_contract> ~ 'fp_contract'
| 'fp_contract' <G0 lparen> <G0 rparen>
| 'fp_contract' <G0 lparen> <MSVS pragma directive fp_contract interior> <G0 rparen>
# function( function1 [,function2, ...] )
<MSVS pragma directive function interior> ~ <G0 identifier>
| <MSVS pragma directive function interior> <G0 comma> <G0 identifier>
<MSVS pragma directive function> ~ 'function' <G0 lparen> <MSVS pragma directive function interior> <G0 rparen>
# hdrstop [( "filename" )]
<MSVS pragma directive hdrstop interior> ~ <G0 string>
<MSVS pragma directive hdrstop> ~ 'hdrstop'
| 'hdrstop' <G0 lparen> <MSVS pragma directive hdrstop interior> <G0 rparen>
# include_alias( "long_filename", "short_filename" )
# include_alias( <long_filename>, <short_filename> )
<MSVS pragma directive include_alias interior> ~ <G0 string> <G0 comma> <G0 string>
| <G0 string 2> <G0 comma> <G0 string 2>
<MSVS pragma directive include_alias> ~ 'include_alias' <G0 lparen> <MSVS pragma directive include_alias interior> <G0 rparen>
# inline_depth( [n] )
<MSVS pragma directive inline_depth interior> ~ <G0 number>
<MSVS pragma directive inline_depth> ~ 'inline_depth' <G0 lparen> <G0 rparen>
| 'inline_depth' <G0 lparen> <MSVS pragma directive inline_depth interior> <G0 rparen>
# inline_recursion( [{on | off}] )
<MSVS pragma directive inline_recursion interior> ~ 'on' | 'off'
<MSVS pragma directive inline_recursion> ~ 'inline_recursion' <G0 lparen> <G0 rparen>
| 'inline_recursion' <G0 lparen> <MSVS pragma directive inline_recursion interior> <G0 rparen>
# intrinsic( function1 [,function2, ...] )
<MSVS pragma directive intrinsic interior> ~ <G0 identifier>
| <MSVS pragma directive intrinsic interior> <G0 comma> <G0 identifier>
<MSVS pragma directive intrinsic> ~ 'intrinsic' <G0 lparen> <MSVS pragma directive intrinsic interior> <G0 rparen>
# loop( hint_parallel(n) )
# loop( no_vector )
# loop( ivdep )
<MSVS pragma directive loop interior> ~ 'hint_parallel' <G0 lparen> <G0 number> <G0 rparen>
| 'no_vector'
| 'ivdep'
<MSVS pragma directive loop> ~ 'loop' <G0 lparen> <MSVS pragma directive loop interior> <G0 rparen>
# make_public(type)
<MSVS pragma directive make_public interior> ~ <G0 identifier>
<MSVS pragma directive make_public> ~ 'make_public' <G0 lparen> <MSVS pragma directive make_public interior> <G0 rparen>
# managed
# managed([push,] on | off)
# managed(pop)
<MSVS pragma directive managed interior on off> ~ 'on' | 'off'
<MSVS pragma directive managed interior> ~ 'push' <G0 comma> <MSVS pragma directive managed interior on off>
| <MSVS pragma directive managed interior on off>
| 'pop'
<MSVS pragma directive managed> ~ 'managed'
| 'managed' <G0 lparen> <G0 rparen>
| 'managed' <G0 lparen> <MSVS pragma directive managed interior> <G0 rparen>
# unmanaged
<MSVS pragma directive unmanaged> ~ 'unmanaged'
| 'unmanaged' <G0 lparen> <G0 rparen>
# message( messagestring )
<MSVS pragma directive message interior> ~ <G0 string>
<MSVS pragma directive message> ~ 'message' <G0 lparen> <MSVS pragma directive message interior> <G0 rparen>
# once
<MSVS pragma directive once> ~ 'once'
| 'once' <G0 lparen> <G0 rparen>
# optimize( "[optimization-list]", {on | off} )
# Note: "[optimization-list]" should contains only specified characters. We do not mind and say this is a string.
<MSVS pragma directive optimize interior optimizationList> ~ <G0 string>
<MSVS pragma directive optimize interior on off> ~ 'on' | 'off'
<MSVS pragma directive optimize interior> ~ <MSVS pragma directive optimize interior optimizationList> <G0 comma> <MSVS pragma directive optimize interior on off>
<MSVS pragma directive optimize> ~ 'optimize' <G0 lparen> <MSVS pragma directive optimize interior> <G0 rparen>
# pack( [ show ] | [ push | pop ] [, identifier ] , n )
<MSVS pragma directive pack interior show> ~ 'show'
<MSVS pragma directive pack interior 1> ~ <MSVS pragma directive pack interior show>
<MSVS pragma directive pack interior push pop> ~ 'push' | 'pop'
<MSVS pragma directive pack interior 21> ~ <MSVS pragma directive pack interior push pop>
| <G0 identifier>
| <MSVS pragma directive pack interior push pop> <G0 comma> <G0 identifier>
<MSVS pragma directive pack interior 2> ~ <G0 number>
| <MSVS pragma directive pack interior 21> <G0 comma> <G0 number>
<MSVS pragma directive pack interior> ~ <MSVS pragma directive pack interior 1>
| <MSVS pragma directive pack interior 2>
<MSVS pragma directive pack> ~ 'pack' <G0 lparen> <G0 rparen>
| 'pack' <G0 lparen> <MSVS pragma directive pack interior> <G0 rparen>
# pointers_to_members( pointer-declaration, [most-general-representation] )
<MSVS pragma directive pointers_to_members interior pointer declaration> ~ 'full_generality' | 'best_case'
<MSVS pragma directive pointers_to_members interior most general representation> ~ 'single_inheritance' | 'multiple_inheritance' | 'virtual_inheritance'
<MSVS pragma directive pointers_to_members interior> ~ <MSVS pragma directive pointers_to_members interior pointer declaration>
| <MSVS pragma directive pointers_to_members interior pointer declaration> <G0 comma> <MSVS pragma directive pointers_to_members interior most general representation>
<MSVS pragma directive pointers_to_members> ~ 'pointers_to_members' <G0 lparen> <MSVS pragma directive pointers_to_members interior> <G0 rparen>
# pop_macro("macro_name")
<MSVS pragma directive pop_macro> ~ 'pop_macro' <G0 lparen> <G0 string> <G0 rparen>
# push_macro("macro_name")
<MSVS pragma directive push_macro> ~ 'push_macro' <G0 lparen> <G0 string> <G0 rparen>
# region [name]
<MSVS pragma directive region interior> ~ <G0 identifier>
<MSVS pragma directive region> ~ 'region'
| 'region' <G0 lparen> <G0 rparen>
| 'region' <G0 lparen> <MSVS pragma directive region interior> <G0 rparen>
# endregion [name]
<MSVS pragma directive endregion interior> ~ <G0 identifier>
<MSVS pragma directive endregion> ~ 'endregion'
| 'endregion' <G0 lparen> <G0 rparen>
| 'endregion' <G0 lparen> <MSVS pragma directive endregion interior> <G0 rparen>
# optimize( "[runtime_checks]", {restore | off} )
# Note: "[runtime_checks]" should contains only specified characters. We do not mind and say this is a string.
<MSVS pragma directive runtime_checks interior optimizationList> ~ <G0 string>
<MSVS pragma directive runtime_checks interior on off> ~ 'restore' | 'off'
<MSVS pragma directive runtime_checks interior> ~ <MSVS pragma directive runtime_checks interior optimizationList> <G0 comma> <MSVS pragma directive runtime_checks interior on off>
<MSVS pragma directive runtime_checks> ~ 'runtime_checks' <G0 lparen> <MSVS pragma directive runtime_checks interior> <G0 rparen>
# section( "section-name" [, attributes] )
<MSVS pragma directive section interior attribute> ~ 'read' | 'write' | 'execute' | 'shared' | 'nopage' | 'nocache' | 'discard' | 'remove'
<MSVS pragma directive section interior attribute list> ~ <MSVS pragma directive section interior attribute>
| <MSVS pragma directive section interior attribute list> <G0 comma> <MSVS pragma directive section interior attribute>
<MSVS pragma directive section interior> ~ <G0 string>
| <G0 string> <G0 comma> <MSVS pragma directive section interior attribute list>
<MSVS pragma directive section> ~ 'section' <G0 lparen> <MSVS pragma directive section interior> <G0 rparen>
# setlocale( "[locale-string]" )
<MSVS pragma directive setlocale interior> ~ <G0 string>
<MSVS pragma directive setlocale> ~ 'setlocale' <G0 lparen> <MSVS pragma directive setlocale interior> <G0 rparen>
# strict_gs_check([push,] on )
# strict_gs_check([push,] off )
# strict_gs_check(pop)
<MSVS pragma directive strict_gs_check interior on off> ~ 'on' | 'off'
<MSVS pragma directive strict_gs_check interior> ~ <MSVS pragma directive strict_gs_check interior on off>
| 'push' <G0 comma> <MSVS pragma directive strict_gs_check interior on off>
| 'pop'
<MSVS pragma directive strict_gs_check> ~ 'strict_gs_check' <G0 lparen> <MSVS pragma directive strict_gs_check interior> <G0 rparen>
# vtordisp([push,] n)
# vtordisp(pop)
# vtordisp()
# vtordisp([push,] {on | off})
<MSVS pragma directive vtordisp interior on off number> ~ 'on' | 'off' | <G0 number>
<MSVS pragma directive vtordisp interior> ~ <MSVS pragma directive vtordisp interior on off number>
| 'push' <G0 comma> <MSVS pragma directive vtordisp interior on off number>
| 'pop'
<MSVS pragma directive vtordisp> ~ 'vtordisp'
| 'vtordisp' <G0 lparen> <G0 rparen>
| 'vtordisp' <G0 lparen> <MSVS pragma directive vtordisp interior> <G0 rparen>
:discard ~ <MSVS pragma>
###############################
# Discard MSVS __declspec stuff
###############################
<MSVS declspec> ~ '__declspec' <G0 lparen> <MSVS declspec directive> <G0 rparen>
<MSVS declspec directive> ~ <MSVS declspec align>
| <MSVS declspec allocate>
| <MSVS declspec appdomain>
| <MSVS declspec deprecated>
| <MSVS declspec dllexport>
| <MSVS declspec dllimport>
| <MSVS declspec jitintrinsic>
| <MSVS declspec naked>
| <MSVS declspec noalias>
| <MSVS declspec noinline>
| <MSVS declspec noreturn>
| <MSVS declspec nothrow>
| <MSVS declspec novtable>
| <MSVS declspec process>
| <MSVS declspec property>
| <MSVS declspec restrict>
| <MSVS declspec safebuffers>
| <MSVS declspec selectany>
| <MSVS declspec thread>
| <MSVS declspec uuid>
# align(#)
<MSVS declspec align> ~ 'align' <G0 lparen> <G0 number> <G0 rparen>
# allocate("segname")
<MSVS declspec allocate> ~ 'allocate' <G0 lparen> <G0 string> <G0 rparen>
# appdomain
<MSVS declspec appdomain> ~ 'appdomain'
# deprecated
# deprecated()
# deprecated("text")
<MSVS declspec deprecated> ~ 'deprecated'
| 'deprecated' <G0 lparen> <G0 rparen>
| 'deprecated' <G0 lparen> <G0 string> <G0 rparen>
# dllexport
<MSVS declspec dllexport> ~ 'dllexport'
# dllimport
<MSVS declspec dllimport> ~ 'dllimport'
# jitintrinsic
<MSVS declspec jitintrinsic> ~ 'jitintrinsic'
# naked
<MSVS declspec naked> ~ 'naked'
# noalias
<MSVS declspec noalias> ~ 'noalias'
# noinline
<MSVS declspec noinline> ~ 'noinline'
# noreturn
<MSVS declspec noreturn> ~ 'noreturn'
# nothrow
<MSVS declspec nothrow> ~ 'nothrow'
# novtable
<MSVS declspec novtable> ~ 'novtable'
# process
<MSVS declspec process> ~ 'process'
# property([get|put]=function)
<MSVS declspec property interior get put> ~ 'get' | 'put'
<MSVS declspec property interior> ~ <MSVS declspec property interior get put> <G0 equal> <G0 identifier>
<MSVS declspec property interior list> ~ <MSVS declspec property interior>
| <MSVS declspec property interior list> <G0 comma> <MSVS declspec property interior>
<MSVS declspec property> ~ 'property' <G0 lparen> <MSVS declspec property interior list> <G0 rparen>
# restrict
<MSVS declspec restrict> ~ 'restrict'
# safebuffers
<MSVS declspec safebuffers> ~ 'safebuffers'
# selectany
<MSVS declspec selectany> ~ 'selectany'
# thread
<MSVS declspec thread> ~ 'thread'
# uuid("ComObjectGUID")
<MSVS declspec uuid> ~ 'uuid' <G0 lparen> <G0 string> <G0 rparen>
:discard ~ <MSVS declspec>
#################################
# Discard GCC __attribute__ stuff
#################################
<GCC attribute keyword> ~ '__attribute__'
| '__attribute'
<GCC attribute> ~ <GCC attribute keyword> <G0 lparen> <G0 lparen> <G0 rparen> <G0 rparen>
| <GCC attribute keyword> <G0 lparen> <G0 lparen> <GCC attribute list> <G0 rparen> <G0 rparen>
<GCC attribute list> ~ <GCC attribute unit>
| <GCC attribute list> <G0 comma> <GCC attribute unit>
<GCC attribute unit> ~ <G0 word>
| <G0 word> <G0 lparen> <G0 rparen>
| <G0 word> <G0 lparen> <GCC attribute parameters> <G0 rparen>
<GCC attribute parameters> ~ <G0 identifier>
| <G0 identifier> <G0 comma> <GCC attribute parameters expressions>
| <GCC attribute parameters expressions>
<GCC attribute parameters expressions> ~ <GCC attribute parameters expression>
| <GCC attribute parameters expressions> <G0 comma> <GCC attribute parameters expression>
#
# Here comes the difficuly. This should be an expression.
# Since this is for :discard, we provide a G0 version of it.
# This is a brutal version:
# - typeName is replaced by <G0 words>
# - GCC extensions are ignored
#
<GCC attribute parameters expression> ~ <G0 expression>
<G0 expression> ~ <G0 assignmentExpression>
| <G0 expression> <G0 comma> <G0 assignmentExpression>
<G0 assignmentExpression> ~ <G0 conditionalExpression>
| <G0 unaryExpression> <G0 assignmentOperator> <G0 assignmentExpression>
<G0 assignmentOperator> ~ <G0 equal>
| <G0 mul assign>
| <G0 div assign>
| <G0 mod assign>
| <G0 add assign>
| <G0 sub assign>
| <G0 left assign>
| <G0 right assign>
| <G0 and assign>
| <G0 xor assign>
| <G0 or assign>
<G0 conditionalExpression> ~ <G0 logicalOrExpression>
| <G0 logicalOrExpression> <G0 question mark> <G0 expression> <G0 colon> <G0 conditionalExpression>
| <G0 logicalOrExpression> <G0 question mark> <G0 colon> <G0 conditionalExpression> # GCC Extension
<G0 logicalOrExpression> ~ <G0 logicalAndExpression>
| <G0 logicalOrExpression> <G0 or op> <G0 logicalAndExpression>
<G0 logicalAndExpression> ~ <G0 inclusiveOrExpression>
| <G0 logicalAndExpression> <G0 and op> <G0 inclusiveOrExpression>
<G0 inclusiveOrExpression> ~ <G0 exclusiveOrExpression>
| <G0 inclusiveOrExpression> <G0 vertical bar> <G0 exclusiveOrExpression>
<G0 exclusiveOrExpression> ~ <G0 andExpression>
| <G0 exclusiveOrExpression> <G0 caret> <G0 andExpression>
<G0 andExpression> ~ <G0 equalityExpression>
| <G0 andExpression> <G0 ampersand> <G0 equalityExpression>
<G0 equalityExpression> ~ <G0 relationalExpression>
| <G0 equalityExpression> <G0 eq op> <G0 relationalExpression>
| <G0 equalityExpression> <G0 ne op> <G0 relationalExpression>
<G0 relationalExpression> ~ <G0 shiftExpression>
| <G0 relationalExpression> <G0 less than> <G0 shiftExpression>
| <G0 relationalExpression> <G0 greater than> <G0 shiftExpression>
| <G0 relationalExpression> <G0 le op> <G0 shiftExpression>
| <G0 relationalExpression> <G0 ge op> <G0 shiftExpression>
<G0 shiftExpression> ~ <G0 additiveExpression>
| <G0 shiftExpression> <G0 left op> <G0 additiveExpression>
| <G0 shiftExpression> <G0 right op> <G0 additiveExpression>
<G0 additiveExpression> ~ <G0 multiplicativeExpression>
| <G0 additiveExpression> <G0 plus> <G0 multiplicativeExpression>
| <G0 additiveExpression> <G0 hyphen> <G0 multiplicativeExpression>
<G0 multiplicativeExpression> ~ <G0 castExpression>
| <G0 multiplicativeExpression> <G0 star> <G0 castExpression>
| <G0 multiplicativeExpression> <G0 slash> <G0 castExpression>
| <G0 multiplicativeExpression> <G0 percent> <G0 castExpression>
<G0 castExpression> ~ <G0 unaryExpression>
| <G0 lparen> <G0 words> <G0 rparen> <G0 castExpression>
<G0 unaryOperator> ~ <G0 ampersand>
| <G0 star>
| <G0 plus>
| <G0 hyphen>
| <G0 tilde>
| <G0 exclamation>
<G0 unaryExpression> ~ <G0 postfixExpression>
| <G0 inc op> <G0 unaryExpression>
| <G0 dec op> <G0 unaryExpression>
| <G0 unaryOperator> <G0 castExpression>
| <G0 sizeof> <G0 unaryExpression>
| <G0 sizeof> <G0 lparen> <G0 words> <G0 rparen>
| <G0 alignof> <G0 lparen> <G0 words> <G0 rparen>
<G0 postfixExpression> ~ <G0 primaryExpression>
| <G0 postfixExpression> <G0 lbracket> <G0 expression> <G0 rbracket>
| <G0 postfixExpression> <G0 lparen> <G0 rparen>
| <G0 postfixExpression> <G0 lparen> <G0 argumentExpressionList> <G0 rparen>
| <G0 postfixExpression> <G0 dot> <G0 identifier>
| <G0 postfixExpression> <G0 ptr op> <G0 identifier>
| <G0 postfixExpression> <G0 inc op>
| <G0 postfixExpression> <G0 dec op>
| <G0 lparen> <G0 words> <G0 rparen> <G0 lcurly> <G0 initializerList> <G0 rcurly>
| <G0 lparen> <G0 words> <G0 rparen> <G0 lcurly> <G0 initializerList> <G0 comma> <G0 rcurly>
<G0 primaryExpression> ~ <G0 identifier>
| <G0 constant>
| <G0 string>
| <G0 lparen> <G0 expression> <G0 rparen>
| <G0 genericSelection>
<G0 argumentExpressionList> ~ <G0 assignmentExpression>
| <G0 argumentExpressionList> <G0 comma> <G0 assignmentExpression>
| <G0 argumentExpressionList> <G0 comma>
<G0 genericSelection> ~ <G0 generic> <G0 lparen> <G0 assignmentExpression> <G0 comma> <G0 genericAssocList> <G0 rparen>
<G0 genericAssocList> ~ <G0 genericAssociation>
| <G0 genericAssocList> <G0 comma> <G0 genericAssociation>
<G0 genericAssociation> ~ <G0 words> <G0 colon> <G0 assignmentExpression>
| <G0 default> <G0 colon> <G0 assignmentExpression>
<G0 initializerList> ~ <G0 designation> <G0 initializer>
| <G0 initializer>
| <G0 identifier> <G0 colon> <G0 initializer>
| <G0 initializerList> <G0 comma> <G0 designation> <G0 initializer>
| <G0 initializerList> <G0 comma> <G0 initializer>
<G0 initializer> ~ <G0 lcurly> <G0 initializerList> <G0 rcurly>
| <G0 lcurly> <G0 initializerList> <G0 comma> <G0 rcurly>
| <G0 assignmentExpression>
<G0 designation> ~ <G0 designatorList> <G0 equal>
<G0 designatorList> ~ <G0 designator>+
<G0 designator> ~ <G0 lbracket> <G0 constantExpression> <G0 rbracket>
| <G0 dot> <G0 identifier>
| <G0 lbracket> <G0 constantExpression> <G0 ellipsis> <G0 constantExpression> <G0 rbracket> # GCC Extension
<G0 constantExpression> ~ <G0 conditionalExpression> # with constraints
:discard ~ <GCC attribute>