grammar Go::Grammar; token TOP { # ^ $ # ^ # ^ # ^ ^ # $ } token ws { [<[\ \t\r\n]>]* } ## this is a rule so whitespace is added around it token com { <.ws>? ',' <.ws>? } token semi { <.ws>? ';' <.ws>? } # | ? ')' <.ws>?> # | ? '}' <.ws>?> token automatic_semicolon { [ [ > | > | | | | | | | | | ] $$ ] | | } ###################################################################### ## Lexical elements #### Characters regex unicode_letter { <.alpha> } regex unicode_digit { <.digit> } #### Letters and digits regex letter { | '_' } regex decimal_digit { <.digit> } regex octal_digit { <[0..7]> } regex hex_digit { <.xdigit> } #### Comments #### Semicolons #### Identifiers token identifier { <.letter> [<.letter> | <.unicode_digit>]* } #### Keywords #### Operators and Delimiters #### Integer literals token int_lit { | | | } token decimal_lit { <[1..9]> <.decimal_digit>* } token octal_lit { 0 <.octal_digit>* } token hex_lit { 0x <.hex_digit>+ } #### Floating-point literals token float_lit { | <.decimals> '.' <.decimals>? ? | <.decimals> | '.' <.decimals> ? } token decimals { <.decimal_digit>+ } token exponent { <[eE]> <[+-]>? <.decimals> } #### Imaginary literals token imaginary_lit { [ | ] i } #### Character literals token char_lit { "'" ~ "'" [ | <-[\n\']> ] } token unicode_value { | | | | } token byte_value { | | } token octal_byte_value { '\\' <.octal_digit> ** 3 } token hex_byte_value { '\\x' <.hex_digit> ** 2 } token little_u_value { '\\u' <.hex_digit> ** 4 } token big_u_value { '\\U' <.hex_digit> ** 8 } token escaped_char { '\\' [ <[abfnrtv]> | '\\' | "'" | '"' ] } #### String literals token string_lit { | | } token raw_string_lit { '`' ~ '`' [ <-[\`]> ]* } token interpreted_string_lit { '"' ~ '"' [ <.unicode_value> | <-[\n\"]> ]* } ###################################################################### ## Types rule type { | | | '(' ')' } rule type_name { } rule type_lit { | | | | | | | | } #### Array types rule array_type { '[' ']' } rule array_length { } rule element_type { } #### Slice types rule slice_type { '[' ']' } #### Struct types rule struct_type { struct '{' ( <.semi>)* '}' } rule field_decl { [ | ] ? } rule anonymous_field { '*'? } rule tag { <.string_lit> } #### Pointer types rule pointer_type { '*' } rule base_type { } #### Function types rule function_type { func } rule signature { ? } rule result { | } rule parameters { '(' ? ')' } rule parameter_list { + % <.com> } rule parameter_decl { ? '...'? ? } #### Interface types rule interface_type { interface '{' ( <.semi>)* '}' } rule method_spec { | | } rule method_name { } rule interface_type_name { } #### Map types rule map_type { map '[' ']' } rule key_type { } #### Channel types rule channel_type { [ | chan '<-'? | '<-' chan ] } #### Blocks rule block { '{' ( <.semi>)* '}' } ###################################################################### ## Declarations and scope rule declaration { | | | } rule top_level_decl { | | | } #### Constant declarations rule const_decl { const [ | '(' ( <.semi>)* ')'] } rule const_spec { [? '=' ] } rule identifier_list { + % <.com> } rule expression_list { + % <.com> } #### Type declarations rule type_decl { type [ | '(' ( <.semi>)* ')'] } rule type_spec { } #### Variable declarations rule var_decl { var [ | '(' ( <.semi>)* ')'] } rule var_spec { } rule var_expression_list { | '=' | ['=' ]? } #### Short variable declarations rule short_var_decl { ':=' } #### Function declarations rule function_decl { func ? } rule function_name { } rule body { } #### Method declarations rule method_decl { func ? } rule receiver { '(' ? '*'? ')' } rule base_type_name { } ###################################################################### ## Expressions #### Operands rule operand { | | | | '(' ')' } rule literal { | | | } rule basic_lit { | | | | | } #### Qualified identifiers rule qualified_ident { | '.' | } #### Composite literals rule composite_lit { } rule literal_type { | | | '[...]' | | | } rule literal_value { '{' (* % <.com>) <.com>? '}' } rule element { [ ':']? } rule key { | } rule field_name { } rule element_index { } rule value { | } #### Function literals rule function_lit { } #### Primary expressions rule primary_expr { * } rule primary_subexpr { | | | } rule secondary_expr { | | | | | } #### Selectors rule selector { '.' } #### Indexes rule index { '[' ']' } #### Slices rule slice { '[' ? ':' ? ']' } #### Type assertions rule type_assertion { '.' '(' ')' } #### Calls rule call { '(' ( <.com>?)? ')' } rule argument_list { '...'? } #### Operators # TODO rule expression { # | # | | ( )* } #rule binary_expr { # # #} rule unary_expr { | | } #### Operator precedence rule binary_op { | '||' | '&&' | | | } # TODO: when there are no bugs, rewrite these rules to be # more like add_op, which is more idiomatic, so they say. # BUG: proto token rel_op {*} token rel_op:sym { '==' } token rel_op:sym { '!=' } token rel_op:sym { '<' } token rel_op:sym { '<=' } token rel_op:sym { '>' } token rel_op:sym { '>=' } proto token add_op {*} token add_op:sym<+> { } token add_op:sym<-> { } token add_op:sym<|> { } token add_op:sym<^> { } proto token mul_op {*} token mul_op:sym<*> { } token mul_op:sym { } token mul_op:sym<%> { } token mul_op:sym { '<<' } token mul_op:sym { '>>' } token mul_op:sym<&> { } token mul_op:sym<&^> { } proto token unary_op {*} token unary_op:sym<+> { } token unary_op:sym<-> { } token unary_op:sym { } token unary_op:sym<^> { } token unary_op:sym<*> { } token unary_op:sym<&> { } token unary_op:sym { '<-' } #### Method expressions rule method_expr { '.' } rule receiver_type { | | '(' '*' ')' } #### Conversions rule conversion { '(' ')' } ###################################################################### ## Statements ##rule statement_list { * % <.semi> } rule statement { | | | | | } # BAD: This rule is nonstandard. # is not supposed to match , # but I don't see a way around this right now. # This shouldn't cause problems, though, because this # is more liberal than the standard Go parser. rule simple_stmt { | | | | | | | } # is not in the Go spec proto rule keyword_stmt {*} #### Empty statements (handled above?) #### Labeled statements rule labeled_stmt {