25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

496 satır
12 KiB

commaSep = (rule) ->
optional(commaSep1(rule))
commaSep1 = (rule) ->
seq(rule, repeat(seq(",", rule)))
# Avoid conflict between optional trailing comma and the comma separator.
# TODO: maybe abstract this in tree-sitter core somehow
commaSepTrailing = (recurSymbol, rule) ->
choice(rule, seq(recurSymbol, ',', rule))
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'
ubiquitous: -> [@comment, /\s/]
expectedConflicts: -> [
[@_type_specifier, @_expression]
[@_type_specifier, @direct_declarator]
[@sizeof_expression, @cast_expression]
]
rules:
translation_unit: -> repeat(choice(
@_preproc_statement,
@function_definition,
@declaration))
# Section - 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*/
# Section - Main Grammar
function_definition: -> seq(
optional(@_declaration_specifiers),
@_type_specifier,
@_declarator,
optional(repeat(@declaration)),
@compound_statement)
declaration: -> 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(@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(/[^\*]/, /\*[^/]/)), "*/")))