grammar C99::Grammar is PCT::Grammar;
## A.2.4 External definitions ##
token TOP { ^ <external_declaration>+ [ $ || <.panic: Syntax error> ] {*} }
rule external_declaration { | <declaration> {*} #= declaration | <function_definition> {*} #= function_definition }
rule function_definition { <declaration_specifiers> <declarator> <declaration>* <compound_statement> {*} }
## A.2.2 ##
rule declaration { <declaration_specifiers> [ <init_declarator> [',' <init_declarator>]* ]? ';' {*} }
rule declaration_specifiers { [ <type_specifier> | <storage_class_specifier> | <type_qualifier> | <function_specifier> ]+ }
rule function_specifier { 'inline' }
rule init_declarator { <declarator> ['=' <initializer>]? {*} }
rule storage_class_specifier { | 'typedef' | 'extern' | 'static' | 'auto' | 'register' }
rule type_specifier { | <builtin_type> | <struct_or_union_specifier> | <enum_specifier> | <typedef_name> }
token builtin_type { | 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | '_Bool' | '_Complex' | '_Imaginary' }
rule struct_or_union_specifier { $<type>=['struct'|'union'] [ | <struct_or_union_definition> | <pre_declaration> ] }
rule struct_or_union_definition { <identifier>? '{' <struct_declaration>+ '}' }
rule pre_declaration { <identifier> }
rule struct_declaration { <specifier_qualifier_list> <struct_declarator_list>* ';' }
rule specifier_qualifier_list { [ | <type_specifier> | <type_qualifier> ]+ }
rule struct_declarator_list { <struct_declarator> [',' <struct_declarator>]* }
rule struct_declarator { | <declarator>? ':' <constant_expression> | <declarator> }
rule enum_specifier { | 'enum' <identifier>? '{' <enumerator_list> [',']? '}' | 'enum' <identifier> }
rule enumerator_list { <enumerator> [',' <enumerator>]* }
rule enumerator { <enumeration_constant> ['=' <constant_expression>]? }
rule type_qualifier { $<qualifier>=['const'|'restrict'|'volatile'] }
rule declarator { <pointer>? <direct_declarator> {*} }
rule direct_declarator { <declarator_prefix> <declarator_suffix>* {*} }
rule declarator_prefix { | '(' <declarator> ')' {*} #= declarator | <identifier> {*} #= identifier }
rule declarator_suffix { | '(' <parameter_type_list> ')' {*} #= parameter_type_list ## old-style C parameter declarations | '(' <identifier_list>? ')' {*} #= identifier_list | '[' <assignment_expression>? ']' | '[' '*' ']' }
rule pointer { '*' <type_qualifier>* ['*']? }
rule parameter_type_list { <parameter_list> [$<vararg>=[',' '...']]? {*} }
rule parameter_list { <parameter_declaration> [',' <parameter_declaration>]* {*} }
rule parameter_declaration { <declaration_specifiers> [ | <declarator> {*} #= declarator | <abstract_declarator>? {*} #= abstract_declarator ] }
rule identifier_list { <identifier> [',' <identifier>]* }
rule type_name { <specifier_qualifier_list> <abstract_declarator>? }
rule abstract_declarator { | '*' | ['*']? <direct_abstract_declarator> }
rule direct_abstract_declarator { [ | '(' <abstract_declatator> ')' | '[' <assignment_expression>? ']' | '(' <parameter_type_list> ')' ] <direct_abstract_declarator_1>* }
rule direct_abstract_declarator_1 { | '[' <assignment_expression>? ']' | '[' '*' ']' | '(' <parameter_type_list> ')' }
rule typedef_name {
## a typedef name can be a return type specifier. This is ambiguous, because ## the parser doesn't know if it's a return type thingie or the name of the ## function. Therefore, typedef'd names must be stored in a %hash, so that ## this rule is not calling <identifier>, but inspecting the registered ## typedef'd names. For now, specify 'SOME_TYPEDEF_NAME' as the only typedef'd name. ## #<identifier> 'SOME_TYPEDEF_NAME' }
rule initializer { | <assignment_expression> | '{' <initializer_list> [',']? '}' }
rule initializer_list { <initializer_item> [',' <initializer_item>]* }
rule initializer_item { <designation>? <initializer> }
rule designation { <designator>+ '=' }
rule designator { | '[' <constant_expression> ']' | '.' <identifier> }
## A.2.3 Statements ##
rule statement { | <labeled_statement> | <compound_statement> {*} #= compound_statement | <expression_statement> {*} #= expression_statement | <if_statement> {*} #= if_statement | <switch_statement> | <while_statement> {*} #= while_statement | <do_while_statement> {*} #= do_while_statement | <for1_statement> {*} #= for1_statement | <for2_statement> {*} #= for2_statement | <jump_statement> {*} #= jump_statement }
rule labeled_statement { | <identifier> ':' <statement> | 'case' <constant_expression> ':' <statement> | 'default' ':' <statement> }
rule compound_statement { '{' <block_item>* '}' {*} }
rule block_item { | <declaration> {*} #= declaration | <statement> {*} #= statement }
rule expression_statement { <expression>? ';' {*} }
rule if_statement { 'if' '(' <expression> ')' <statement> ['else' $<else>=<statement>]? {*} }
rule switch_statement { 'switch' '(' <expression> ')' <statement> }
rule while_statement { 'while' '(' <expression> ')' <statement> {*} }
rule do_while_statement { 'do' <statement> 'while' '(' <expression> ')' ';' {*} }
rule for1_statement { 'for' '(' [$<init>=<expression>]? ';' [$<cond>=<expression>]? ';' [$<step>=<expression>]? ')' <statement> {*} }
rule for2_statement { 'for' '(' <declaration> [$<cond>=<expression>]? ';' [$<step>=<expression>]? ')' <statement> {*} }
rule jump_statement { | 'goto' <identifier> ';' {*} #= goto | 'continue' ';' {*} #= continue | 'break' ';' {*} #= break | 'return' <expression>? ';' {*} #= return }
## A.1.1 Lexical elements ## ##rule token { ## | <keyword> ## | <identifier> ## | <constant> ## | <c_string_literal> ## | <punctuator> ##}
regex preprocessing_token { | <header_name> | <identifier> | <pp_number> | <character_constant> | <string_literal> | <!pound> <punctuator> | <universal_character_name> | <-[# \r\n\t]>\S* ## <-[#]-\S>\S* ##non-whitespace }
## A.1.2 Keywords ## token keyword { [ auto | enum | restrict | unsigned | break | extern | return | void | case | float | short | volatile | char | for | signed | while | const | goto | sizeof | _Bool | continue | if | static | _Complex | default | inline | struct | _Imaginary | do | int | switch | double | long | typedef | else | register | union ]>>
}
token reserved_word { <keyword> }
token identifier { <!reserved_word> <identifier_nondigit> [ <identifier_nondigit> | <digit> ]* {*} }
token identifier_nondigit { <alpha> | <[_]> | <universal_character_name> }
## A.1.4 Universal character names ## token universal_character_name { | '\u' <xdigit>**{4} | '\U' <xdigit>**{8} }
## A.1.5 Constants ## token constant { | <floating_constant> {*} #= floating_constant | <integer_constant> {*} #= integer_constant | <enumeration_constant> {*} #= enumeration_constant | <character_constant> {*} #= character_constant }
token integer_constant { [ <decimal_constant> | <octal_constant> | <hexadecimal_constant> ] <integer_suffix>? {*} }
token decimal_constant { <[1..9]> <digit>* }
token octal_constant { 0 <[0..7]>* }
token hexadecimal_constant { 0 <[xX]> <xdigit>+ }
token integer_suffix { | <[uU]> [ll?|LL?]? | [ll?|LL?] <[uU]>? }
token floating_constant { [ | <decimal_floating_constant> | <hexadecimal_floating_constant> ] {*} }
token decimal_floating_constant { [ | <fractional_constant> <exponent_part>? | <digit_sequence> <exponent_part> ] <floating_suffix>? }
token hexadecimal_prefix { 0 <[xX]> }
token hexadecimal_floating_constant { <hexadecimal_prefix> [ | <hexadecimal_fractional_constant> | <hexadecimal_digit_constant> ] <binary_exponent_part> <floating_suffix>? }
token fractional_constant { | <digit_sequence>? \. <digit_sequence> | <digit_sequence> \. }
token exponent_part { <[eE]> ['+'|'-']? <digit_sequence> }
token digit_sequence { <digit>+ }
token hexadecimal_fractional_constant { | <hexadecimal_digit_sequence>? \. <hexadecimal_digit_sequence> | <hexadecimal_digit_sequence> \. }
token binary_exponent_part { <[pP]> ['+'|'-']? <digit_sequence> }
token hexadecimal_digit_sequence { <xdigit>+ }
token floating_suffix { <[fFlL]> }
token enumeration_constant { <identifier> }
token character_constant { [L]? \' <c_char>+ \' }
token <c_char> { <-['\\\n]> | <escape_sequence> }
token escape_sequence { \\ [ <['"?\\abfnrtv]> | <octal_digit>**{1..3} | x <xdigit>+ | <universal_character_name> ] }
## A.1.6 String literals token c_string_literal { [L]? <string_literal: '"'> {*} }
##\" <s_char>* \"
token s_char { <-["\\\n]> | <escape_sequence> }
## A.2 Phrase structure grammar ##
## A.2.1 Expressions ##
rule constant_expression { <conditional_expression> {*} }
rule expression { <assignment_expression> [',' <assignment_expression>]* {*} }
rule assignment_expression { [<unary_expression> <assign_op>]* <conditional_expression> {*} }
rule assign_op { '='|'*='|'/='|'%='|'+='|'-='|'<<='|'>>='|'&='|'^='|'|=' }
rule conditional_expression { <logical_expression> ['?' <expression> ':' <conditional_expression>]? {*} }
rule logical_expression is optable { ... }
proto 'infix:||' is precedence('1') { ... }
proto 'infix:&&' is tighter('infix:||') { ... }
proto 'infix:|' is tighter('infix:&&') { ... }
proto 'infix:^' is tighter('infix:|') { ... }
proto 'infix:&' is tighter('infix:^') { ... }
proto 'infix:==' is tighter('infix:&') { ... } proto 'infix:!=' is equal('infix:==') { ... }
proto 'infix:<' is tighter('infix:==') { ... } proto 'infix:>' is equal('infix:<') { ... } proto 'infix:>=' is equal('infix:<') { ... } proto 'infix:<=' is equal('infix:<') { ... }
proto 'infix:<<' is tighter('infix:==') { ... } proto 'infix:>>' is equal('infix:<<') { ... }
proto 'infix:+' is tighter('infix:<<') is pirop('n_add') { ... } proto 'infix:-' is equal('infix:+') is pirop('n_sub') { ... }
proto 'infix:*' is tighter('infix:+') is pirop('n_mul') { ... } proto 'infix:/' is equal('infix:*') is pirop('n_div') { ... } proto 'infix:%' is equal('infix:*') is pirop('n_mod') { ... }
proto 'term:' is tighter('infix:*') is parsed(&cast_expression) { ... }
rule postfix_expression_prefix { | <primary_expression> {*} #= primary_expression | '(' <type_name> ')' '{' <initializer_list> [',']? '}' {*} #= type_name }
rule postfix_expression { <postfix_expression_prefix> <postfix_expression_suffix>* {*} }
rule postfix_expression_suffix { | <index> {*} #= index | <arguments> {*} #= arguments | <direct_field> {*} #= direct_field | <indirect_field> {*} #= indirect_field | <inc_or_dec> {*} #= inc_or_dec }
rule inc_or_dec { $<op>=['++'|'--'] {*} }
rule index { '[' <expression> ']' {*} }
rule direct_field { '.' <identifier> {*} }
rule indirect_field { '->' <identifier> {*} }
rule arguments { '(' <argument_expression_list>? ')' {*} }
rule argument_expression_list { <assignment_expression> [',' <assignment_expression>]* {*} }
rule unary_expression { | <postfix_expression> {*} #= postfix_expression | <prefix_expression> {*} #= prefix_expression | <unary_operator> <cast_expression> | 'sizeof' <unary_expression> | 'sizeof' '(' <type_name> ')' }
rule prefix_expression { $<op>=['++'|'--'] <unary_expression> {*} }
rule unary_operator { '&' | '*' | '+' | '-' | '~' | '!' }
rule cast_expression { ['(' <type_name> ')']* <unary_expression> {*} }
rule primary_expression { | <identifier> {*} #= identifier | <constant> {*} #= constant | <c_string_literal> {*} #= c_string_literal | '(' <expression> ')' {*} #= expression }
token ws { [ | '//' \N* \n | '/*' .*? '*/' | \s+ | '#' \N* \n ]* }
## A.1.7 Punctuators ##
token punctuator { | \[ | \] | <[(){}.]> | '->' | '++' | '--' | <[&*+\-~!/%]> | '<<' | '>>' | '<' | '>' | '<=' | '>=' | '==' | '!=' | <[^|]> | '&&' | '||' | <[?:;]> | '...' | <[*/%+\-&^|]> | '<<' | '>>' | '=' | <[,#]> | '##' | '<:' | ':>' | '<%' | '%>' | '%:' | '%:%:' }
## A.3 Preprocessing directives ##
rule pre_processing_file { <group>? }
rule group { <group_part>+ }
rule group_part { | <pp_tokens>? <newline> | <if_section> | <control_line> }
rule if_section { <if_group> <elif_group>* <else_group>? <endif_line> }
rule if_group { | '#' 'if' <constant_expression> <newline> <group>? | '#' 'ifdef' <identifier> <newline> <group>? | '#' 'ifndef' <identifier> <newline> <group>? }
rule elif_group { '#' 'elif' <constant_expression> <newline> <group>? }
rule else_group { '#' 'else' <newline> <group>? }
rule endif_line { '#' 'endif' <newline> }
rule control_line { | '#' 'include' <pp_tokens> <newline> | '#' 'define' <identifier> <replacement_list> <newline> | '#' 'define' <identifier> <lparen> <identifier_list>? ')' <replacement_list> <newline> | '#' 'define' <identifier> <lparen> '...' ')' <replacement_list> <newline> | '#' 'define' <identifier> <lparen> <identifier_list> ',' '...' ')' <replacement_list> <newline> | '#' 'undef' <identifier> <newline> | '#' 'line' <pp_tokens> <newline> | '#' 'error' <pp_tokens>? <newline> | '#' 'pragma' <pp_tokens>? <newline> | '#' <newline> }
rule pp_tokens { <preprocessing_token>+ }
rule preprocessing_token { | <header_name> | <identifier> | <pp_number> | <character_constant> | <c_string_literal> | <punctuator> }
rule pp_number { ['.']? <digit> <pp_number_suffix>* }
rule pp_number_suffix { | '.' | <identifier_nondigit> | <digit> | <[eEpP]> ['+'|'-'] }
rule replacement_list { <pp_tokens>? }
token lparen { '(' }
token newline { \n }
## A.1.8 Header names token header_name { | \< <h_char>+ \> | \" <q_char>+ \" }
token h_char { <-[\n>]> } token q_char { <-[\n"]> }