afborchert / astl-c

Astl programming language for C
GNU General Public License v2.0
1 stars 0 forks source link

Grammar railroad diagram #1

Open mingodad opened 3 years ago

mingodad commented 3 years ago

Using this tool https://www.bottlecaps.de/convert/ and manually adding the tokens from astl-c/operators.txt we can see a railroad diagram for the grammar in astl-c/parser.ypp copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui in the tab Edit Grammar then switching to the tab View Diagram.

/*
From https://raw.githubusercontent.com/afborchert/astl-c/27e8ed50fdd0336e3d9bd9cd58b50959723ab2bd/astl-c/parser.ypp
*/

/* converted on Sun Jul 18, 2021, 18:11 (UTC+02) by bison-to-w3c v0.53 which is Copyright (c) 2011-2021 by Gunther Rademacher <grd@gmx.net> */

start    ::= symtab_open translation_unit symtab_close
symtab_open
         ::=
symtab_close
         ::=
translation_unit
         ::= semicolons external_declaration*
external_declaration
         ::= ( function_definition | extended_declaration | assembler_instructions SEMICOLON ) semicolons
semicolons
         ::= SEMICOLON*
function_definition
         ::= std_function_definition
           | symtab_open restricted_declaration_specifiers? regular_direct_declarator declaration_list? compound_statement symtab_close
std_function_definition
         ::= symtab_open extended_declaration_specifiers declarator declaration_list? compound_statement symtab_close
declaration_list
         ::= declaration extended_declaration*
primary_expression
         ::= identifier
           | constant
           | string_literal
           | LPAREN embedded_expression RPAREN
           | statement_expression
va_arg_macro
         ::= VA_ARG LPAREN expression COMMA type_name RPAREN
builtin_offsetof
         ::= BUILTIN_OFFSETOF LPAREN type_name COMMA name ( DOT name | LBRACKET expression RBRACKET )* RPAREN
alignof_expr
         ::= ALIGNOF LPAREN ( type_name | unary_expression ) RPAREN
types_compatible_p
         ::= TYPES_COMPATIBLE_P LPAREN type_name COMMA type_name RPAREN
choose_expr
         ::= CHOOSE_EXPR LPAREN assignment_expression COMMA assignment_expression COMMA assignment_expression RPAREN
unreachable
         ::= UNREACHABLE LPAREN RPAREN
statement_expression
         ::= LPAREN compound_statement RPAREN
postfix_expression
         ::= ( primary_expression | function_call | postfix_plusplus | postfix_minusminus | LPAREN type_name RPAREN LBRACE initializer_list? RBRACE | assembler_instructions | builtin_offsetof | alignof_expr | va_arg_macro | types_compatible_p | choose_expr | unreachable ) ( LBRACKET expression RBRACKET | ( DOT | ARROW ) name )*
postfix_plusplus
         ::= postfix_expression PLUSPLUS
postfix_minusminus
         ::= postfix_expression MINUSMINUS
function_call
         ::= postfix_expression LPAREN argument_expression_list? RPAREN
unary_expression
         ::= SIZEOF* ( postfix_expression | address_of | pointer_dereference | unary_plus | unary_minus | prefix_plusplus | prefix_minusminus | ( TILDE | EXCLAMATION ) cast_expression | SIZEOF LPAREN type_name RPAREN | label_as_value )
label_as_value
         ::= AND identifier
address_of
         ::= AMPERSAND cast_expression
prefix_plusplus
         ::= PLUSPLUS unary_expression
prefix_minusminus
         ::= MINUSMINUS unary_expression
unary_plus
         ::= PLUS cast_expression
unary_minus
         ::= MINUS cast_expression
pointer_dereference
         ::= STAR cast_expression
cast_expression
         ::= ( LPAREN type_name RPAREN )* unary_expression
multiplicative_expression
         ::= cast_expression ( ( STAR | SLASH | PERCENT ) cast_expression )*
argument_expression_list
         ::= assignment_expression ( COMMA assignment_expression )*
assignment_expression
         ::= ( unary_expression ( EQ | STAR_EQ | SLASH_EQ | PERCENT_EQ | PLUS_EQ | MINUS_EQ | LTLT_EQ | GTGT_EQ | AMPERSAND_EQ | CARET_EQ | BAR_EQ ) )* conditional_expression
condition
         ::= expression
expression
         ::= embedded_expression
embedded_expression
         ::= ( expression COMMA )? assignment_expression
initializer
         ::= assignment_expression
           | LBRACE initializer_list? RBRACE
initializer_list
         ::= initializer_list_items COMMA?
initializer_list_items
         ::= ( initializer | designated_initializer ) ( COMMA ( initializer | designated_initializer ) )*
designated_initializer
         ::= designation initializer
designation
         ::= ( LBRACKET constant_expression RBRACKET | DOT name | designated_range ) ( LBRACKET constant_expression RBRACKET | DOT name )* EQ
           | name COLON
designated_range
         ::= LBRACKET constant_expression DOTS constant_expression RBRACKET
constant_expression
         ::= conditional_expression
conditional_expression
         ::= logical_or_expression ( QMARK embedded_expression? COLON logical_or_expression )*
logical_or_expression
         ::= logical_and_expression ( OR logical_and_expression )*
logical_and_expression
         ::= inclusive_or_expression ( AND inclusive_or_expression )*
inclusive_or_expression
         ::= exclusive_or_expression ( BAR exclusive_or_expression )*
exclusive_or_expression
         ::= and_expression ( CARET and_expression )*
and_expression
         ::= equality_expression ( AMPERSAND equality_expression )*
equality_expression
         ::= relational_expression ( ( EQEQ | NE ) relational_expression )*
relational_expression
         ::= shift_expression ( ( LT | GT | LE | GE ) shift_expression )*
shift_expression
         ::= additive_expression ( ( LTLT | GTGT ) additive_expression )*
additive_expression
         ::= multiplicative_expression ( ( PLUS | MINUS ) multiplicative_expression )*
assembler_instructions
         ::= ASM ( VOLATILE? LPAREN assembler_spec | GOTO LPAREN asm_goto_spec ) RPAREN
assembler_spec
         ::= string_literal ( COLON asm_operands ( COLON asm_operands ( COLON asm_clobbered_objects )? )? )?
asm_goto_spec
         ::= string_literal COLON asm_operands COLON asm_operands COLON asm_clobbered_objects COLON identifier_list
asm_operands
         ::= ( asm_operand ( COMMA asm_operand )* )?
asm_operand
         ::= string_literal ( LPAREN expression RPAREN )?
           | LBRACKET identifier RBRACKET string_literal LPAREN expression RPAREN
asm_clobbered_objects
         ::= ( asm_clobbered_object ( COMMA asm_clobbered_object )* )?
asm_clobbered_object
         ::= string_literal
asm_labeled_declarator
         ::= declarator ASM LPAREN string_literal RPAREN
declaration
         ::= declaration_specifiers init_declarator_list? SEMICOLON
extended_declaration
         ::= symtab_open extended_declaration_specifiers init_declarator_list? SEMICOLON symtab_close
declaration_specifiers
         ::= ( storage_class_specifier | type_qualifier | function_specifier )* ( type_specifier ( storage_class_specifier | type_specifier | type_qualifier | function_specifier )* | singular_type_specifier restricted_declaration_specifiers_list? )
extended_declaration_specifiers
         ::= ( storage_class_specifier | type_qualifier | function_specifier | attribute_specifier )* ( type_specifier ( storage_class_specifier | type_specifier | type_qualifier | function_specifier | attribute_specifier )* | singular_type_specifier ( storage_class_specifier | type_qualifier | function_specifier | attribute_specifier )* )
restricted_declaration_specifiers
         ::= restricted_declaration_specifiers_list
restricted_declaration_specifiers_list
         ::= ( storage_class_specifier | type_qualifier | function_specifier )+
storage_class_specifier
         ::= TYPEDEF
           | EXTERN
           | STATIC
           | AUTO
           | REGISTER
type_specifier
         ::= CHAR
           | SHORT
           | INT
           | LONG
           | FLOAT
           | DOUBLE
           | SIGNED
           | UNSIGNED
           | _COMPLEX_T
           | _IMAGINARY_T
singular_type_specifier
         ::= VOID
           | _BOOL_T
           | struct_or_union_specifier
           | enum_specifier
           | typedef_name
           | TYPEOF LPAREN ( expression | type_name ) RPAREN
function_specifier
         ::= INLINE
type_qualifier
         ::= CONST
           | RESTRICT
           | VOLATILE
struct_or_union_specifier
         ::= STRUCT ( LBRACE opt_struct_declaration_list RBRACE | struct_name ( LBRACE opt_struct_declaration_list RBRACE )? )
           | UNION ( LBRACE opt_struct_declaration_list RBRACE | union_name ( LBRACE opt_struct_declaration_list RBRACE )? )
           | struct_or_union_specifier_with_attributes
struct_or_union_specifier_with_attributes
         ::= ( STRUCT attribute_specifier_list struct_name? | UNION attribute_specifier_list union_name? ) LBRACE opt_struct_declaration_list RBRACE
struct_name
         ::= name
union_name
         ::= name
enum_specifier
         ::= ENUM ( LBRACE enumerator_list RBRACE | enum_name ( LBRACE enumerator_list RBRACE )? )
           | enum_specifier_with_attributes
enum_specifier_with_attributes
         ::= ENUM attribute_specifier_list enum_name? LBRACE enumerator_list RBRACE
enum_name
         ::= name
opt_struct_declaration_list
         ::= semicolons struct_declaration_list?
struct_declaration_list
         ::= ( struct_declaration semicolons )+
struct_declaration
         ::= ( specifier_qualifier_list struct_declarator_list | struct_or_union_specifier ) SEMICOLON
type_name
         ::= specifier_qualifier_list abstract_declarator?
specifier_qualifier_list
         ::= type_qualifier* ( type_specifier ( type_specifier | type_qualifier )* | singular_type_specifier type_qualifier* )
struct_declarator_list
         ::= struct_declarator ( COMMA struct_declarator )*
struct_declarator
         ::= declarator ( COLON constant_expression )?
           | COLON constant_expression
enumerator_list
         ::= enumerator_list_items COMMA?
enumerator_list_items
         ::= enumerator ( COMMA enumerator )*
enumerator
         ::= enumeration_constant ( EQ constant_expression )?
enumeration_constant
         ::= identifier
init_declarator_list
         ::= init_declarator ( COMMA extended_init_declarator )*
init_declarator
         ::= ( declarator | asm_labeled_declarator ) ( EQ initializer )?
           | init_declarator_with_attributes
init_declarator_with_attributes
         ::= asm_labeled_declarator attribute_specifier_list ( EQ initializer )?
extended_init_declarator
         ::= ( extended_declarator | asm_labeled_declarator ) ( EQ initializer )?
declarator
         ::= pointer? direct_declarator
extended_declarator
         ::= pointer? direct_declarator
           | declarator_with_attributes
declarator_with_attributes
         ::= attribute_specifier_list pointer? direct_declarator
restricted_declarator
         ::= pointer? restricted_direct_declarator
direct_declarator
         ::= ( LPAREN extended_declarator RPAREN | identifier | typedef_name | direct_declarator_with_attributes ) ( LBRACKET ( ( STATIC type_qualifier_list? )? assignment_expression | STAR | type_qualifier_list ( STATIC? assignment_expression | STAR )? )? RBRACKET | LPAREN ( parameter_type_list | identifier_list )? RPAREN )*
direct_declarator_with_attributes
         ::= ( direct_declarator LPAREN ( parameter_type_list | identifier_list )? RPAREN | identifier ) attribute_specifier_list
regular_direct_declarator
         ::= ( LPAREN extended_declarator RPAREN | identifier ) ( LBRACKET ( ( STATIC type_qualifier_list? )? assignment_expression | STAR | type_qualifier_list ( STATIC? assignment_expression | STAR )? )? RBRACKET | LPAREN ( parameter_type_list | identifier_list )? RPAREN )*
restricted_direct_declarator
         ::= identifier
           | typedef_name
           | LPAREN pointer restricted_direct_declarator RPAREN
           | restricted_direct_declarator ( LBRACKET ( ( STATIC type_qualifier_list? )? assignment_expression | STAR | type_qualifier_list ( STATIC? assignment_expression | STAR )? )? RBRACKET | LPAREN ( parameter_type_list | identifier_list )? RPAREN )
           | restricted_direct_declarator_with_attributes
restricted_direct_declarator_with_attributes
         ::= ( restricted_direct_declarator LPAREN ( parameter_type_list | identifier_list )? RPAREN | identifier ) attribute_specifier_list
pointer  ::= ( STAR type_qualifier_and_attribute_specifier_list? )+
type_qualifier_list
         ::= type_qualifier+
type_qualifier_and_attribute_specifier_list
         ::= ( type_qualifier | attribute_specifier )+
parameter_type_list
         ::= parameter_list ( COMMA DOTS )?
parameter_list
         ::= parameter_declaration ( COMMA parameter_declaration )*
parameter_declaration
         ::= extended_declaration_specifiers ( restricted_declarator | abstract_declarator )?
abstract_declarator
         ::= pointer direct_abstract_declarator?
           | direct_abstract_declarator
direct_abstract_declarator
         ::= ( LPAREN ( abstract_declarator | parameter_type_list )? RPAREN | LBRACKET ( assignment_expression | STAR )? RBRACKET ) ( LBRACKET ( assignment_expression | STAR )? RBRACKET | LPAREN parameter_type_list? RPAREN )*
identifier_list
         ::= identifier ( COMMA identifier )*
statement
         ::= labeled_statement
           | compound_statement
           | expression_statement
           | if_statement
           | switch_or_iteration_statement
           | jump_statement
switch_or_iteration_statement
         ::= iteration_statement
           | switch_statement
labeled_statement
         ::= ( identifier | DEFAULT | CASE constant_expression ( DOTS constant_expression )? ) COLON statement
           | labeled_statement_with_attributes
labeled_statement_with_attributes
         ::= identifier COLON attribute_specifier_list statement
compound_statement
         ::= LBRACE block_item* RBRACE
block_item
         ::= extended_declaration
           | statement
           | std_function_definition
expression_statement
         ::= expression? SEMICOLON
if_statement
         ::= IF LPAREN condition RPAREN statement ( ELSE statement )?
switch_statement
         ::= SWITCH LPAREN expression RPAREN statement
iteration_statement
         ::= ( WHILE LPAREN condition | FOR LPAREN ( expression? SEMICOLON | extended_declaration ) condition? SEMICOLON expression? ) RPAREN statement
           | DO statement WHILE LPAREN condition RPAREN SEMICOLON
jump_statement
         ::= ( GOTO identifier | CONTINUE | BREAK | RETURN expression? ) SEMICOLON
           | computed_goto
computed_goto
         ::= GOTO STAR embedded_expression SEMICOLON
constant ::= integer_constant
           | floating_constant
           | character_constant
integer_constant
         ::= DECIMAL_CONSTANT
           | OCTAL_CONSTANT
           | HEXADECIMAL_CONSTANT
character_constant
         ::= CHAR_CONSTANT
floating_constant
         ::= DECIMAL_FLOATING_CONSTANT
           | HEXADECIMAL_FLOATING_CONSTANT
typedef_name
         ::= TYPE_IDENT
identifier
         ::= IDENT
name     ::= IDENT
           | TYPE_IDENT
string_literal
         ::= STRING_LITERAL+
attribute_specifier_list
         ::= attribute_specifier+
attribute_specifier
         ::= ATTRIBUTE LPAREN LPAREN attribute_list RPAREN RPAREN
attribute_list
         ::= attribute ( COMMA attribute )*
attribute
         ::= ( attribute_name ( LPAREN attribute_parameter ( COMMA attribute_parameter )* RPAREN )? )?
attribute_name
         ::= IDENT
           | CONST
attribute_parameter
         ::= assignment_expression

// Tokens from https://github.com/afborchert/astl-c/blob/27e8ed50fdd0336e3d9bd9cd58b50959723ab2bd/astl-c/operators.txt

//# keywords
ALIGNOF ::= "alignof"
AUTO ::= "auto"
BREAK ::= "break"
CASE ::= "case"
CHAR ::= "char"
CONST ::= "const"
CONTINUE ::= "continue"
DEFAULT ::= "default"
DO ::= "do"
DOUBLE ::= "double"
ELSE ::= "else"
ENUM ::= "enum"
EXTERN ::= "extern"
FLOAT ::= "float"
FOR ::= "for"
GOTO ::= "goto"
IF ::= "if"
INLINE ::= "inline"
INT ::= "int"
LONG ::= "long"
REGISTER ::= "register"
RESTRICT ::= "restrict"
RETURN ::= "return"
SHORT ::= "short"
SIGNED ::= "signed"
SIZEOF ::= "sizeof"
STATIC ::= "static"
STRUCT ::= "struct"
SWITCH ::= "switch"
TYPEDEF ::= "typedef"
UNION ::= "union"
UNSIGNED ::= "unsigned"
VOID ::= "void"
VOLATILE ::= "volatile"
WHILE ::= "while"
_BOOL_T ::= "_Bool"
_COMPLEX_T ::= "_Complex"
_IMAGINARY_T ::= "_Imaginary"

//# gcc extensions
TYPEOF ::= "typeof"

//# operators and delimiters
LBRACKET ::= "["
RBRACKET ::= "]"
LPAREN ::= "("
RPAREN ::= ")"
LBRACE ::= "{"
RBRACE ::= "}"
DOT ::= "."
ARROW ::= "->"
postfix_plusplus ::= "postfix++"
postfix_minusminus ::= "postfix--"
prefix_plusplus ::= "prefix++"
prefix_minusminus ::= "prefix--"
unary_plus ::= "unary+"
unary_minus ::= "unary-"
AMPERSAND ::= "&"
STAR ::= "*"
PLUS ::= "+"
MINUS ::= "-"
TILDE ::= "~"
EXCLAMATION ::= "!"
SLASH ::= "/"
PERCENT ::= "%"
LTLT ::= "<<"
GTGT ::= ">>"
LT ::= "<"
GT ::= ">"
LE ::= "<="
GE ::= ">="
EQEQ ::= "=="
NE ::= "!="
CARET ::= "^"
BAR ::= "|"
AND ::= "&&"
OR ::= "||"
QMARK ::= "?"
COLON ::= ":"
SEMICOLON ::= ";"
DOTS ::= "..."
EQ ::= "="
STAR_EQ ::= "*="
SLASH_EQ ::= "/="
PERCENT_EQ ::= "%="
PLUS_EQ ::= "+="
MINUS_EQ ::= "-="
LTLT_EQ ::= "<<="
GTGT_EQ ::= ">>="
AMPERSAND_EQ ::= "&="
CARET_EQ ::= "^="
BAR_EQ ::= "|="
COMMA ::= ","
HASH ::= "#"
HASH_HASH ::= "##"
LT_COLON ::= "<:"
COLON_GT ::= ">"
LT_PERCENT ::= "<%"
PERCENT_GT ::= "%>"
PERCENT_COLON ::= "%:"
PERCENT_COLON_PERCENT_COLON ::= "%:%:"
va_arg_macro ::= "va_arg"
mingodad commented 3 years ago

And here is the EBNF for astl/parser.ypp:

/*
From https://raw.githubusercontent.com/afborchert/astl/master/astl/parser.ypp
*/

/* converted on Sun Jul 18, 2021, 18:02 (UTC+02) by bison-to-w3c v0.53 which is Copyright (c) 2011-2021 by Gunther Rademacher <grd@gmx.net> */

start    ::= unit
unit     ::= opt_clauses opt_rules
opt_clauses
         ::= clause*
clause   ::= import_clause
           | library_clause
           | operator_set_clause
import_clause
         ::= IMPORT IDENT SEMICOLON
library_clause
         ::= LIBRARY STRING_LITERAL SEMICOLON
operator_set_clause
         ::= OPSET IDENT EQ operator_expression SEMICOLON
opt_rules
         ::= rule*
rule     ::= print_rules
           | named_print_rules
           | operator_rules
           | transformation_rules
           | named_transformation_rules
           | named_inplace_transformation_rules
           | attribution_rules
           | named_attribution_rules
           | function_definition
           | state_machine
           | abstract_state_machine
function_definition
         ::= SUB IDENT parameter_list? block
parameter_list
         ::= LPAREN ( IDENT ( COMMA IDENT )* )? RPAREN
print_rules
         ::= PRINT RULES LBRACE sequence_of_print_rules RBRACE
named_print_rules
         ::= PRINT RULES IDENT LBRACE sequence_of_print_rules RBRACE
sequence_of_print_rules
         ::= print_rule+
print_rule
         ::= conditional_tree_expression ARROW print_expression
named_tree_expression
         ::= tree_expression ( AS IDENT )?
tree_expression
         ::= LPAREN operator_expression subnodes? RPAREN
           | variable_length_tree_expression
variable_length_tree_expression
         ::= LPAREN operator_expression ( STAR | subnodes? subnode_list subnodes? ) RPAREN
operator_expression
         ::= string_literal
           | IDENT
           | LBRACKET operators RBRACKET
conditional_tree_expression
         ::= contextual_tree_expression ( WHERE expression )?
contextual_tree_expression
         ::= named_tree_expression ( NOT? IN context_expression )?
context_expression
         ::= context_match ( AND NOT? IN context_match )*
context_match
         ::= named_tree_expression
subnodes ::= subnode+
subnode  ::= named_tree_expression
           | regular_expression
           | string_literal
           | IDENT
subnode_list
         ::= IDENT DOTS
regular_expression
         ::= REGEXP_LITERAL ( AS IDENT )?
assignment
         ::= ( designator ( EQ | AMP_EQ | PLUS_EQ | MINUS_EQ ) )* conditional
conditional
         ::= term ( QMARK term COLON term )?
term     ::= factor
           | term ( ( OR | AND | AMPERSAND | X | EQEQ | NE | LT | LE | GE | GT | PLUS | MINUS | DIV | MOD | STAR | POWER ) term | MATCHES ( REGEXP_LITERAL | term ) )
factor   ::= ( MINUS | NOT )? primary
primary  ::= designator
           | EXISTS ( designator | LPAREN designator RPAREN )
           | prefix_increment
           | prefix_decrement
           | postfix_increment
           | postfix_decrement
           | LPAREN assignment RPAREN
           | list_aggregate
           | dictionary_aggregate
           | tree_constructor
           | function_call
           | function_constructor
           | CARDINAL_LITERAL
           | STRING_LITERAL
           | NULL_T
prefix_increment
         ::= PLUSPLUS designator
prefix_decrement
         ::= MINUSMINUS designator
postfix_increment
         ::= designator PLUSPLUS
postfix_decrement
         ::= designator MINUSMINUS
list_aggregate
         ::= LBRACKET expression_list? RBRACKET
dictionary_aggregate
         ::= LBRACE ( key_value_pairs COMMA? )? RBRACE
tree_constructor
         ::= LEYE STRING_LITERAL subnodes_constructor? REYE
key_value_pairs
         ::= key_value_pair ( COMMA key_value_pair )*
key_value_pair
         ::= ( IDENT | STRING_LITERAL ) ARROW expression
function_call
         ::= primary LPAREN expression_list? RPAREN
function_constructor
         ::= SUB parameter_list? block
expression_list
         ::= expression ( COMMA expression )*
print_expression
         ::= print_expression_item*
print_expression_item
         ::= TEXT_LITERAL
           | VARIABLE
           | LBRACE expression RBRACE
           | print_expression_listvar
print_expression_listvar
         ::= DOTS
operator_rules
         ::= OPERATORS LBRACE ( operator_list SEMICOLON )+ RBRACE
operator_list
         ::= ( LEFT | RIGHT | NONASSOC ) operators
operators
         ::= operator_term+
operator_term
         ::= string_literal
           | IDENT
transformation_rules
         ::= TRANSFORMATION RULES LBRACE transformations RBRACE
named_transformation_rules
         ::= TRANSFORMATION RULES IDENT LBRACE transformations RBRACE
named_inplace_transformation_rules
         ::= INPLACE TRANSFORMATION RULES IDENT LBRACE transformations RBRACE
transformations
         ::= transformation+
transformation
         ::= ( IDENT COLON )? conditional_tree_expression ARROW ( PRE | POST )? transformation_instructions
transformation_instructions
         ::= pre_transformation_block? subnode_constructor post_transformation_block?
pre_transformation_block
         ::= block
post_transformation_block
         ::= block
subnode_constructor
         ::= IDENT DOTS?
           | named_tree_expression_constructor
           | named_expression
named_expression
         ::= LBRACE expression RBRACE DOTS? ( AS IDENT )?
named_tree_expression_constructor
         ::= tree_expression_constructor ( AS IDENT )?
tree_expression_constructor
         ::= LPAREN STRING_LITERAL subnodes_constructor? RPAREN
subnodes_constructor
         ::= subnode_constructor+
attribution_rules
         ::= ATTRIBUTION RULES LBRACE attributions RBRACE
named_attribution_rules
         ::= ATTRIBUTION RULES IDENT LBRACE attributions RBRACE
attributions
         ::= attribution+
attribution
         ::= conditional_tree_expression ARROW ( PRE | POST )? block
block    ::= LBRACE statement* RBRACE
statement
         ::= ( ( expression | delete_statement | var_statement | return_statement ) SEMICOLON | if_statement | while_statement | foreach_statement ) SEMICOLON*
delete_statement
         ::= DELETE designator
if_statement
         ::= IF LPAREN expression RPAREN block elsif_chain? ( ELSE block )?
elsif_chain
         ::= elsif_statement+
elsif_statement
         ::= ELSIF LPAREN expression RPAREN block
while_statement
         ::= WHILE LPAREN expression RPAREN block
foreach_statement
         ::= FOREACH ( IDENT | LPAREN IDENT COMMA IDENT RPAREN ) IN LPAREN expression RPAREN block
var_statement
         ::= VAR IDENT ( EQ expression )?
return_statement
         ::= RETURN expression?
designator
         ::= IDENT ( DOT IDENT | LBRACE expression RBRACE | LBRACKET expression RBRACKET )*
expression
         ::= assignment
abstract_state_machine
         ::= ABSTRACT STATE MACHINE IDENT ( COLON IDENT )? LBRACE sm_vars sm_functions sm_rules RBRACE
state_machine
         ::= STATE MACHINE IDENT ( COLON IDENT )? LPAREN states RPAREN LBRACE sm_vars sm_functions sm_rules RBRACE
states   ::= IDENT ( COMMA IDENT )*
sm_vars  ::= ( sm_var_declaration SEMICOLON )*
sm_var_declaration
         ::= ( SHARED | PRIVATE ) VAR IDENT ( EQ expression )?
sm_functions
         ::= function_definition*
sm_rules ::= sm_rule+
sm_rule  ::= sm_condition ( ARROW ( sm_block | CREATE block ) | sm_alternative+ )
           | ON CLOSE sm_handler
sm_handler
         ::= ( WHEN sm_state_condition )? ARROW block
sm_condition
         ::= conditional_tree_expression ( AT cfg_node_expression )?
           | AT cfg_node_expression
cfg_node_expression
         ::= ( cfg_node_types | STAR ) ( WHERE expression )?
cfg_node_types
         ::= IDENT ( OR IDENT )*
sm_block ::= block
           | sm_action block?
sm_alternative
         ::= ( WHEN sm_state_condition | IF cfg_edge_condition ( AND WHEN sm_state_condition )? ) ARROW sm_block
cfg_edge_condition
         ::= IDENT ( OR IDENT )*
sm_state_condition
         ::= IDENT ( OR IDENT )*
sm_action
         ::= CACHE LPAREN expression RPAREN
           | CLOSE
           | CUT
           | RETRACT
           | IDENT
string_literal
         ::= STRING_LITERAL

// Tokens from https://github.com/afborchert/astl/blob/master/astl/operators.txt

//# keywords
ABSTRACT ::= "abstract"
AND ::= "and"
AS ::= "as"
AT ::= "at"
ATTRIBUTION ::= "attribution"
CACHE ::= "cache"
CREATE ::= "create"
CLOSE ::= "close"
CUT ::= "cut"
DELETE ::= "delete"
DIV ::= "div"
ELSE ::= "else"
ELSIF ::= "elsif"
EXISTS ::= "exists"
FOREACH ::= "foreach"
IF ::= "if"
IMPORT ::= "import"
IN ::= "in"
INPLACE ::= "inplace"
LEFT ::= "left"
LIBRARY ::= "library"
MACHINE ::= "machine"
MOD ::= "mod"
NONASSOC ::= "nonassoc"
NULL_T ::= "null"
ON ::= "on"
OPERATORS ::= "operators"
OPSET ::= "opset"
OR ::= "or"
POST ::= "post"
PRE ::= "pre"
PRINT ::= "print"
PRIVATE ::= "private"
RETRACT ::= "retract"
RIGHT ::= "right"
RETURN ::= "return"
RULES ::= "rules"
SHARED ::= "shared"
STATE ::= "state"
SUB ::= "sub"
TRANSFORMATION ::= "transformation"
VAR ::= "var"
WHERE ::= "where"
WHEN ::= "when"
WHILE ::= "while"
X ::= "x"

//# operators and delimiters
MATCHES ::= "=~"
AMPERSAND ::= "&"
LT ::= "<"
GT ::= ">"
LE ::= "<="
GE ::= ">="
EQEQ ::= "=="
NE ::= "!="
EQEQ ::= "=="
PLUS ::= "+"
MINUS ::= "-"
STAR ::= "*"
POWER ::= "^"
LBRACKET ::= "["
RBRACKET ::= "]"
LPAREN ::= "("
RPAREN ::= ")"
LBRACE ::= "{"
RBRACE ::= "}"
DOT ::= "."
ARROW ::= "->"
EQ ::= "="
AMP_EQ ::= "&="
PLUS_EQ ::= "+="
MINUS_EQ ::= "-="
COMMA ::= ","
DOTS ::= "..."

prefix_increment ::= "prefix++"
prefix_decrement ::= "prefix--"
postfix_increment ::= "postfix++"
postfix_decrement ::= "postfix--"