|
|
@ -0,0 +1,609 @@ |
|
|
|
|
|
const PREC = { |
|
|
|
|
|
ASSIGNMENT: -1, |
|
|
|
|
|
CONDITIONAL: -2, |
|
|
|
|
|
DEFAULT: 0, |
|
|
|
|
|
LOGICAL_OR: 1, |
|
|
|
|
|
LOGICAL_AND: 2, |
|
|
|
|
|
INCLUSIVE_OR: 3, |
|
|
|
|
|
EXCLUSIVE_OR: 4, |
|
|
|
|
|
BITWISE_AND: 5, |
|
|
|
|
|
EQUAL: 6, |
|
|
|
|
|
RELATIONAL: 7, |
|
|
|
|
|
SIZEOF: 8, |
|
|
|
|
|
SHIFT: 9, |
|
|
|
|
|
ADD: 10, |
|
|
|
|
|
MULTIPLY: 11, |
|
|
|
|
|
CALL: 12, |
|
|
|
|
|
CAST: 13, |
|
|
|
|
|
UNARY: 14, |
|
|
|
|
|
FIELD: 15, |
|
|
|
|
|
SUBSCRIPT: 16, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
module.exports = grammar({ |
|
|
|
|
|
name: 'c', |
|
|
|
|
|
|
|
|
|
|
|
extras: $ => [ |
|
|
|
|
|
/\s/, |
|
|
|
|
|
$.comment, |
|
|
|
|
|
], |
|
|
|
|
|
|
|
|
|
|
|
conflicts: $ => [ |
|
|
|
|
|
[$._type_specifier, $._expression], |
|
|
|
|
|
[$._type_specifier, $.direct_declarator], |
|
|
|
|
|
[$.sizeof_expression, $.cast_expression], |
|
|
|
|
|
], |
|
|
|
|
|
|
|
|
|
|
|
rules: { |
|
|
|
|
|
translation_unit: $ => repeat(choice( |
|
|
|
|
|
$._preproc_statement, |
|
|
|
|
|
$.function_definition, |
|
|
|
|
|
$.declaration |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
// Preprocesser
|
|
|
|
|
|
|
|
|
|
|
|
_preproc_statement: $ => choice( |
|
|
|
|
|
$.preproc_ifdef, |
|
|
|
|
|
$.preproc_include, |
|
|
|
|
|
$.preproc_def, |
|
|
|
|
|
$.preproc_function_def, |
|
|
|
|
|
$.preproc_call |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_include: $ => seq( |
|
|
|
|
|
'#include', |
|
|
|
|
|
choice( |
|
|
|
|
|
$.string_literal, |
|
|
|
|
|
$.system_lib_string |
|
|
|
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_def: $ => seq( |
|
|
|
|
|
'#define', |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
optional($.preproc_arg), |
|
|
|
|
|
'\n' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_function_def: $ => seq( |
|
|
|
|
|
'#define', |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
$.preproc_params, |
|
|
|
|
|
optional($.preproc_arg), |
|
|
|
|
|
'\n' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_params: $ => seq( |
|
|
|
|
|
'(', commaSep(choice($.identifier, '...')), ')' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_call: $ => seq( |
|
|
|
|
|
$.preproc_directive, |
|
|
|
|
|
$.preproc_arg |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_arg: $ => token(prec(-1, repeat1(choice(/./, '\\\n')))), |
|
|
|
|
|
|
|
|
|
|
|
preproc_ifdef: $ => seq( |
|
|
|
|
|
choice('#ifdef', '#ifndef'), |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
err(repeat(choice( |
|
|
|
|
|
$._preproc_statement, |
|
|
|
|
|
$.function_definition, |
|
|
|
|
|
$.declaration |
|
|
|
|
|
))), |
|
|
|
|
|
optional($.preproc_else), |
|
|
|
|
|
'#endif' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_else: $ => seq( |
|
|
|
|
|
'#else', |
|
|
|
|
|
repeat(choice( |
|
|
|
|
|
$._preproc_statement, |
|
|
|
|
|
$.function_definition, |
|
|
|
|
|
$.declaration |
|
|
|
|
|
)) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
preproc_directive: $ => (/#\a\w*/), |
|
|
|
|
|
|
|
|
|
|
|
// Main Grammar
|
|
|
|
|
|
|
|
|
|
|
|
function_definition: $ => seq( |
|
|
|
|
|
optional($._declaration_specifiers), |
|
|
|
|
|
$._type_specifier, |
|
|
|
|
|
$._declarator, |
|
|
|
|
|
$.compound_statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
declaration: $ => seq( |
|
|
|
|
|
err(seq( |
|
|
|
|
|
optional($._declaration_specifiers), |
|
|
|
|
|
$._type_specifier, |
|
|
|
|
|
commaSep(choice( |
|
|
|
|
|
$._declarator, |
|
|
|
|
|
$.init_declarator)))), |
|
|
|
|
|
';'), |
|
|
|
|
|
|
|
|
|
|
|
_declaration_specifiers: $ => repeat1(choice( |
|
|
|
|
|
$.storage_class_specifier, |
|
|
|
|
|
$.type_qualifier, |
|
|
|
|
|
$.function_specifier |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
_declarator: $ => choice( |
|
|
|
|
|
$.pointer_declarator, |
|
|
|
|
|
$.function_declarator, |
|
|
|
|
|
$.array_declarator, |
|
|
|
|
|
seq('(', $._declarator, ')'), |
|
|
|
|
|
$.identifier |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
_abstract_declarator: $ => choice( |
|
|
|
|
|
$.abstract_pointer_declarator, |
|
|
|
|
|
$.abstract_function_declarator, |
|
|
|
|
|
$.abstract_array_declarator, |
|
|
|
|
|
prec(1, seq('(', $._abstract_declarator, ')')) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
pointer_declarator: $ => seq( |
|
|
|
|
|
'*', $._declarator |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
abstract_pointer_declarator: $ => seq( |
|
|
|
|
|
'*', |
|
|
|
|
|
optional($._abstract_declarator) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
function_declarator: $ => prec(1, seq( |
|
|
|
|
|
$._declarator, |
|
|
|
|
|
'(', |
|
|
|
|
|
optional($.parameter_type_list), |
|
|
|
|
|
')' |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
abstract_function_declarator: $ => prec(1, seq( |
|
|
|
|
|
$._abstract_declarator, |
|
|
|
|
|
'(', |
|
|
|
|
|
optional($.parameter_type_list), |
|
|
|
|
|
')' |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
array_declarator: $ => prec(1, seq( |
|
|
|
|
|
$._declarator, |
|
|
|
|
|
'[', |
|
|
|
|
|
choice( |
|
|
|
|
|
seq(optional('static'), repeat($.type_qualifier), optional($._expression)), |
|
|
|
|
|
seq(repeat($.type_qualifier), 'static', $._expression) |
|
|
|
|
|
), |
|
|
|
|
|
']' |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
abstract_array_declarator: $ => prec(1, seq( |
|
|
|
|
|
optional($._abstract_declarator), |
|
|
|
|
|
'[', |
|
|
|
|
|
choice( |
|
|
|
|
|
seq(optional('static'), repeat($.type_qualifier), optional($._expression)), |
|
|
|
|
|
seq(repeat($.type_qualifier), 'static', $._expression) |
|
|
|
|
|
), |
|
|
|
|
|
']' |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
init_declarator: $ => seq( |
|
|
|
|
|
$._declarator, |
|
|
|
|
|
'=', |
|
|
|
|
|
choice($.initializer_list, $._expression) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
compound_statement: $ => seq( |
|
|
|
|
|
'{', |
|
|
|
|
|
err(repeat(choice($.declaration, $._statement))), |
|
|
|
|
|
'}' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
storage_class_specifier: $ => choice( |
|
|
|
|
|
'typedef', |
|
|
|
|
|
'extern', |
|
|
|
|
|
'static' , |
|
|
|
|
|
'auto', |
|
|
|
|
|
'register' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
type_qualifier: $ => choice( |
|
|
|
|
|
'const', |
|
|
|
|
|
'restrict', |
|
|
|
|
|
'volatile' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
function_specifier: $ => 'inline', |
|
|
|
|
|
|
|
|
|
|
|
_type_specifier: $ => choice( |
|
|
|
|
|
$.struct_specifier, |
|
|
|
|
|
$.union_specifier, |
|
|
|
|
|
$.enum_specifier, |
|
|
|
|
|
$.sized_type_specifier, |
|
|
|
|
|
$.identifier |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
sized_type_specifier: $ => seq( |
|
|
|
|
|
repeat1(choice( |
|
|
|
|
|
'unsigned', |
|
|
|
|
|
'long', |
|
|
|
|
|
'short' |
|
|
|
|
|
)), |
|
|
|
|
|
$.identifier |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
enum_specifier: $ => seq( |
|
|
|
|
|
'enum', |
|
|
|
|
|
choice( |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
seq( |
|
|
|
|
|
optional($.identifier), |
|
|
|
|
|
'{', |
|
|
|
|
|
$._enum_specifier_contents, |
|
|
|
|
|
optional(','), |
|
|
|
|
|
'}' |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
_enum_specifier_contents: $ => commaSepTrailing( |
|
|
|
|
|
$._enum_specifier_contents, |
|
|
|
|
|
$.enumerator |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
struct_specifier: $ => seq( |
|
|
|
|
|
'struct', |
|
|
|
|
|
choice( |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
seq( |
|
|
|
|
|
optional($.identifier), |
|
|
|
|
|
'{', |
|
|
|
|
|
repeat($.struct_declaration), |
|
|
|
|
|
'}' |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
union_specifier: $ => seq( |
|
|
|
|
|
'union', |
|
|
|
|
|
choice( |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
seq( |
|
|
|
|
|
optional($.identifier), |
|
|
|
|
|
'{', |
|
|
|
|
|
repeat($.struct_declaration), |
|
|
|
|
|
'}' |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
struct_declaration: $ => seq( |
|
|
|
|
|
repeat($.type_qualifier), |
|
|
|
|
|
$._type_specifier, |
|
|
|
|
|
commaSep($._declarator), |
|
|
|
|
|
optional(seq(':', $._expression)), |
|
|
|
|
|
';' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
enumerator: $ => choice( |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
seq($.identifier, '=', $._expression) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
parameter_type_list: $ => commaSep1(choice( |
|
|
|
|
|
$.parameter_declaration, |
|
|
|
|
|
'...' |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
parameter_declaration: $ => seq( |
|
|
|
|
|
optional($._declaration_specifiers), |
|
|
|
|
|
$._type_specifier, |
|
|
|
|
|
optional(choice($._declarator, $._abstract_declarator)) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
// Statements
|
|
|
|
|
|
|
|
|
|
|
|
_statement: $ => choice( |
|
|
|
|
|
$.labeled_statement, |
|
|
|
|
|
$.compound_statement, |
|
|
|
|
|
$.expression_statement, |
|
|
|
|
|
$.if_statement, |
|
|
|
|
|
$.switch_statement, |
|
|
|
|
|
$.case_statement, |
|
|
|
|
|
$.do_statement, |
|
|
|
|
|
$.while_statement, |
|
|
|
|
|
$.for_statement, |
|
|
|
|
|
$.return_statement, |
|
|
|
|
|
$.break_statement, |
|
|
|
|
|
$.continue_statement, |
|
|
|
|
|
$.goto_statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
labeled_statement: $ => seq( |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
':', |
|
|
|
|
|
$._statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
expression_statement: $ => seq( |
|
|
|
|
|
optional($._expression), ';' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
if_statement: $ => prec.right(seq( |
|
|
|
|
|
'if', |
|
|
|
|
|
'(', $._expression, ')', |
|
|
|
|
|
$._statement, |
|
|
|
|
|
optional(seq( |
|
|
|
|
|
'else', |
|
|
|
|
|
$._statement |
|
|
|
|
|
)) |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
switch_statement: $ => seq( |
|
|
|
|
|
'switch', |
|
|
|
|
|
'(', $._expression, ')', |
|
|
|
|
|
$._statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
case_statement: $ => seq( |
|
|
|
|
|
choice( |
|
|
|
|
|
seq('case', $._expression), |
|
|
|
|
|
'default' |
|
|
|
|
|
), |
|
|
|
|
|
':', |
|
|
|
|
|
$._statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
while_statement: $ => seq( |
|
|
|
|
|
'while', |
|
|
|
|
|
'(', $._expression, ')', |
|
|
|
|
|
$._statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
do_statement: $ => seq( |
|
|
|
|
|
'do', |
|
|
|
|
|
$._statement, |
|
|
|
|
|
'while', |
|
|
|
|
|
'(', $._expression, ')' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
for_statement: $ => seq( |
|
|
|
|
|
'for', |
|
|
|
|
|
'(', |
|
|
|
|
|
choice( |
|
|
|
|
|
$.declaration, |
|
|
|
|
|
seq(optional($._expression), ';') |
|
|
|
|
|
), |
|
|
|
|
|
optional($._expression), ';', |
|
|
|
|
|
commaSep($._expression), |
|
|
|
|
|
')', |
|
|
|
|
|
$._statement |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
return_statement: $ => seq( |
|
|
|
|
|
'return', |
|
|
|
|
|
optional($._expression), |
|
|
|
|
|
';' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
break_statement: $ => seq( |
|
|
|
|
|
'break', ';' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
continue_statement: $ => seq( |
|
|
|
|
|
'continue', ';' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
goto_statement: $ => seq( |
|
|
|
|
|
'goto', $.identifier, ';' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
// Expressions
|
|
|
|
|
|
|
|
|
|
|
|
_expression: $ => choice( |
|
|
|
|
|
$.conditional_expression, |
|
|
|
|
|
$.assignment_expression, |
|
|
|
|
|
$.logical_expression, |
|
|
|
|
|
$.bitwise_expression, |
|
|
|
|
|
$.equality_expression, |
|
|
|
|
|
$.relational_expression, |
|
|
|
|
|
$.shift_expression, |
|
|
|
|
|
$.math_expression, |
|
|
|
|
|
$.cast_expression, |
|
|
|
|
|
$.pointer_expression, |
|
|
|
|
|
$.sizeof_expression, |
|
|
|
|
|
$.subscript_expression, |
|
|
|
|
|
$.call_expression, |
|
|
|
|
|
$.field_expression, |
|
|
|
|
|
$.compound_literal_expression, |
|
|
|
|
|
$.identifier, |
|
|
|
|
|
$.number_literal, |
|
|
|
|
|
$.string_literal, |
|
|
|
|
|
$.char_literal, |
|
|
|
|
|
seq('(', err($._expression), ')') |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
conditional_expression: $ => prec.right(PREC.CONDITIONAL, seq( |
|
|
|
|
|
$._expression, |
|
|
|
|
|
'?', |
|
|
|
|
|
$._expression, |
|
|
|
|
|
':', |
|
|
|
|
|
$._expression |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
assignment_expression: $ => prec.right(PREC.ASSIGNMENT, seq( |
|
|
|
|
|
$._expression, |
|
|
|
|
|
choice( |
|
|
|
|
|
'=', |
|
|
|
|
|
'*=', |
|
|
|
|
|
'/=', |
|
|
|
|
|
'%=', |
|
|
|
|
|
'+=', |
|
|
|
|
|
'-=', |
|
|
|
|
|
'<<=', |
|
|
|
|
|
'>>=', |
|
|
|
|
|
'&=', |
|
|
|
|
|
'^=', |
|
|
|
|
|
'|=' |
|
|
|
|
|
), |
|
|
|
|
|
$._expression |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
pointer_expression: $ => choice( |
|
|
|
|
|
prec.left(PREC.UNARY, seq('*', $._expression)), |
|
|
|
|
|
prec.left(PREC.UNARY, seq('&', $._expression)) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
logical_expression: $ => choice( |
|
|
|
|
|
prec.left(PREC.LOGICAL_OR, seq($._expression, '||', $._expression)), |
|
|
|
|
|
prec.left(PREC.LOGICAL_AND, seq($._expression, '&&', $._expression)), |
|
|
|
|
|
prec.left(PREC.UNARY, seq('!', $._expression)) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
bitwise_expression: $ => choice( |
|
|
|
|
|
prec.left(PREC.INCLUSIVE_OR, seq($._expression, '|', $._expression)), |
|
|
|
|
|
prec.left(PREC.EXCLUSIVE_OR, seq($._expression, '^', $._expression)), |
|
|
|
|
|
prec.left(PREC.BITWISE_AND, seq($._expression, '&', $._expression)), |
|
|
|
|
|
prec.left(PREC.UNARY, seq('~', $._expression)) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
equality_expression: $ => prec.left(PREC.EQUAL, seq( |
|
|
|
|
|
$._expression, choice('==', '!='), $._expression |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
relational_expression: $ => prec.left(PREC.RELATIONAL, seq( |
|
|
|
|
|
$._expression, choice('<', '>', '<=', '>='), $._expression |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
shift_expression: $ => prec.left(PREC.SHIFT, seq( |
|
|
|
|
|
$._expression, choice('<<', '>>'), $._expression) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
math_expression: $ => choice( |
|
|
|
|
|
prec.left(PREC.ADD, seq($._expression, '+', $._expression)), |
|
|
|
|
|
prec.left(PREC.ADD, seq($._expression, '-', $._expression)), |
|
|
|
|
|
prec.left(PREC.MULTIPLY, seq($._expression, '*', $._expression)), |
|
|
|
|
|
prec.left(PREC.MULTIPLY, seq($._expression, '/', $._expression)), |
|
|
|
|
|
prec.left(PREC.MULTIPLY, seq($._expression, '%', $._expression)), |
|
|
|
|
|
prec.right(PREC.UNARY, seq('-', $._expression)), |
|
|
|
|
|
prec.right(PREC.UNARY, seq('+', $._expression)), |
|
|
|
|
|
prec.right(PREC.UNARY, seq(choice('--', '++'), $._expression)), |
|
|
|
|
|
prec.right(PREC.UNARY, seq($._expression, choice('++', '--'))) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
cast_expression: $ => prec(PREC.CAST, seq( |
|
|
|
|
|
'(', $.type_name, ')', $._expression |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
sizeof_expression: $ => choice( |
|
|
|
|
|
prec(PREC.SIZEOF, seq('sizeof', $._expression)), |
|
|
|
|
|
prec(PREC.SIZEOF, seq('sizeof', '(', $.type_name, ')')) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
subscript_expression: $ => prec(PREC.SUBSCRIPT, seq( |
|
|
|
|
|
$._expression, '[', $._expression, ']') |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
call_expression: $ => prec(PREC.CALL, seq( |
|
|
|
|
|
$._expression, '(', commaSep($._expression), ')') |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
field_expression: $ => choice( |
|
|
|
|
|
prec.left(PREC.FIELD, seq($._expression, '.', $._expression)), |
|
|
|
|
|
prec.left(PREC.FIELD, seq($._expression, '->', $._expression)) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
compound_literal_expression: $ => seq( |
|
|
|
|
|
prec(PREC.CAST, seq('(', $.type_name, ')')), |
|
|
|
|
|
$.initializer_list |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
type_name: $ => seq( |
|
|
|
|
|
repeat($.type_qualifier), |
|
|
|
|
|
$._type_specifier, |
|
|
|
|
|
optional($._abstract_declarator) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
initializer_list: $ => seq( |
|
|
|
|
|
'{', |
|
|
|
|
|
$._initializer_list_contents, |
|
|
|
|
|
optional(','), |
|
|
|
|
|
'}' |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
_initializer_list_contents: $ => commaSepTrailing( |
|
|
|
|
|
$._initializer_list_contents, |
|
|
|
|
|
seq( |
|
|
|
|
|
optional(seq(repeat1($.designator), '=')), |
|
|
|
|
|
choice($._expression, $.initializer_list) |
|
|
|
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
designator: $ => choice( |
|
|
|
|
|
seq('[', $._expression, ']'), |
|
|
|
|
|
seq('.', $.identifier) |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
initializer: $ => choice( |
|
|
|
|
|
$._expression, |
|
|
|
|
|
$.initializer_list |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
number_literal: $ => token(choice( |
|
|
|
|
|
/\d+(\.\d+)?/, |
|
|
|
|
|
/\d+u/, |
|
|
|
|
|
seq('0x', /[0-9a-fA-f]+/), |
|
|
|
|
|
seq('0b', /[01]+/) |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
char_literal: $ => token(seq( |
|
|
|
|
|
'\'', |
|
|
|
|
|
choice( |
|
|
|
|
|
seq(optional('\\'), /[^']/), |
|
|
|
|
|
seq('\\', '\'') |
|
|
|
|
|
), |
|
|
|
|
|
'\'' |
|
|
|
|
|
)), |
|
|
|
|
|
|
|
|
|
|
|
string_literal: $ => token(seq( |
|
|
|
|
|
'"', |
|
|
|
|
|
repeat(choice(/[^"]/, '\\"')), |
|
|
|
|
|
'"') |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
system_lib_string: $ => token(seq( |
|
|
|
|
|
'<', |
|
|
|
|
|
repeat(choice(/[^>]/, '\\>')), |
|
|
|
|
|
'>') |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
identifier: $ => (/[\a_][\a\d_]*/), |
|
|
|
|
|
|
|
|
|
|
|
comment: $ => token(choice( |
|
|
|
|
|
seq( |
|
|
|
|
|
'//', |
|
|
|
|
|
/.*/ |
|
|
|
|
|
), |
|
|
|
|
|
seq( |
|
|
|
|
|
'/*', |
|
|
|
|
|
repeat(choice(/[^\*]/, /\*[^/]/)), |
|
|
|
|
|
'*/' |
|
|
|
|
|
) |
|
|
|
|
|
)), |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
function commaSep (rule) { |
|
|
|
|
|
return optional(commaSep1(rule)) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function commaSep1 (rule) { |
|
|
|
|
|
return seq(rule, repeat(seq(',', rule))) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function commaSepTrailing (recurSymbol, rule) { |
|
|
|
|
|
return choice(rule, seq(recurSymbol, ',', rule)) |
|
|
|
|
|
} |