grammar C99::CPP::Grammar is PCT::Grammar;

token ws { | \h* | <multilinecomment> }

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

## 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 expression { <constant_expression> {*} }

rule constant_expression { <conditional_expression> {*} }

rule assign_op { '='|'*='|'/='|'%='|'+='|'-='|'<<='|'>>='|'&='|'^='|'|=' }

rule conditional_expression { <logical_expression> ['?' <conditional_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 pound { '#' } token begincomment { '/*' }

token multilinecomment { '/*' .*? '*/' }

regex preprocessing_token { # | <multilinecomment> | <header_name> | <identifier> | <pp_number> | <character_constant> | '"' <string_literal: '"'> '"' | <!pound> <!begincomment> <punctuator> | <universal_character_name> | <!begincomment><-[# \t\r\n]>\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> }

token character_constant { [L]? \' <c_char>+ \' }

token <c_char> { <-['\\\n]> | <escape_sequence> }

## A.1.4 Universal character names ## token universal_character_name { | '\u' <xdigit>**{4} | '\U' <xdigit>**{8} }

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

token pp_number { ['.']? <digit> <pp_number_suffix>* }

token 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"]> }


parrot