tagged release 0.7.1
[parrot.git] / languages / c99 / src / parser / grammar.pg
blobed6cd41c39377bc88d284e07d48c0ed22046b315
1 # $Id$
2 # Copyright (C) 2008, The Perl Foundation.
4 =begin overview
6 This is the grammar for C99 written as a sequence of Perl 6 rules.
9 taken from n869.pdf
10 google for n869.pdf
12 =end overview
14 grammar C99::Grammar is PCT::Grammar;
16 ## A.2.4 External definitions
19 token TOP {
20     ^
21     <external_declaration>+
22     [ $ || <.panic: Syntax error> ]
23     {*}
26 rule external_declaration {
27     | <declaration> {*}          #= declaration
28     | <function_definition> {*}  #= function_definition
31 rule function_definition {
32     <declaration_specifiers>
33     <declarator>
34     <declaration>*
35     <compound_statement>
36     {*}
40 ## A.2.2
43 rule declaration {
44     <declaration_specifiers>
45     [ <init_declarator> [',' <init_declarator>]* ]?
46     ';'
47     {*}
50 rule declaration_specifiers {
51     [ <type_specifier>
52     | <storage_class_specifier>
53     | <type_qualifier>
54     | <function_specifier>
55     ]+
58 rule function_specifier {
59     'inline'
62 rule init_declarator {
63     <declarator> ['=' <initializer>]?
64     {*}
67 rule storage_class_specifier {
68     | 'typedef'
69     | 'extern'
70     | 'static'
71     | 'auto'
72     | 'register'
75 rule type_specifier {
76     | <builtin_type>
77     | <struct_or_union_specifier>
78     | <enum_specifier>
79     | <typedef_name>
82 token builtin_type {
83     | 'void'
84     | 'char'
85     | 'short'
86     | 'int'
87     | 'long'
88     | 'float'
89     | 'double'
90     | 'signed'
91     | 'unsigned'
92     | '_Bool'
93     | '_Complex'
94     | '_Imaginary'
97 rule struct_or_union_specifier {
98     $<type>=['struct'|'union']
99     [
100     | <struct_or_union_definition>
101     | <pre_declaration>
102     ]
105 rule struct_or_union_definition {
106     <identifier>? '{' <struct_declaration>+ '}'
109 rule pre_declaration {
110     <identifier>
113 rule struct_declaration {
114     <specifier_qualifier_list> <struct_declarator_list>* ';'
117 rule specifier_qualifier_list {
118     [
119     | <type_specifier>
120     | <type_qualifier>
121     ]+
124 rule struct_declarator_list {
125     <struct_declarator> [',' <struct_declarator>]*
128 rule struct_declarator {
129     | <declarator>? ':' <constant_expression>
130     | <declarator>
133 rule enum_specifier {
134     | 'enum' <identifier>? '{' <enumerator_list> [',']? '}'
135     | 'enum' <identifier>
138 rule enumerator_list {
139     <enumerator> [',' <enumerator>]*
142 rule enumerator {
143     <enumeration_constant> ['=' <constant_expression>]?
146 rule type_qualifier {
147     $<qualifier>=['const'|'restrict'|'volatile']
150 rule declarator {
151     <pointer>?
152     <direct_declarator>
153     {*}
156 rule direct_declarator {
157     <declarator_prefix>
158     <declarator_suffix>*
159     {*}
162 rule declarator_prefix {
163     | '(' <declarator> ')' {*}       #= declarator
164     | <identifier> {*}               #= identifier
167 rule declarator_suffix {
168     | '(' <parameter_type_list> ')' {*}    #= parameter_type_list
169     | '(' <identifier_list>? ')' {*}       #= identifier_list ## old-style C parameter declarations
170     | '[' <assignment_expression>? ']'
171     | '[' '*' ']'
174 rule pointer {
175     '*' <type_qualifier>* ['*']?
178 rule parameter_type_list {
179     <parameter_list>  [$<vararg>=[',' '...']]?
180     {*}
183 rule parameter_list {
184     <parameter_declaration> [',' <parameter_declaration>]*
185     {*}
188 rule parameter_declaration {
189     <declaration_specifiers>
190     [
191     | <declarator> {*}               #= declarator
192     | <abstract_declarator>? {*}     #= abstract_declarator
193     ]
196 rule identifier_list {
197     <identifier> [',' <identifier>]*
200 rule type_name {
201     <specifier_qualifier_list> <abstract_declarator>?
204 rule abstract_declarator {
205     | '*'
206     | ['*']? <direct_abstract_declarator>
209 rule direct_abstract_declarator {
210     [
211     | '(' <abstract_declatator> ')'
212     | '[' <assignment_expression>? ']'
213     | '(' <parameter_type_list> ')'
214     ]
215     <direct_abstract_declarator_1>*
218 rule direct_abstract_declarator_1 {
219     | '[' <assignment_expression>? ']'
220     | '[' '*' ']'
221     | '(' <parameter_type_list> ')'
224 rule typedef_name {
226 ## a typedef name can be a return type specifier. This is ambiguous, because
227 ## the parser doesn't know if it's a return type thingie or the name of the
228 ## function. Therefore, typedef'd names must be stored in a %hash, so that
229 ## this rule is not calling <identifier>, but inspecting the registered
230 ## typedef'd names. For now, specify 'SOME_TYPEDEF_NAME' as the only typedef'd name.
232     #<identifier>
233     'SOME_TYPEDEF_NAME'
236 rule initializer {
237     | <assignment_expression>
238     | '{' <initializer_list> [',']? '}'
241 rule initializer_list {
242     <initializer_item> [',' <initializer_item>]*
245 rule initializer_item {
246     <designation>? <initializer>
249 rule designation {
250     <designator>+ '='
253 rule designator {
254     | '[' <constant_expression> ']'
255     | '.' <identifier>
259 ## A.2.3 Statements
262 rule statement {
263     | <labeled_statement>
264     | <compound_statement> {*}        #= compound_statement
265     | <expression_statement> {*}      #= expression_statement
266     | <if_statement> {*}              #= if_statement
267     | <switch_statement>
268     | <while_statement> {*}           #= while_statement
269     | <do_while_statement> {*}        #= do_while_statement
270     | <for1_statement> {*}            #= for1_statement
271     | <for2_statement> {*}            #= for2_statement
272     | <jump_statement> {*}            #= jump_statement
275 rule labeled_statement {
276     | <identifier> ':' <statement>
277     | 'case' <constant_expression> ':' <statement>
278     | 'default' ':' <statement>
281 rule compound_statement {
282     '{' <block_item>* '}'
283     {*}
286 rule block_item {
287     | <declaration> {*}    #= declaration
288     | <statement> {*}      #= statement
291 rule expression_statement {
292     <expression>? ';'
293     {*}
296 rule if_statement {
297     'if' '(' <expression> ')' <statement> ['else' $<else>=<statement>]?
298     {*}
301 rule switch_statement {
302     'switch' '(' <expression> ')' <statement>
305 rule while_statement {
306     'while' '(' <expression> ')' <statement>
307     {*}
310 rule do_while_statement {
311     'do' <statement> 'while' '(' <expression> ')' ';'
312     {*}
315 rule for1_statement {
316     'for' '(' [$<init>=<expression>]? ';' [$<cond>=<expression>]? ';' [$<step>=<expression>]? ')'
317     <statement>
318     {*}
321 rule for2_statement {
322     'for' '(' <declaration> [$<cond>=<expression>]? ';' [$<step>=<expression>]? ')' <statement>
323     {*}
326 rule jump_statement {
327     | 'goto' <identifier> ';' {*}         #= goto
328     | 'continue' ';' {*}                  #= continue
329     | 'break' ';' {*}                     #= break
330     | 'return' <expression>? ';' {*}      #= return
334 ## A.1.1 Lexical elements
336 ##rule token {
337 ##  | <keyword>
338 ##  | <identifier>
339 ##  | <constant>
340 ##  | <c_string_literal>
341 ##  | <punctuator>
344 regex preprocessing_token {
345   | <header_name>
346   | <identifier>
347   | <pp_number>
348   | <character_constant>
349   | <string_literal>
350   | <!pound> <punctuator>
351   | <universal_character_name>
352   | <-[# \r\n\t]>\S* ## <-[#]-\S>\S* ##non-whitespace
355 ## A.1.2 Keywords
357 token keyword {
358   [ auto      | enum      | restrict  | unsigned
359   | break     | extern    | return    | void
360   | case      | float     | short     | volatile
361   | char      | for       | signed    | while
362   | const     | goto      | sizeof    | _Bool
363   | continue  | if        | static    | _Complex
364   | default   | inline    | struct    | _Imaginary
365   | do        | int       | switch
366   | double    | long      | typedef
367   | else      | register  | union     ]>>
371 token reserved_word {
372     <keyword>
376 token identifier {
377     <!reserved_word>
378     <identifier_nondigit> [ <identifier_nondigit> | <digit> ]*
379     {*}
382 token identifier_nondigit {
383     <alpha> | <[_]> | <universal_character_name>
386 ## A.1.4 Universal character names
388 token universal_character_name {
389   | '\u' <xdigit>**{4}
390   | '\U' <xdigit>**{8}
394 ## A.1.5 Constants
396 token constant {
397     | <floating_constant> {*}       #= floating_constant
398     | <integer_constant> {*}        #= integer_constant
399     | <enumeration_constant> {*}    #= enumeration_constant
400     | <character_constant> {*}      #= character_constant
403 token integer_constant {
404     [ <decimal_constant>
405     | <octal_constant>
406     | <hexadecimal_constant>
407     ]
408     <integer_suffix>?
409     {*}
412 token decimal_constant {
413     <[1..9]> <digit>*
416 token octal_constant {
417     0 <[0..7]>*
420 token hexadecimal_constant {
421     0 <[xX]> <xdigit>+
424 token integer_suffix {
425     | <[uU]> [ll?|LL?]?
426     | [ll?|LL?] <[uU]>?
429 token floating_constant {
430     [
431     | <decimal_floating_constant>
432     | <hexadecimal_floating_constant>
433     ]
434     {*}
437 token decimal_floating_constant {
438     [
439     | <fractional_constant> <exponent_part>?
440     | <digit_sequence> <exponent_part>
441     ]
442     <floating_suffix>?
445 token hexadecimal_prefix {
446   0 <[xX]>
449 token hexadecimal_floating_constant {
450   <hexadecimal_prefix>
451   [
452   | <hexadecimal_fractional_constant>
453   | <hexadecimal_digit_constant>
454   ]
455   <binary_exponent_part> <floating_suffix>?
458 token fractional_constant {
459   | <digit_sequence>? \. <digit_sequence>
460   | <digit_sequence> \.
463 token exponent_part {
464   <[eE]> ['+'|'-']? <digit_sequence>
467 token digit_sequence { <digit>+ }
469 token hexadecimal_fractional_constant {
470   | <hexadecimal_digit_sequence>? \. <hexadecimal_digit_sequence>
471   | <hexadecimal_digit_sequence> \.
474 token binary_exponent_part {
475   <[pP]> ['+'|'-']? <digit_sequence>
478 token hexadecimal_digit_sequence { <xdigit>+ }
480 token floating_suffix { <[fFlL]> }
482 token enumeration_constant { <identifier> }
484 token character_constant { [L]? \' <c_char>+ \' }
486 token <c_char> { <-['\\\n]> | <escape_sequence> }
488 token escape_sequence {
489   \\
490   [ <['"?\\abfnrtv]>
491   | <octal_digit>**{1..3}
492   | x <xdigit>+
493   | <universal_character_name>
494   ]
497 ## A.1.6 String literals
498 token c_string_literal {
499     [L]? <string_literal: '"'>
500     {*}
503 ##\" <s_char>* \"
505 token s_char { <-["\\\n]> | <escape_sequence> }
508 ## A.2 Phrase structure grammar
511 ## A.2.1 Expressions
514 rule constant_expression {
515     <conditional_expression>
516     {*}
519 rule expression {
520     <assignment_expression> [',' <assignment_expression>]*
521     {*}
524 rule assignment_expression {
525     [<unary_expression> <assign_op>]* <conditional_expression>
526     {*}
529 rule assign_op { '='|'*='|'/='|'%='|'+='|'-='|'<<='|'>>='|'&='|'^='|'|=' }
531 rule conditional_expression {
532     <logical_expression> ['?' <expression> ':' <conditional_expression>]?
533     {*}
536 rule logical_expression is optable { ... }
538 proto 'infix:||' is precedence('1') { ... }
540 proto 'infix:&&' is tighter('infix:||') { ... }
542 proto 'infix:|' is tighter('infix:&&') { ... }
544 proto 'infix:^' is tighter('infix:|') { ... }
546 proto 'infix:&' is tighter('infix:^') { ... }
548 proto 'infix:==' is tighter('infix:&') { ... }
549 proto 'infix:!=' is equal('infix:==') { ... }
551 proto 'infix:<' is tighter('infix:==') { ... }
552 proto 'infix:>' is equal('infix:<') { ... }
553 proto 'infix:>=' is equal('infix:<') { ... }
554 proto 'infix:<=' is equal('infix:<') { ... }
556 proto 'infix:<<' is tighter('infix:==') { ... }
557 proto 'infix:>>' is equal('infix:<<') { ... }
559 proto 'infix:+' is tighter('infix:<<') is pirop('n_add') { ... }
560 proto 'infix:-' is equal('infix:+') is pirop('n_sub') { ... }
562 proto 'infix:*' is tighter('infix:+') is pirop('n_mul') { ... }
563 proto 'infix:/' is equal('infix:*') is pirop('n_div') { ... }
564 proto 'infix:%' is equal('infix:*') is pirop('n_mod') { ... }
566 proto 'term:' is tighter('infix:*')
567               is parsed(&cast_expression) { ... }
570 rule postfix_expression_prefix {
571     | <primary_expression> {*}                                  #= primary_expression
572     | '(' <type_name> ')' '{' <initializer_list> [',']? '}' {*} #= type_name
575 rule postfix_expression {
576     <postfix_expression_prefix>
577     <postfix_expression_suffix>*
578     {*}
581 rule postfix_expression_suffix {
582     | <index> {*}                           #= index
583     | <arguments>  {*}                      #= arguments
584     | <direct_field> {*}                    #= direct_field
585     | <indirect_field> {*}                  #= indirect_field
586     | <inc_or_dec> {*}                      #= inc_or_dec
589 rule inc_or_dec {
590     $<op>=['++'|'--']
591     {*}
594 rule index {
595     '[' <expression> ']'
596     {*}
599 rule direct_field {
600     '.' <identifier>
601     {*}
604 rule indirect_field {
605     '->' <identifier>
606     {*}
609 rule arguments {
610     '(' <argument_expression_list>? ')'
611     {*}
614 rule argument_expression_list {
615     <assignment_expression> [',' <assignment_expression>]*
616     {*}
619 rule unary_expression {
620     | <postfix_expression> {*}              #= postfix_expression
621     | <prefix_expression> {*}               #= prefix_expression
622     | <unary_operator> <cast_expression>
623     | 'sizeof' <unary_expression>
624     | 'sizeof' '(' <type_name> ')'
627 rule prefix_expression {
628     $<op>=['++'|'--'] <unary_expression>
629     {*}
632 rule unary_operator {
633     '&' | '*' | '+' | '-' | '~' | '!'
636 rule cast_expression {
637     ['(' <type_name> ')']* <unary_expression>
638     {*}
641 rule primary_expression {
642     | <identifier> {*}             #= identifier
643     | <constant> {*}               #= constant
644     | <c_string_literal> {*}       #= c_string_literal
645     | '(' <expression> ')' {*}     #= expression
648 token ws {
649   [
650   | '//' \N* \n
651   | '/*' .*? '*/'
652   | \s+
653   | '#' \N* \n
654   ]*
657 ## A.1.7 Punctuators
660 token punctuator {
661   | \[        | \]      | <[(){}.]>     | '->'
662   | '++'      | '--'    | <[&*+\-~!/%]>
663   | '<<'      | '>>'    | '<'    | '>'
664   | '<='      | '>='    | '=='          | '!='
665   | <[^|]>    | '&&'    | '||'
666   | <[?:;]>   | '...'
667   | <[*/%+\-&^|]>       | '<<'   | '>>' | '='
668   | <[,#]>    | '##'
669   | '<:'      | ':>'    | '<%'   | '%>' | '%:' | '%:%:'
673 ## A.3 Preprocessing directives
676 rule pre_processing_file {
677     <group>?
680 rule group {
681     <group_part>+
684 rule group_part {
685     | <pp_tokens>? <newline>
686     | <if_section>
687     | <control_line>
690 rule if_section {
691     <if_group> <elif_group>* <else_group>? <endif_line>
694 rule if_group {
695     | '#' 'if' <constant_expression> <newline> <group>?
696     | '#' 'ifdef' <identifier> <newline> <group>?
697     | '#' 'ifndef' <identifier> <newline> <group>?
700 rule elif_group {
701     '#' 'elif' <constant_expression> <newline> <group>?
704 rule else_group {
705     '#' 'else' <newline> <group>?
708 rule endif_line {
709     '#' 'endif' <newline>
712 rule control_line {
713     | '#' 'include' <pp_tokens> <newline>
714     | '#' 'define' <identifier> <replacement_list> <newline>
715     | '#' 'define' <identifier> <lparen> <identifier_list>? ')' <replacement_list> <newline>
716     | '#' 'define' <identifier> <lparen> '...' ')' <replacement_list> <newline>
717     | '#' 'define' <identifier> <lparen> <identifier_list> ',' '...' ')' <replacement_list> <newline>
718     | '#' 'undef' <identifier> <newline>
719     | '#' 'line' <pp_tokens> <newline>
720     | '#' 'error' <pp_tokens>? <newline>
721     | '#' 'pragma' <pp_tokens>? <newline>
722     | '#' <newline>
725 rule pp_tokens {
726     <preprocessing_token>+
729 rule preprocessing_token {
730     | <header_name>
731     | <identifier>
732     | <pp_number>
733     | <character_constant>
734     | <c_string_literal>
735     | <punctuator>
738 rule pp_number {
739     ['.']? <digit> <pp_number_suffix>*
742 rule pp_number_suffix {
743     | '.'
744     | <identifier_nondigit>
745     | <digit>
746     | <[eEpP]> ['+'|'-']
749 rule replacement_list {
750     <pp_tokens>?
753 token lparen {
754     '('
757 token newline {
758      \n
761 ## A.1.8 Header names
762 token header_name {
763     | \< <h_char>+ \>
764     | \" <q_char>+ \"
767 token h_char { <-[\n>]> }
768 token q_char { <-[\n"]> }