grammar C99::Grammar is PCT::Grammar;

## A.2.4 External definitions ## ## {{ _dumper(match) }}

token TOP { ^ <external_declaration>+ [ $ || <.panic: Syntax error> ] {*} }

rule external_declaration { | <declaration> {*} #= declaration | <function_definition> {*} #= function_definition # <declaration_specifiers> # [ # | <declaration2> # | <func_decl2> # ] }

rule func_decl2 { <declarator> <declaration>* <compound_statement> {*} }

rule declaration2 { [ <init_declarator> [',' <init_declarator>]* ]? ';' {*} }

rule function_definition { <declaration_specifiers> <declarator> <declaration>* <compound_statement> {*} }

## A.2.2 ##

rule declaration { <declaration_specifiers> [ <init_declarator> [',' <init_declarator>]* ]? ';' {*} }

rule declaration_specifiers { <repeatable_declaration_specifiers>* <type_specifier> <repeatable_declaration_specifiers>* {*} } #rule declaration_specifiers_orig { [ <storage_class_specifier> | <type_specifier> | <type_qualifier> | <function_specifier> ]+ {*} } #rule declaration_specifiers { [ <declaration_specifiers_inside> ]+ {*} } #rule declaration_specifiers_inside { [ <storage_class_specifier> | <type_specifier> | <type_qualifier> | <function_specifier> ] {{ _dumper(match) }} } token builtin_type_specifier { 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | '_Bool' | '_Complex' | '_Imaginary' }

rule repeatable_declaration_specifiers { [ | <storage_class_specifier> | <type_qualifier> | <function_specifier> ] }

rule function_specifier { | 'inline' | '__inline__' }

rule init_declarator { <declarator> ['=' <initializer>]? {*} }

rule storage_class_specifier { [ | $<typedef>=['typedef'] {*} #= typedef | $<extern>=['extern'] {*} #= extern | $<static>=['static'] {*} #= static | $<auto>=['auto'] {*} #= auto | $<register>=['register'] {*} #= register | $<__extension__>=['__extension__'] {*} #= __extension__ ] }

rule type_specifier { #| <builtin_type_specifier> | <builtin_type> | $<type>=[ 'struct' | 'union' ] <struct_or_union_specifier> | 'enum' <enum_specifier> | $<typedef_name>=<identifier> }

token builtin_type { [ [ $<signed>=[ 'signed' | 'unsigned' ] <.ws> ]? [ | 'void' | 'char' | 'short' <.ws> 'int' >> | 'short' | 'int' | 'long' <.ws> 'long' <.ws> 'int' >> | 'long' <.ws> 'long' >> | 'long' <.ws> 'int' >> | 'long' <.ws> 'double' >> | 'long' | 'float' | 'double' | '_Bool' | '_Complex' | '_Imaginary' ] >> | 'unsigned' | 'signed' ] }

rule struct_or_union_specifier { | <identifier>? '{' <struct_declaration>+ '}' | <identifier> }

rule struct_declaration { <specifier_qualifier_list> <struct_declarator_list>* ';' }

rule specifier_qualifier_list { <type_qualifier>* <type_specifier> <type_qualifier>* # [ # | <type_specifier> # | <type_qualifier> # ]+ }

rule struct_declarator_list { <struct_declarator> [',' <struct_declarator>]* }

rule struct_declarator { | <declarator>? ':' <constant_expression> | <declarator> }

rule enum_specifier { | <identifier>? '{' <enumerator_list> [',']? '}' | <identifier> }

rule enumerator_list { <enumerator> [',' <enumerator>]* }

rule enumerator { <enumeration_constant> ['=' <constant_expression>]? }

rule type_qualifier { $<qualifier>=[ |'const' |'restrict' |'volatile' |'__const' # gcc version of const |'__restrict' # gcc version of restricted |'__volatile' # gcc version of volatile |'__extension__' # gcc extension ] }

rule declarator { <pointer>? <direct_declarator> {*} }

rule direct_declarator { <declarator_prefix> <declarator_suffix>* <gcc_asm>? <gcc_attribute>* {*} }

rule declarator_prefix { | '(' <declarator> ')' {*} #= declarator | <identifier> {*} #= identifier }

rule declarator_suffix { | '(' <parameter_type_list> ')' {*} #= parameter_type_list | '(' <identifier_list>? ')' {*} #= identifier_list ## old-style C parameter declarations | '[' <assignment_expression>? ']' | '[' '*' ']' }

rule gcc_attribute { '__attribute__' '((' <gcc_attributes_list>'))' }

rule gcc_attributes_list { [<gcc_attr> [',' <gcc_attr>]* ]?

}

rule gcc_attr { | 'noreturn' | '__noreturn__' | [ 'format' | '__format__' ] '(' <gcc_attr_formats> ',' <digit>+ ',' <digit>+ ')' | '__const__' | '__const' | '__nothrow__' | '__aligned__' '(' <digit>+ ')' | '__format_arg__' '(' <digit>+ ')' | '__nonnull__' '(' <digit_list_plus> ')' | '__mode__' '(' <gcc_attr_mode> ')' | '__sentinel__' '(' <digit>+ ')' | '__malloc__' | '__pure__' | '__warn_unused_result__' }

rule digit_list_plus { <digit>+ [',' <digit>+ ]* {*} }

token gcc_attr_mode { | '__QI__' | '__DI__' | '__SI__' | '__HI__' | 'byte' | '__byte__' | 'word' | '__word__' | 'pointer' | '__pointer__' }

token gcc_attr_formats { | printf | __printf__ | scanf | strftime | gnu_printf | gnu_scanf | gnu_strftime | strfmon | __printf__ | __scanf__ | __strftime__ | __strfmon__ | ms_printf | ms_scanf | ms_strftime }

rule gcc_asm { [ 'asm' | '__asm__' ] '(' [<c_string_literal> ]* ')' }

rule pointer { |'*' [ <type_qualifier> ]* <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 ] <repeatable_declaration_specifiers>* }

rule identifier_list { <identifier> [',' <identifier>]* }

rule type_name { <specifier_qualifier_list> <abstract_declarator>? }

rule abstract_declarator { | <pointer> | <pointer>? <direct_abstract_declarator> }

rule direct_abstract_declarator { [ | '(' <abstract_declarator> ')' | '[' <assignment_expression>? ']' | '[' '*' ']' | '(' <parameter_type_list> ')' ] <direct_abstract_declarator_1>* }

rule direct_abstract_declarator_1 { | '[' <assignment_expression>? ']' | '[' '*' ']' | '(' <parameter_type_list> ')' }

rule typedef_name_DEAD_CODE {

## 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> ##}

## 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> | <hexadecimal_constant> | <octal_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_sequence> ] <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 equiv('infix:==') { ... }

proto 'infix:<' is tighter('infix:==') { ... } proto 'infix:>' is equiv('infix:<') { ... } proto 'infix:>=' is equiv('infix:<') { ... } proto 'infix:<=' is equiv('infix:<') { ... }

proto 'infix:<<' is equiv('infix:<') { ... } proto 'infix:>>' is equiv('infix:<') { ... }

proto 'infix:+' is tighter('infix:<<') is pirop('n_add') { ... } proto 'infix:-' is equiv('infix:+') is pirop('n_sub') { ... }

proto 'infix:*' is tighter('infix:+') is pirop('n_mul') { ... } proto 'infix:/' is equiv('infix:*') is pirop('n_div') { ... } proto 'infix:%' is equiv('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> {*} #= unary_operator | 'sizeof' <unary_expression> {*} #= sizeof | 'sizeof' '(' <type_name> ')' {*} #= sizeof_type }

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+ | <.gcc_preprocess_id> #| ^^ '#' \N \n #| '#' \N* \n {*} #= origin ]* }

token gcc_preprocess_id { ^^ '#' \s+ $<line>=[<.digit>+] \s+ <c_string_literal> $<ilist>=[ \s+ <.digit>+ ]* $$ {*} #= origin }


parrot