Created
April 16, 2021 16:59
-
-
Save alexnask/2c0eb2f4543cbcfc3bfe3bd146b4f396 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Rules that will be inlined. | |
| let underscore_sep = r => seq(r, repeat( | |
| seq(optional("_"), r), | |
| )); | |
| let bin = /[01]/; | |
| let oct = /[0-7]/; | |
| let dec = /[0-9]/; | |
| let hex = /[0-9a-fA-F]/; | |
| let bin_int = underscore_sep(bin); | |
| let oct_int = underscore_sep(oct); | |
| let dec_int = underscore_sep(dec); | |
| let hex_int = underscore_sep(hex); | |
| let char_escape = choice( | |
| seq("\\x", hex, hex), | |
| seq("\\u{", repeat1(hex), "}"), | |
| seq("\\", /[nr\\t'"]/), | |
| ); | |
| let string_char = choice(char_escape, /[^\\"\n]/); | |
| let ox80_oxBF = /[\x80-\xBF]/; | |
| let oxF4 = '\364'; | |
| let ox80_ox8F = /[\x80-\x8F]/; | |
| let oxF1_oxF3 = /[\xF1-\xF3]/; | |
| let oxF0 = '\360'; | |
| let ox90_0xBF = /[\x90-\xBF]/; | |
| let oxEE_oxEF = /[\xEE-\xEF]/; | |
| let oxED = '\355'; | |
| let ox80_ox9F = /[\x80-\x9F]/; | |
| let oxE1_oxEC = /[\xE1-\xEC]/; | |
| let oxE0 = '\340'; | |
| let oxA0_oxBF = /[\xA0-\xBF]/; | |
| let oxC2_oxDF = /[\xC2-\xDF]/; | |
| let mb_utf8_literal = choice( | |
| seq(oxF4, ox80_ox8F, ox80_oxBF, ox80_oxBF), | |
| seq(oxF1_oxF3, ox80_oxBF, ox80_oxBF, ox80_oxBF), | |
| seq(oxF0, ox90_0xBF, ox80_oxBF, ox80_oxBF), | |
| seq(oxEE_oxEF, ox80_oxBF, ox80_oxBF), | |
| seq(oxED, ox80_ox9F, ox80_oxBF), | |
| seq(oxE1_oxEC, ox80_oxBF, ox80_oxBF), | |
| seq(oxE0, oxA0_oxBF, ox80_oxBF), | |
| seq(oxC2_oxDF, ox80_oxBF), | |
| ); | |
| let ascii_char_not_nl_slash_squote = /[\x00-\x09 \x0B-\x26-\x28-\x5B \x5D-\x7F]/; | |
| let char_char = choice(mb_utf8_literal, char_escape, ascii_char_not_nl_slash_squote); | |
| let comma_list = rule => seq( | |
| rule, | |
| repeat(seq(",", rule)), | |
| optional(","), | |
| ); | |
| let optional_comma_list = rule => seq( | |
| repeat(seq(rule, ",")), | |
| optional(rule), | |
| ); | |
| let keyword_expression = (kw, $) => prec(expr_precs.primary, seq(kw, $._expression)); | |
| let if_prefix = $ => seq( | |
| "if", "(", field("cond", $._expression), ")", | |
| optional(field("payload", $.ptr_payload)), | |
| ); | |
| let for_prefix = $ => seq( | |
| "for", "(", field("iterable", $._expression), ")", | |
| field("payload", $.ptr_index_payload), | |
| ); | |
| let while_prefix = $ => seq( | |
| "while", "(", field("cond", $._expression), ")", | |
| optional(field("payload", $.ptr_payload)), | |
| optional(seq( | |
| ":", "(", field("continue_expr", $._assignment_or_expression), ")", | |
| )), | |
| ); | |
| let loop_statement_prefix = ($, prefix) => seq( | |
| optional(field("label", $.block_label)), | |
| optional("inline"), | |
| prefix, | |
| ); | |
| let control_flow_statement = ($, prefix, has_else_payload) => { | |
| const payload_rule = has_else_payload ? | |
| optional(field("else_payload", $.payload)) : blank(); | |
| return prec(statement_prec, seq( | |
| prefix, | |
| choice( | |
| seq( | |
| field("body", $.block_expression), | |
| optional(seq( | |
| "else", | |
| payload_rule, | |
| field("else_body", $._statement), | |
| )), | |
| ), | |
| seq( | |
| field("body", $._assignment_or_expression), | |
| choice( | |
| ";", | |
| seq( | |
| "else", | |
| payload_rule, | |
| field("else_body", $._statement), | |
| ), | |
| ), | |
| ), | |
| ), | |
| )); | |
| }; | |
| let control_flow_expression = ($, prefix, expr_rule, has_else_payload) => { | |
| const payload_rule = has_else_payload ? | |
| optional(field("else_payload", $.payload)) : blank(); | |
| return seq( | |
| optional(field("label", $.block_label)), | |
| optional("inline"), | |
| prefix, | |
| expr_rule, | |
| optional(seq( | |
| "else", | |
| payload_rule, | |
| field("else_body", expr_rule), | |
| )), | |
| ); | |
| }; | |
| let expr_precs = { | |
| or: 1, | |
| and: 2, | |
| compare: 3, | |
| bitwise: 4, | |
| bitshift: 5, | |
| addition: 6, | |
| multiply: 7, | |
| prefix: 8, | |
| primary: 9, | |
| async_call: 10, | |
| primary_type: 11, | |
| suffix: 12, | |
| error_union: 13, | |
| prefix_type: 14, | |
| }; | |
| let statement_prec = 15; | |
| module.exports = grammar({ | |
| name: "zig", | |
| externals: (_) => [], | |
| extras: $ => [/\s/, $.line_comments], | |
| // TODO Will I need this? | |
| //word: $ => $.identifier, | |
| rules: { | |
| root: ($) => seq( | |
| optional($.container_doc_comment), | |
| repeat($._container_members), | |
| ), | |
| // Top level (grammar.y:3) | |
| // Container level expressions, statements, declarations | |
| _container_members: $ => choice( | |
| $.test_decl, | |
| $.top_level_comptime, | |
| $.top_level_var_decl, | |
| $.top_level_fn_proto, | |
| $.usingnamespace, | |
| $.container_field, | |
| ), | |
| test_decl: $ => seq( | |
| field("doc_comments", optional($.doc_comment)), | |
| "test", | |
| field("name", optional($.string_literal_single)), | |
| field("body", $.block), | |
| ), | |
| top_level_comptime: $ => seq( | |
| field("doc_comments", optional($.doc_comment)), | |
| "comptime", | |
| field("body", $.block_expression) | |
| ), | |
| top_level_var_decl: $ => seq( | |
| optional(field("doc_comments", $.doc_comment)), | |
| optional(field("pub", alias("pub", $.pub_mod))), | |
| optional(field("export_extern", $.export_extern_mod)), | |
| optional(field("threadlocal", $.threadlocal_mod)), | |
| field("decl", $.var_decl), | |
| ), | |
| top_level_fn_proto: $ => seq( | |
| optional(field("doc_comments", $.doc_comment)), | |
| optional(field("pub", alias("pub", $.pub_mod))), | |
| optional(field("export_extern", $.export_extern_mod)), | |
| field("proto", $.fn_proto), | |
| choice( | |
| ";", | |
| field("block", $.block), | |
| ), | |
| ), | |
| usingnamespace: $ => seq( | |
| optional(field("doc_comments", $.doc_comment)), | |
| optional(field("pub", alias("pub", $.pub_mod))), | |
| "usingnamespace", | |
| $._expression, | |
| ";", | |
| ), | |
| container_field: $ => seq( | |
| optional(field("doc_comments", $.doc_comment)), | |
| optional("comptime"), | |
| field("name", $.identifier), | |
| optional(seq(":", field("type", $.container_field_type))), | |
| optional(seq("=", field("initializer", $._expression))), | |
| ",", | |
| ), | |
| container_field_type: $ => seq( | |
| choice("anytype", field("type_expr", $._type_expression)), | |
| optional(field("byte_align", $.byte_align)), | |
| ), | |
| var_decl: $ => seq( | |
| choice("var", "const"), | |
| field("name", $.identifier), | |
| optional(seq(":", field("type_expr", $._type_expression))), | |
| optional(field("byte_align", $.byte_align)), | |
| optional(field("link_section", $.link_section)), | |
| optional(seq("=", field("initializer", $._expression))), | |
| ";", | |
| ), | |
| fn_proto: $ => prec(expr_precs.primary_type, seq( | |
| "fn", | |
| optional(field("name", $.identifier)), | |
| "(", | |
| optional_comma_list($.param_decl), | |
| ")", | |
| optional(field("byte_align", $.byte_align)), | |
| optional(field("link_section", $.link_section)), | |
| optional(field("call_conv", $.call_conv)), | |
| optional("!"), | |
| field("return_type", $._type_expression), | |
| )), | |
| param_decl: $ => seq( | |
| optional(field("doc_comments", $.doc_comment)), | |
| optional(choice("noalias", "comptime")), | |
| optional(seq(field("name", $.identifier), ":")), | |
| field("type", $.param_type), | |
| ), | |
| param_type: $ => choice( | |
| "anytype", | |
| "...", | |
| field("type_expr", $._type_expression), | |
| ), | |
| // Block level (grammar.y:29) | |
| _statement: $ => choice( | |
| $.var_decl_statement, | |
| // TODO Does this work? | |
| prec(statement_prec, seq($._assignment_or_expression, ";")), | |
| $.prefixed_block_expression_statement, | |
| $.bare_suspend_statement, | |
| $.errdefer_statement, | |
| $.if_statement, | |
| $.block_statement, | |
| $.for_statement, | |
| $.while_statement, | |
| // Match this instead of a switch expression + semicolon | |
| prec(statement_prec + 1, $.switch_expression), | |
| ), | |
| block_statement: $ => $.block_expression, | |
| while_statement: $ => control_flow_statement( | |
| $, | |
| loop_statement_prefix($, while_prefix($)), | |
| true, | |
| ), | |
| for_statement: $ => control_flow_statement( | |
| $, | |
| loop_statement_prefix($, for_prefix($)), | |
| false, | |
| ), | |
| if_statement: $ => control_flow_statement( | |
| $, | |
| if_prefix($), | |
| true, | |
| ), | |
| bare_suspend_statement: _ => seq("suspend", ";"), | |
| block_label: $ => prec(expr_precs.primary_type + 1, seq($.identifier, ":")), | |
| block_expression: $ => prec(statement_prec, seq( | |
| optional(field("label", $.block_label)), | |
| $.block, | |
| )), | |
| errdefer_statement: $ => prec(statement_prec, seq( | |
| "errdefer", | |
| optional(field("payload", $.payload)), | |
| choice( | |
| $.block_expression, | |
| seq($._assignment_or_expression, ";"), | |
| ), | |
| )), | |
| prefixed_block_expression_statement: $ => prec(statement_prec, seq( | |
| // TODO Doesnt show up in `tree-sitter parse` output, check programmatically. | |
| // remove some other aliases if it does. | |
| field("keyword", choice( | |
| "comptime", "nosuspend", | |
| "suspend", "defer", | |
| )), | |
| choice( | |
| $.block_expression, | |
| seq($._assignment_or_expression, ";"), | |
| ), | |
| )), | |
| var_decl_statement: $ => prec(statement_prec, seq( | |
| optional("comptime"), | |
| $.var_decl, | |
| )), | |
| assign_or_expression_statement: $ => prec(statement_prec, seq( | |
| $._assignment_or_expression, | |
| ";", | |
| )), | |
| // Expression level (grammar.y:65) | |
| _expression: $ => choice( | |
| $.binary_expression, | |
| $.catch_expression, | |
| $.unary_expression, | |
| $.asm_expression, | |
| $.if_expression, | |
| $.for_expression, | |
| $.while_expression, | |
| $.break_expression, | |
| $.continue_expression, | |
| $.comptime_expression, | |
| $.nosuspend_expression, | |
| $.resume_expression, | |
| $.block, | |
| $._type_expression, | |
| // This is CurlySuffixExpr in grammar.y | |
| $.type_init_list_expression, | |
| ), | |
| // TODO Is this the correct associativity? | |
| if_expression: $ => prec.left(expr_precs.primary, | |
| control_flow_expression($, if_prefix($), $._expression, true) | |
| ), | |
| // TODO Is this the correct associativity? | |
| for_expression: $ => prec.left(expr_precs.primary, | |
| control_flow_expression($, for_prefix($), $._expression, false) | |
| ), | |
| // TODO Is this the correct associativity? | |
| while_expression: $ => prec.left(expr_precs.primary, | |
| control_flow_expression($, while_prefix($), $._expression, true) | |
| ), | |
| block: $ => prec(expr_precs.primary, seq( | |
| "{", repeat($._statement), "}" | |
| )), | |
| type_init_list_expression: $ => prec(expr_precs.primary, seq( | |
| field("type_expr", $._type_expression), | |
| field("list", $.init_list), | |
| )), | |
| // TODO Is this the correct associativity? | |
| comptime_expression: $ => keyword_expression("comptime", $), | |
| nosuspend_expression: $ =>keyword_expression("nosuspend", $), | |
| resume_expression: $ => keyword_expression("resume", $), | |
| return_expression: $ => prec(expr_precs.primary, seq( | |
| "return", | |
| optional(field("expr", $._expression)), | |
| )), | |
| // TODO Check associativity | |
| break_label: $ => seq(":", $.identifier), | |
| break_expression: $ => prec.left(expr_precs.primary, seq( | |
| "break", | |
| optional(field("label", $.break_label)), | |
| optional(field("expr", $._expression)), | |
| )), | |
| continue_expression: $ => prec.left(expr_precs.primary, seq( | |
| "continue", | |
| optional(field("expr", $._expression)), | |
| )), | |
| assignment: $ => seq( | |
| field("left", $._expression), | |
| field("operator", alias(choice( | |
| "*=", "/=", | |
| "%=", "+=", | |
| "-=", "<<=", | |
| ">>=", "&=", | |
| "^=", "|=", | |
| "*%=", "+%=", | |
| "-%=", "=", | |
| ), $.assign_operator)), | |
| field("right", $._expression), | |
| ), | |
| _assignment_or_expression: $ => choice( | |
| $.assignment, | |
| $._expression, | |
| ), | |
| field_init: $ => seq( | |
| ".", field("name", $.identifier), "=", field("expr", $._expression), | |
| ), | |
| init_list: $ => seq( | |
| "{", | |
| choice( | |
| optional_comma_list($.field_init), | |
| optional_comma_list($._expression), | |
| ), | |
| "}", | |
| ), | |
| // grammar.y:115 | |
| _type_expression: $ => choice( | |
| $.unary_type_expression, | |
| $.slice_type_expression, | |
| $.single_ptr_type_expression, | |
| $.multi_ptr_type_expression, | |
| $.array_type_expression, | |
| $.error_union_expression, | |
| $.grouped_expression, | |
| $.builtin_call_expression, | |
| $.identifier, | |
| $.anonymous_init_list_expression, | |
| // Literals | |
| $._string_literal, | |
| $.char_literal, | |
| $.integer_literal, | |
| $.float_literal, | |
| $.enum_literal, | |
| $.error_value_literal, | |
| alias("false", $.false), | |
| alias("true", $.true), | |
| alias("null", $.null), | |
| alias("undefined", $.undefined), | |
| alias("unreachable", $.unreachable), | |
| // Container and function decls | |
| $.fn_proto, | |
| $.error_set_decl, | |
| $.struct_decl, | |
| $.opaque_decl, | |
| $.enum_decl, | |
| $.union_decl, | |
| // Control flow expressions | |
| $.switch_expression, | |
| $.if_type_expression, | |
| $.for_type_expression, | |
| $.while_type_expression, | |
| // Block | |
| $.block_type_expression, | |
| // All these are in SuffixOp | |
| $.bracket_access_expression, | |
| $.field_access, | |
| $.suffix_type_expression, | |
| // Misc | |
| $.comptime_type_expression, | |
| $.async_call_expression, | |
| $.call_expression, | |
| ), | |
| error_set_decl: $ => prec(expr_precs.primary_type, seq( | |
| "error", "{", | |
| optional_comma_list($.identifier), | |
| "}", | |
| )), | |
| struct_decl: $ => prec(expr_precs.primary_type, seq( | |
| optional(choice("extern", "packed")), | |
| "struct", | |
| "{", optional($.container_doc_comment), | |
| repeat($._container_members), "}", | |
| )), | |
| opaque_decl: $ => prec(expr_precs.primary_type, seq( | |
| optional(choice("extern", "packed")), | |
| "opaque", | |
| "{", optional($.container_doc_comment), | |
| repeat($._container_members), "}", | |
| )), | |
| enum_decl: $ => prec(expr_precs.primary_type, seq( | |
| optional(choice("extern", "packed")), | |
| "enum", | |
| optional(seq("(", field("enum_int_type_expr", $._expression), ")")), | |
| "{", optional($.container_doc_comment), | |
| repeat($._container_members), "}", | |
| )), | |
| union_decl: $ => prec(expr_precs.primary_type, seq( | |
| optional(choice("extern", "packed")), | |
| "union", | |
| optional(seq( | |
| "(", | |
| choice( | |
| seq("enum", optional(seq("(", field("enum_int_type_expr", $._expression), ")"))), | |
| field("enum_type_expr", $._expression), | |
| ), | |
| ")", | |
| )), | |
| "{", optional($.container_doc_comment), | |
| repeat($._container_members), "}", | |
| )), | |
| block_type_expression: $ => prec(expr_precs.primary_type, seq( | |
| field("label", $.block_label), | |
| field("block", $.block), | |
| )), | |
| // TODO Is this the correct associativity? | |
| if_type_expression: $ => prec.left(expr_precs.primary_type, | |
| control_flow_expression($, if_prefix($), $._type_expression, true) | |
| ), | |
| // TODO Is this the correct associativity? | |
| for_type_expression: $ => prec.left(expr_precs.primary_type, | |
| control_flow_expression($, for_prefix($), $._type_expression, false) | |
| ), | |
| // TODO Is this the correct associativity? | |
| while_type_expression: $ => prec.left(expr_precs.primary_type, | |
| control_flow_expression($, while_prefix($), $._type_expression, true) | |
| ), | |
| comptime_type_expression: $ => prec(expr_precs.primary_type, seq( | |
| "comptime", | |
| field("type_expr", $._type_expression), | |
| )), | |
| anonymous_init_list_expression: $ => prec(expr_precs.primary_type, seq( | |
| ".", | |
| field("list", $.init_list), | |
| )), | |
| // TODO Shouldnt this need an associativity? | |
| suffix_type_operator: $ => choice(".?", ".*"), | |
| suffix_type_expression: $ => prec(expr_precs.suffix, seq( | |
| field("type_expr", $._type_expression), | |
| field("operator", $.suffix_type_operator), | |
| )), | |
| field_access: $ => prec(expr_precs.suffix, seq( | |
| field("left", $._type_expression), | |
| ".", | |
| field("right", $.identifier), | |
| )), | |
| unary_type_operator: _ => choice("?", seq("anyframe", "->")), | |
| unary_type_expression: $ => prec(expr_precs.prefix_type, seq( | |
| field("operator", $.unary_type_operator), | |
| field("type_expr", $._type_expression), | |
| )), | |
| slice_type_expression: $ => prec(expr_precs.prefix_type, seq( | |
| "[", | |
| optional(seq(":", field("sentinel", $._expression))), | |
| "]", | |
| optional_comma_list( | |
| choice( | |
| $.byte_align, | |
| "const", | |
| "volatile", | |
| "allowzero", | |
| ), | |
| ), | |
| field("type_expr", $._type_expression), | |
| )), | |
| _ptr_modifier: $ => choice( | |
| $.pointer_align, | |
| "const", | |
| "volatile", | |
| "allowzero", | |
| ), | |
| single_ptr_type_expression: $ => prec(expr_precs.prefix_type, seq( | |
| "*", | |
| optional_comma_list($._ptr_modifier), | |
| field("type_expr", $._type_expression), | |
| )), | |
| multi_ptr_type_expression: $ => prec(expr_precs.prefix_type, seq( | |
| "[", "*", | |
| optional(choice( | |
| "c", | |
| seq(":", field("sentinel", $._expression)), | |
| )), | |
| "]", | |
| optional_comma_list($._ptr_modifier), | |
| field("type_expr", $._type_expression), | |
| )), | |
| array_type_expression: $ => prec(expr_precs.prefix_type, seq( | |
| "[", | |
| field("size_expr", $._expression), | |
| optional(seq(":", field("sentinel", $._expression))), | |
| "]", | |
| field("type_expr", $._type_expression), | |
| )), | |
| // TODO Check associativity | |
| error_union_expression: $ => prec.left(expr_precs.error_union, seq( | |
| field("left", $._type_expression), | |
| "!", | |
| field("right", $._type_expression), | |
| )), | |
| grouped_expression: $ => prec(expr_precs.primary_type, seq( | |
| "(", | |
| field("expr", $._expression), | |
| ")", | |
| )), | |
| builtin_identifier: _ => seq("@", /[A-Za-z_][A-Za-z0-9_]*/), | |
| builtin_call_expression: $ => prec(expr_precs.primary_type, seq( | |
| field("name", $.builtin_identifier), | |
| "(", | |
| optional_comma_list($._expression), | |
| ")", | |
| )), | |
| bracket_access_expression: $ => prec(expr_precs.suffix, seq( | |
| field("base_expr", $._type_expression), | |
| "[", | |
| field("start_index", $._expression), | |
| optional(seq( | |
| "..", | |
| optional(seq( | |
| optional(field("end_index", $._expression)), | |
| optional(seq( | |
| ":", | |
| field("sentinel", $._expression), | |
| )), | |
| )), | |
| )), | |
| "]", | |
| )), | |
| async_call_expression: $ => prec(expr_precs.async_call, seq( | |
| "async", | |
| field("fn_expr", $._type_expression), | |
| "(", | |
| optional_comma_list($._expression), | |
| ")", | |
| )), | |
| call_expression: $ => prec(expr_precs.suffix, seq( | |
| field("fn_expr", $._type_expression), | |
| "(", | |
| optional_comma_list($._expression), | |
| ")", | |
| )), | |
| asm_output_item: $ => seq( | |
| "[", field("name", $.identifier), "]", | |
| $._string_literal, | |
| "(", choice(seq("->", $._type_expression), $.identifier), ")", | |
| ), | |
| asm_output_list: $ => comma_list($.asm_output_item), | |
| asm_output: $ => seq( | |
| ":", | |
| optional(field("output_list", $.asm_output_list)), | |
| optional(field("input", $.asm_input)), | |
| ), | |
| asm_input_item: $ => seq( | |
| "[", field("name", $.identifier), "]", | |
| $._string_literal, | |
| "(", field("expr", $._expression), ")", | |
| ), | |
| asm_input_list: $ => comma_list($.asm_input_item), | |
| asm_clobbers: $ => seq( | |
| ":", | |
| optional(field("list", $.string_list)), | |
| ), | |
| asm_input: $ => seq( | |
| ":", | |
| field("input_list", $.asm_input_list), | |
| optional(field("clobbers", $.asm_clobbers)), | |
| ), | |
| asm_expression: $ => prec(expr_precs.primary, seq( | |
| "asm", | |
| optional(field("volatile", alias("volatile", $.volatile))), | |
| "(", | |
| field("template", $._expression), | |
| optional(field("output", $.asm_output)), | |
| ")", | |
| )), | |
| // TODO Check associativity | |
| catch_expression: $ => prec.left(expr_precs.bitwise,seq( | |
| field("left", $._expression), | |
| "catch", | |
| optional(field("payload", $.payload)), | |
| field("right", $._expression), | |
| )), | |
| binary_expression: $ => { | |
| // TODO Check associativity. | |
| const table = [ | |
| [expr_precs.or, "or"], | |
| [expr_precs.and, "and"], | |
| [expr_precs.compare, choice("==", "!=", "<", "<=", ">", ">=")], | |
| [expr_precs.bitwise, choice("&", "^", "|", "orelse")], | |
| [expr_precs.bitshift, choice("<<", ">>")], | |
| [expr_precs.addition, choice("+", "+%", "-", "-%", "++")], | |
| [expr_precs.multiply, choice("*", "/", "%", "**", "*%", "||")], | |
| ]; | |
| return choice( | |
| ...table.map(([precedence, op]) => | |
| prec.left( | |
| precedence, | |
| seq( | |
| field("left", $._expression), | |
| field("operator", alias(op, $.binary_operator)), | |
| field("right", $._expression), | |
| ) | |
| )) | |
| ); | |
| }, | |
| unary_operator: _ => choice("~", "!", "-", "-%", "&", "try", "await"), | |
| unary_expression: $ => prec(expr_precs.prefix, seq( | |
| field("operator", $.unary_operator), | |
| field("expression", $._expression), | |
| )), | |
| identifier: $ => token(choice( | |
| seq(/[a-zA-Z_]/, repeat(/[a-zA-Z0-9_]/)), | |
| seq('@"', repeat(string_char), token.immediate('"')), | |
| )), | |
| // Comments | |
| container_doc_comment: _ => repeat1(token(seq("//!", /.*/))), | |
| doc_comment: _ => repeat1(token(seq("///", /.*/))), | |
| line_comments: _ => token(repeat1(seq("//", /.*/))), | |
| // Literals | |
| string_literal_single: _ => token(seq('"', repeat(string_char), token.immediate('"'))), | |
| line_string: _ => token(repeat1(seq( | |
| "\\\\", /.*/, | |
| ))), | |
| _string_literal: $ => choice($.string_literal_single, $.line_string), | |
| string_list: $ => comma_list($._string_literal), | |
| enum_literal: $ => seq(".", $.identifier), | |
| error_value_literal: $ => seq("error", ".", $.identifier), | |
| char_literal: _ => seq( | |
| "'", char_char, token.immediate("'"), | |
| ), | |
| float_literal: _ => token(choice( | |
| seq("0x", hex_int, ".", hex_int, optional(seq(/[pP][-+]?/, dec_int))), | |
| seq(dec_int, ".", dec_int, optional(seq(/[eE][-+]?/, dec_int))), | |
| seq("0x", hex_int, optional("."), /[pP][-+]?/, hex_int), | |
| seq(dec_int, optional("."), /[eE][-+]?/, dec_int), | |
| )), | |
| integer_literal: _ => token(choice( | |
| seq("0b", bin_int), | |
| seq("0o", oct_int), | |
| seq("0x", hex_int), | |
| dec_int, | |
| )), | |
| // Switch stuff | |
| switch_expression: $ => seq( | |
| "switch", "(", field("switched_expr", $._expression), ")", "{", | |
| optional_comma_list($.switch_prong), "}", | |
| ), | |
| switch_prong: $ => seq( | |
| field("case", $.switch_case), | |
| "=>", optional(field("payload", $.ptr_payload)), | |
| field("body", $._assignment_or_expression), | |
| ), | |
| switch_case: $ => choice( | |
| "else", | |
| comma_list($.switch_item), | |
| ), | |
| switch_item: $ => seq( | |
| field("start_expr", $._expression), | |
| optional(seq("...", field("end_expr", $._expression))), | |
| ), | |
| // Modifiers | |
| call_conv: $ => seq("callconv", "(", field("expr", $._expression), ")"), | |
| export_extern_mod: $ => choice("export",seq("extern", optional($.string_literal_single))), | |
| threadlocal_mod: _ => "threadlocal", | |
| byte_align: $ => seq("align", "(", field("expr", $._expression), ")"), | |
| pointer_align: $ => seq( | |
| "align", "(", field("bytes_expr", $._expression), | |
| optional(seq( | |
| ":", field("bit_range_start", $._expression), ":", | |
| field("bit_range_end", $._expression), | |
| )), | |
| ")", | |
| ), | |
| link_section: $ => seq("linksection", "(", field("expr", $._expression), ")"), | |
| // Payloads | |
| payload: $ => seq("|", $.identifier, "|"), | |
| ptr_payload: $ => seq("|", optional(field("ptr", "*")), $.identifier, "|"), | |
| ptr_index_payload: $ => seq( | |
| "|", optional(field("ptr", "*")), | |
| field("payload_name", $.identifier), optional(seq(",", field("index_name", $.identifier))), "|", | |
| ), | |
| } | |
| }); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment