synth/tools/cc.ebnf
2021-03-20 21:25:01 -07:00

161 lines
5.1 KiB
EBNF

start: top_level*
?top_level: fun_decl
| global_var
| fun_def
| struct_def
| typedef
fun_decl: fun_prot ";"
fun_prot: type symbol "(" [fun_param ("," fun_param)*] ")"
fun_param: type [symbol]
global_var: type symbol sized_array* empty_array? [ "=" literal ] ";"
fun_def: fun_prot body
typedef: "typedef" type IDENTIFIER ";"
body: "{" statement* "}"
statement: if_stat
| while_stat
| for_stat
| do_while_stat
| "break" ";" -> break
| "continue" ";" -> continue
| "goto" label ";" -> goto // yay \o/
| "return" expression ";" -> return_stat
| local_var ";"
| local_array
| expression ";"
| body
if_stat: "if" "(" expression ")" statement ["else" statement]
while_stat: "while" "(" expression ")" statement
for_stat: "for" "(" local_var? ";" expression? ";" iter_expression? ")" statement
do_while_stat: "do" statement "while" "(" expression ")" statement
iter_expression: expression
local_var: type symbol initializer?
local_array: type symbol sized_array* (sized_array | empty_array) initializer? ";"
empty_array: "[" "]"
sized_array: "[" array_size "]"
initializer: "=" (expression | initializer_list)
initializer_list: "{" [init_list_field ("," init_list_field)* ","? ] "}"
?init_list_field: "." field "=" expression
| expression
// precedence from https://en.cppreference.com/w/c/language/operator_precedence
?expression: comma_expr
?comma_expr: prec14_expr
| comma_expr "," prec14_expr
?prec14_expr: prec13_expr
| prec2_expr "=" prec14_expr -> assignment
| prec2_expr "+=" prec14_expr
| prec2_expr "-=" prec14_expr
| prec2_expr "*=" prec14_expr
| prec2_expr "/=" prec14_expr
| prec2_expr "%=" prec14_expr
| prec2_expr "<<=" prec14_expr
| prec2_expr ">>=" prec14_expr
| prec2_expr "&=" prec14_expr
| prec2_expr "^=" prec14_expr
| prec2_expr "|=" prec14_expr -> or_ass
?prec13_expr: prec12_expr
| prec12_expr "?" prec13_expr ":" prec13_expr
?prec12_expr: prec11_expr
| prec12_expr "||" prec11_expr
?prec11_expr: prec10_expr
| prec11_expr "&&" prec10_expr
?prec10_expr: prec9_expr
| prec10_expr "|" prec9_expr -> _or
?prec9_expr: prec8_expr
| prec9_expr "^" prec8_expr
?prec8_expr: prec7_expr
| prec8_expr "&" prec7_expr -> _and // reserved work in python
?prec7_expr: prec6_expr
| prec7_expr "==" prec6_expr -> eq
| prec7_expr "!=" prec6_expr -> neq
?prec6_expr: prec5_expr
| prec6_expr "<" prec5_expr -> lt
| prec6_expr "<=" prec5_expr -> lte
| prec6_expr ">" prec5_expr -> gt
| prec6_expr ">=" prec5_expr -> gte
?prec5_expr: prec4_expr
| prec5_expr "<<" prec4_expr -> shl
| prec5_expr ">>" prec4_expr -> shr
?prec4_expr: prec3_expr
| prec4_expr "+" prec3_expr -> add
| prec4_expr "-" prec3_expr -> su
?prec3_expr: prec2_expr
| prec3_expr "*" prec2_expr -> mul
| prec3_expr "/" prec2_expr -> div
| prec3_expr "%" prec2_expr -> mod
?prec2_expr: prec1_expr
| "++" prec2_expr -> pre_increment
| "--" prec2_expr -> pre_decrement
| "+" prec2_expr
| "-" prec2_expr
| "!" prec2_expr -> bool_not
| "~" prec2_expr
| "(" type ")" prec2_expr -> cast
| "*" prec2_expr -> dereference
| "&" prec2_expr -> address_of
| "sizeof" prec2_expr -> sizeof
?prec1_expr: literal
| identifier
| "(" expression ")"
| prec1_expr "++" -> post_increment
| prec1_expr "--" -> post_decrement
| prec1_expr "(" expression? ")" -> fun_call
| prec1_expr "[" expression "]" -> array_item
| prec1_expr "." field -> field_access
| prec1_expr "->" field -> pointer_access
label: IDENTIFIER
literal: SIGNED_NUMBER | ESCAPED_STRING | HEX_LITTERAL | CHARACTER
field: IDENTIFIER
identifier: IDENTIFIER
?symbol: IDENTIFIER
type: type_qualifier* IDENTIFIER
| struct_type
| type "*" -> pointer
?array_size: INT
?type_qualifier: "volatile" -> volatile
| "const" -> const
| "static" -> static
| "extern" -> extern
struct_type: "struct" (IDENTIFIER | IDENTIFIER? struct_body)
struct_def: "struct" IDENTIFIER struct_body ";"
struct_body: "{" struct_field* "}"
struct_field: type IDENTIFIER sized_array* ";"
IDENTIFIER: /[_a-zA-Z]\w*/
COMMENT: /\/\/.*/
HEX_LITTERAL: /0x[a-fA-F0-9]+/
CHARACTER: /'([^']|\\n|\\r|\\0|\\t)'/
%import common.WS
%import common.CNAME
%import common.C_COMMENT
%import common.SIGNED_NUMBER
%import common.INT
%import common.ESCAPED_STRING
%ignore COMMENT
%ignore C_COMMENT
%ignore WS