No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

454 líneas
12 KiB

module.exports =
({choice, err, repeat, seq, keyword, optional, token, prec, precedenceValues}) ->
precedenceValues = (names) ->
result = {}
startValue = -1 * names.indexOf('default')
for name in names
result[name] = startValue++
result
commaSep = (rule) ->
optional(commaSep1(rule))
commaSep1 = (rule) ->
seq(rule, repeat(seq(",", rule)))
prefix = (precedence, operand, operator) ->
prec(precedence, seq(operator, operand))
postfix = (precedence, operand, operator) ->
prec(precedence, seq(operand, operator))
infix = (precedence, operand, operator) ->
prec(precedence, seq(operand, operator, operand))
PREC = precedenceValues [
'assignment'
'conditional'
'default'
'logical_or'
'logical_and'
'inclusive_or'
'exclusive_or'
'bitwise_and'
'equal'
'relational'
'sizeof'
'shift'
'add'
'multiply'
'call'
'cast'
'unary'
'field'
'subscript'
]
{
name: 'c'
ubiquitous: -> [@comment, /\s/]
rules:
translation_unit: -> repeat(choice(
@preproc_statement,
@function_definition,
@declaration))
# Section - Preprocesser
preproc_statement: -> choice(
@preproc_ifdef,
@preproc_ifndef,
@preproc_endif,
@preproc_else,
@preproc_include,
@preproc_define,
@preproc_call)
preproc_include: -> seq(
keyword("#include"),
choice(@string_literal, @system_lib_string))
preproc_define: -> seq(
keyword("#define"),
@identifier,
token(seq(/.+/, repeat(seq("\\\n", /.+/)))))
preproc_call: -> choice(
seq(@preproc_directive, /.*/))
preproc_ifdef: -> seq(keyword("#ifdef"), @identifier)
preproc_ifndef: -> seq(keyword("#ifndef"), @identifier)
preproc_else: -> keyword("#else")
preproc_endif: -> keyword("#endif")
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(@init_declarator),
";")
declaration_specifiers: -> repeat(choice(
@storage_class_specifier,
@type_qualifier,
@function_specifier))
declarator: ->
seq(repeat(@pointer), @direct_declarator)
abstract_declarator: -> choice(
@pointer,
seq(repeat(@pointer), @direct_abstract_declarator))
init_declarator: -> choice(
@declarator,
seq(@declarator, "=", @initializer))
compound_statement: -> seq(
"{",
repeat(choice(@declaration, @statement)),
"}")
storage_class_specifier: -> choice(
keyword("typedef"),
keyword("extern"),
keyword("static") ,
keyword("auto"),
keyword("register"))
type_qualifier: -> choice(
keyword("const"),
keyword("restrict"),
keyword("volatile"))
function_specifier: -> keyword("inline")
type_specifier: -> choice(
@struct_specifier,
@union_specifier,
@enum_specifier,
seq(
repeat(choice(
keyword("unsigned"),
keyword("long"),
keyword("short"))),
@identifier))
enum_specifier: -> seq(
keyword("enum"),
choice(
@identifier,
seq(
optional(@identifier),
"{", commaSep(@enumerator), "}")))
struct_specifier: -> seq(
keyword("struct"),
choice(
@identifier,
seq(
optional(@identifier),
"{", repeat(@struct_declaration), "}")))
union_specifier: -> seq(
keyword("union"),
choice(
@identifier,
seq(
optional(@identifier),
"{", repeat(@struct_declaration), "}")))
struct_declaration: -> seq(
repeat(choice(
@type_specifier,
@type_qualifier)),
commaSep(@struct_declarator),
";")
enumerator: -> choice(
@identifier,
seq(@identifier, "=", @expression))
struct_declarator: -> choice(
@declarator,
seq(optional(@declarator), ":", @expression))
pointer: -> seq(
"*",
repeat(@type_qualifier))
direct_declarator: -> choice(
@identifier,
# TODO - is this needed? Currently, it creates ambiguity w/
# call expressions
#
# seq("(", @declarator, ")"),
seq(
@direct_declarator,
choice(
seq("[", repeat(@type_qualifier), optional(@expression), "]"),
seq("[", keyword("static"), repeat(@type_qualifier), @expression, "]"),
seq("[", repeat(@type_qualifier), keyword("static"), @expression, "]"),
seq("[", repeat(@type_qualifier), "*", "]"),
seq("(", optional(@parameter_type_list), ")"),
seq("(", commaSep(@identifier), ")"))))
direct_abstract_declarator: -> choice(
seq("(", @abstract_declarator, ")"),
seq(
@direct_abstract_declarator,
choice(
seq("[", repeat(@type_qualifier), optional(@expression), "]"),
seq("[", keyword("static"), repeat(@type_qualifier), @expression, "]"),
seq("[", repeat(@type_qualifier), keyword("static"), @expression, "]"),
seq("[", "*", "]"),
seq("(", optional(@parameter_type_list), ")"))))
parameter_type_list: -> seq(
commaSep(@parameter_declaration),
optional(seq(",", "...")))
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: -> seq(
keyword("if"),
"(", @expression, ")",
@statement,
optional(seq(
keyword("else"),
@statement)))
switch_statement: -> seq(
keyword("switch"),
"(", @expression, ")",
@statement)
case_statement: -> seq(
choice(
seq(keyword("case"), @expression),
keyword("default")),
":",
@statement)
while_statement: -> seq(
keyword("while"),
"(", @expression, ")",
@statement)
do_statement: -> seq(
keyword("do"),
@statement,
keyword("while"),
"(", @expression, ")")
for_statement: -> seq(
keyword("for"),
"(",
choice(
@declaration,
seq(optional(@expression), ";")),
optional(@expression), ";"
optional(@expression),
")",
@statement)
return_statement: -> seq(
keyword("return"),
optional(@expression)
";")
break_statement: -> seq(
keyword("break"), ";")
continue_statement: -> seq(
keyword("continue"), ";")
goto_statement: -> seq(
keyword("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("(", @expression, ")"))
conditional_expression: -> prec(PREC.conditional, seq(
@expression,
"?",
@expression,
":",
@expression))
assignment_expression: ->
infix(PREC.assignment, @expression, choice(
"=",
"*=",
"/=",
"%=",
"+=",
"-=",
"<<=",
">>=",
"&=",
"^=",
"|="))
pointer_expression: -> choice(
prefix(PREC.unary, @expression, "*"),
prefix(PREC.unary, @expression, "&"))
logical_expression: -> choice(
infix(PREC.logical_or, @expression, "||"),
infix(PREC.logical_and, @expression, "&&"),
prefix(PREC.unary, @expression, "!"))
bitwise_expression: -> choice(
infix(PREC.inclusive_or, @expression, "|"),
infix(PREC.exclusive_or, @expression, "^"),
infix(PREC.bitwise_and, @expression, "&"),
prefix(PREC.unary, @expression, "~"))
equality_expression: ->
infix(PREC.equal, @expression, choice("==", "!="))
relational_expression: ->
infix(PREC.relational, @expression, choice("<", ">", "<=", ">="))
shift_expression: ->
infix(PREC.shift, @expression, choice("<<", ">>"))
math_expression: -> choice(
infix(PREC.add, @expression, "+"),
infix(PREC.add, @expression, "-"),
infix(PREC.multiply, @expression, "*"),
infix(PREC.multiply, @expression, "/"),
infix(PREC.multiply, @expression, "%"),
prefix(PREC.unary, @expression, "-"),
prefix(PREC.unary, @expression, "+"),
prefix(PREC.unary, @expression, choice("++", "--")),
postfix(PREC.unary, @expression, choice("++", "--")))
cast_expression: ->
prec(PREC.cast, seq("(", @type_name, ")", @expression))
sizeof_expression: -> choice(
prefix(PREC.sizeof, @expression, keyword("sizeof"))
prefix(PREC.sizeof, seq("(", @type_name, ")"), keyword("sizeof")))
subscript_expression: ->
prec(PREC.subscript, seq(@expression, "[", @expression, "]"))
call_expression: ->
prec(PREC.call, seq(@expression, "(", commaSep(@expression), ")"))
field_expression: -> choice(
infix(PREC.field, @expression, "."),
infix(PREC.field, @expression, "->"))
compound_literal_expression: -> seq(
"(", @type_name, ")",
@initializer_list)
type_name: -> seq(
repeat(choice(
@type_specifier,
@type_qualifier)),
optional(@abstract_declarator))
initializer_list: -> seq(
"{",
commaSep(seq(
optional(seq(repeat(@designator), "=")),
@initializer)),
optional(",")
"}")
designator: -> choice(
seq("[", @expression, "]"),
seq(".", @identifier))
initializer: -> choice(
@expression,
@initializer_list)
number_literal: -> /\d+(\.\d+)?/
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(/[^\*]/, /\*[^/]/)), "*/")))
}