Created
December 10, 2022 02:01
-
-
Save jackalcooper/d4ed087872a24bff9e73f48e141bbf7b to your computer and use it in GitHub Desktop.
Zig parser in elixir based on https://github.com/ziglang/zig-spec/blob/master/grammar/grammar.y
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
| defmodule Kinda.ParserHelper do | |
| @moduledoc false | |
| @doc """ | |
| define a parser combinator and variable with same name | |
| """ | |
| defmacro defcv(name, expr) do | |
| quote do | |
| defcombinatorp(unquote(name), unquote(expr)) | |
| Kernel.var!(unquote({name, [], nil})) = parsec(unquote(name)) | |
| _ = Kernel.var!(unquote({name, [], nil})) | |
| end | |
| end | |
| end | |
| defmodule Kinda.Parser do | |
| import NimbleParsec | |
| import Kinda.ParserHelper | |
| # *** forward declare *** | |
| expr = parsec(:expr) | |
| typeexpr = parsec(:typeexpr) | |
| assignexpr = parsec(:assignexpr) | |
| stringlist = parsec(:stringlist) | |
| asminputlist = parsec(:asminputlist) | |
| asmoutputlist = parsec(:asmoutputlist) | |
| ifexpr = parsec(:ifexpr) | |
| ptrpayload = parsec(:ptrpayload) | |
| slicetypestart = parsec(:slicetypestart) | |
| bytealign = parsec(:bytealign) | |
| ptrtypestart = parsec(:ptrtypestart) | |
| arraytypestart = parsec(:arraytypestart) | |
| exprlist = parsec(:exprlist) | |
| containermembers = parsec(:containermembers) | |
| loopexpr = parsec(:loopexpr) | |
| block = parsec(:block) | |
| statement = parsec(:statement) | |
| containerdeclarations = parsec(:containerdeclarations) | |
| topleveldecl = parsec(:topleveldecl) | |
| # *** Tokens *** | |
| defcv( | |
| :container_doc_comment, | |
| string("//!") | |
| |> repeat(ascii_char([?^, ?\n])) | |
| |> repeat(ascii_char([?\s, ?\n])) | |
| |> times(min: 1) | |
| ) | |
| defcv( | |
| :doc_comment, | |
| string("///") | |
| |> repeat(ascii_char([?^, ?\n])) | |
| |> repeat(ascii_char([?\s, ?\n])) | |
| |> times(min: 1) | |
| ) | |
| defcv( | |
| :line_comment, | |
| choice([ | |
| string("//") |> lookahead_not(ascii_char([?!, ?/])) |> repeat(ascii_char([?^, ?\n])), | |
| string("////") |> lookahead_not(ascii_char([?\n])) |> repeat(ascii_char([?^, ?\n])) | |
| ]) | |
| ) | |
| defcv(:skip, choice([ascii_char([?\s, ?\n]), line_comment]) |> repeat) | |
| defcv( | |
| :builtinidentifier, | |
| string("@") | |
| |> ascii_char([?A..?Z, ?a..?z, ?_]) | |
| |> concat(ascii_char([?A..?Z, ?a..?z, ?0..?9, ?_]) |> repeat) | |
| |> concat(skip) | |
| ) | |
| defcv(:ampersand, string("&") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:ampersandequal, string("&=") |> concat(skip)) | |
| defcv( | |
| :asterisk, | |
| string("*") |> lookahead_not(ascii_char([?*, ?%, ?=])) |> concat(skip) | |
| ) | |
| defcv(:asterisk2, string("**") |> concat(skip)) | |
| defcv(:asteriskequal, string("*=") |> concat(skip)) | |
| defcv( | |
| :asteriskpercent, | |
| string("*%") |> lookahead_not(ascii_char([?=])) |> concat(skip) | |
| ) | |
| defcv(:asteriskpercentequal, string("*%=") |> concat(skip)) | |
| defcv(:caret, string("^") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:caretequal, string("^=") |> concat(skip)) | |
| defcv(:colon, string(":") |> concat(skip)) | |
| defcv(:comma, string(",") |> concat(skip)) | |
| defcv(:dot, string(".") |> lookahead_not(ascii_char([?*, ?., ??])) |> concat(skip)) | |
| defcv(:dot2, string("..") |> lookahead_not(ascii_char([?.])) |> concat(skip)) | |
| defcv(:dot3, string("...") |> concat(skip)) | |
| defcv(:dotasterisk, string(".*") |> concat(skip)) | |
| defcv(:dotquestionmark, string(".?") |> concat(skip)) | |
| defcv(:equal, string("=") |> lookahead_not(ascii_char([?>, ?=])) |> concat(skip)) | |
| defcv(:equalequal, string("==") |> concat(skip)) | |
| defcv(:equalrarrow, string("=>") |> concat(skip)) | |
| defcv(:exclamationmark, string("!") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:exclamationmarkequal, string("!=") |> concat(skip)) | |
| defcv(:larrow, string("<") |> lookahead_not(ascii_char([?<, ?=])) |> concat(skip)) | |
| defcv(:larrow2, string("<<") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:larrow2equal, string("<<=") |> concat(skip)) | |
| defcv(:larrowequal, string("<=") |> concat(skip)) | |
| defcv(:lbrace, string("{") |> concat(skip)) | |
| defcv(:lbracket, string("[") |> concat(skip)) | |
| defcv(:lparen, string("(") |> concat(skip)) | |
| defcv(:minus, string("-") |> lookahead_not(ascii_char([?%, ?=, ?>])) |> concat(skip)) | |
| defcv(:minusequal, string("-=") |> concat(skip)) | |
| defcv(:minuspercent, string("-%") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:minuspercentequal, string("-%=") |> concat(skip)) | |
| defcv(:minusrarrow, string("->") |> concat(skip)) | |
| defcv(:percent, string("%") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:percentequal, string("%=") |> concat(skip)) | |
| defcv(:pipe, string("|") |> lookahead_not(ascii_char([?|, ?=])) |> concat(skip)) | |
| defcv(:pipe2, string("||") |> concat(skip)) | |
| defcv(:pipeequal, string("|=") |> concat(skip)) | |
| defcv(:plus, string("+") |> lookahead_not(ascii_char([?%, ?+, ?=])) |> concat(skip)) | |
| defcv(:plus2, string("++") |> concat(skip)) | |
| defcv(:plusequal, string("+=") |> concat(skip)) | |
| defcv(:pluspercent, string("+%") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:pluspercentequal, string("+%=") |> concat(skip)) | |
| defcv(:letterc, string("c") |> concat(skip)) | |
| defcv(:questionmark, string("?") |> concat(skip)) | |
| defcv(:rarrow, string(">") |> lookahead_not(ascii_char([?>, ?=])) |> concat(skip)) | |
| defcv(:rarrow2, string(">>") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:rarrow2equal, string(">>=") |> concat(skip)) | |
| defcv(:rarrowequal, string(">=") |> concat(skip)) | |
| defcv(:rbrace, string("}") |> concat(skip)) | |
| defcv(:rbracket, string("]") |> concat(skip)) | |
| defcv(:rparen, string(")") |> concat(skip)) | |
| defcv(:semicolon, string(";") |> concat(skip)) | |
| defcv(:slash, string("/") |> lookahead_not(ascii_char([?=])) |> concat(skip)) | |
| defcv(:slashequal, string("/=") |> concat(skip)) | |
| defcv(:tilde, string("~") |> concat(skip)) | |
| defcv( | |
| :end_of_word, | |
| lookahead_not(ascii_char([?a..?z, ?A..?Z, ?0..?9, ?_])) |> concat(skip) | |
| ) | |
| defcv(:keyword_align, string("align") |> concat(end_of_word)) | |
| defcv(:keyword_allowzero, string("allowzero") |> concat(end_of_word)) | |
| defcv(:keyword_and, string("and") |> concat(end_of_word)) | |
| defcv(:keyword_anyframe, string("anyframe") |> concat(end_of_word)) | |
| defcv(:keyword_anytype, string("anytype") |> concat(end_of_word)) | |
| defcv(:keyword_asm, string("asm") |> concat(end_of_word)) | |
| defcv(:keyword_async, string("async") |> concat(end_of_word)) | |
| defcv(:keyword_await, string("await") |> concat(end_of_word)) | |
| defcv(:keyword_break, string("break") |> concat(end_of_word)) | |
| defcv(:keyword_callconv, string("callconv") |> concat(end_of_word)) | |
| defcv(:keyword_catch, string("catch") |> concat(end_of_word)) | |
| defcv(:keyword_comptime, string("comptime") |> concat(end_of_word)) | |
| defcv(:keyword_const, string("const") |> concat(end_of_word)) | |
| defcv(:keyword_continue, string("continue") |> concat(end_of_word)) | |
| defcv(:keyword_defer, string("defer") |> concat(end_of_word)) | |
| defcv(:keyword_else, string("else") |> concat(end_of_word)) | |
| defcv(:keyword_enum, string("enum") |> concat(end_of_word)) | |
| defcv(:keyword_errdefer, string("errdefer") |> concat(end_of_word)) | |
| defcv(:keyword_error, string("error") |> concat(end_of_word)) | |
| defcv(:keyword_export, string("export") |> concat(end_of_word)) | |
| defcv(:keyword_extern, string("extern") |> concat(end_of_word)) | |
| defcv(:keyword_fn, string("fn") |> concat(end_of_word)) | |
| defcv(:keyword_for, string("for") |> concat(end_of_word)) | |
| defcv(:keyword_if, string("if") |> concat(end_of_word)) | |
| defcv(:keyword_inline, string("inline") |> concat(end_of_word)) | |
| defcv(:keyword_noalias, string("noalias") |> concat(end_of_word)) | |
| defcv(:keyword_nosuspend, string("nosuspend") |> concat(end_of_word)) | |
| defcv(:keyword_noinline, string("noinline") |> concat(end_of_word)) | |
| defcv(:keyword_opaque, string("opaque") |> concat(end_of_word)) | |
| defcv(:keyword_or, string("or") |> concat(end_of_word)) | |
| defcv(:keyword_orelse, string("orelse") |> concat(end_of_word)) | |
| defcv(:keyword_packed, string("packed") |> concat(end_of_word)) | |
| defcv(:keyword_pub, string("pub") |> concat(end_of_word)) | |
| defcv(:keyword_resume, string("resume") |> concat(end_of_word)) | |
| defcv(:keyword_return, string("return") |> concat(end_of_word)) | |
| defcv(:keyword_linksection, string("linksectio") |> concat(end_of_word)) | |
| defcv(:keyword_struct, string("struct") |> concat(end_of_word)) | |
| defcv(:keyword_suspend, string("suspend") |> concat(end_of_word)) | |
| defcv(:keyword_switch, string("switch") |> concat(end_of_word)) | |
| defcv(:keyword_test, string("test") |> concat(end_of_word)) | |
| defcv(:keyword_threadlocal, string("threadloca") |> concat(end_of_word)) | |
| defcv(:keyword_try, string("try") |> concat(end_of_word)) | |
| defcv(:keyword_union, string("union") |> concat(end_of_word)) | |
| defcv(:keyword_unreachable, string("unreachabl") |> concat(end_of_word)) | |
| defcv(:keyword_usingnamespace, string("usingnamespac") |> concat(end_of_word)) | |
| defcv(:keyword_var, string("var") |> concat(end_of_word)) | |
| defcv(:keyword_volatile, string("volatile") |> concat(end_of_word)) | |
| defcv(:keyword_while, string("while") |> concat(end_of_word)) | |
| defcv( | |
| :keyword, | |
| choice([ | |
| keyword_align, | |
| keyword_allowzero, | |
| keyword_and, | |
| keyword_anyframe, | |
| keyword_anytype, | |
| keyword_asm, | |
| keyword_async, | |
| keyword_await, | |
| keyword_break, | |
| keyword_callconv, | |
| keyword_catch, | |
| keyword_comptime, | |
| keyword_const, | |
| keyword_continue, | |
| keyword_defer, | |
| keyword_else, | |
| keyword_enum, | |
| keyword_errdefer, | |
| keyword_error, | |
| keyword_export, | |
| keyword_extern, | |
| keyword_fn, | |
| keyword_for, | |
| keyword_if, | |
| keyword_inline, | |
| keyword_noalias, | |
| keyword_nosuspend, | |
| keyword_noinline, | |
| keyword_opaque, | |
| keyword_or, | |
| keyword_orelse, | |
| keyword_packed, | |
| keyword_pub, | |
| keyword_resume, | |
| keyword_return, | |
| keyword_linksection, | |
| keyword_struct, | |
| keyword_suspend, | |
| keyword_switch, | |
| keyword_test, | |
| keyword_threadlocal, | |
| keyword_try, | |
| keyword_union, | |
| keyword_unreachable, | |
| keyword_usingnamespace, | |
| keyword_var, | |
| keyword_volatile, | |
| keyword_while | |
| ]) | |
| ) | |
| defcv(:eof, eos()) | |
| defcv(:bin, ascii_char([?0..?1])) | |
| defcv(:bin_, optional(string("_")) |> concat(bin)) | |
| defcv(:oct, ascii_char([?0..?7])) | |
| defcv(:oct_, optional(string("_")) |> concat(oct)) | |
| defcv(:hex, ascii_char([?0..?9, ?a..?f, ?A..?F])) | |
| defcv(:hex_, optional(string("_")) |> concat(hex)) | |
| defcv(:dec, ascii_char([?0..?9])) | |
| defcv(:dec_, optional(string("_")) |> concat(dec)) | |
| defcv(:bin_int, bin |> concat(repeat(bin_))) | |
| defcv(:oct_int, oct |> concat(repeat(oct_))) | |
| defcv(:dec_int, dec |> concat(repeat(dec_))) | |
| defcv(:hex_int, hex |> concat(repeat(hex_))) | |
| defcv(:mb_utf8_literal, utf8_char([])) | |
| defcv( | |
| :ascii_char_not_nl_slash_squote, | |
| ascii_char([0..11, 13..46, 46..50, 50..133, 135..177]) | |
| ) | |
| defcv( | |
| :char_escape, | |
| choice([ | |
| string("\\x") |> concat(hex) |> concat(hex), | |
| string("\\u") |> concat(times(hex, min: 1)) |> concat(string("}")), | |
| string("\\") |> concat(hex) |> concat(ascii_char([?n, ?r, ?\\, ?t, ?', ?"])) | |
| ]) | |
| ) | |
| defcv( | |
| :char_char, | |
| choice([ | |
| mb_utf8_literal, | |
| char_escape, | |
| ascii_char_not_nl_slash_squote | |
| ]) | |
| ) | |
| defcv(:string_char, choice([char_escape, ascii_char([?^, ?\\, ?", ?\n])])) | |
| defcv( | |
| :line_string, | |
| string("\\\\") | |
| |> concat(ascii_char([?^, ?\n]) |> repeat) | |
| |> concat(ascii_char([?\s, ?\n]) |> repeat) | |
| |> repeat | |
| ) | |
| defcv(:char_literal, string("'") |> concat(char_char) |> string("'") |> concat(skip)) | |
| defcv( | |
| :float, | |
| choice([ | |
| string("0x") | |
| |> concat(hex_int) | |
| |> string(".") | |
| |> concat(hex_int) | |
| |> optional(ascii_char([?p, ?P]) |> optional(ascii_char([?-, ?+])) |> concat(hex_int)) | |
| |> concat(skip), | |
| dec_int | |
| |> string(".") | |
| |> concat(dec_int) | |
| |> optional(ascii_char([?e, ?E]) |> optional(ascii_char([?-, ?+])) |> concat(dec_int)) | |
| |> concat(skip), | |
| string("0x") | |
| |> concat(hex_int) | |
| |> ascii_char([?p, ?P]) | |
| |> optional(ascii_char([?-, ?+])) | |
| |> concat(dec_int) | |
| |> concat(skip), | |
| dec_int | |
| |> ascii_char([?e, ?E]) | |
| |> optional(ascii_char([?-, ?+])) | |
| |> concat(dec_int) | |
| |> concat(skip) | |
| ]) | |
| ) | |
| defcv( | |
| :integer, | |
| choice([ | |
| string("0b") |> concat(bin_int) |> concat(skip), | |
| string("0o") |> concat(oct_int) |> concat(skip), | |
| string("0x") |> concat(hex_int) |> concat(skip), | |
| dec_int |> concat(skip) | |
| ]) | |
| ) | |
| defcv( | |
| :stringliteralsingle, | |
| string("\"") |> concat(repeat(string_char)) |> concat(string("\"")) |> concat(skip) | |
| ) | |
| defcv( | |
| :stringliteral, | |
| choice([ | |
| stringliteralsingle, | |
| line_string |> concat(skip) |> times(min: 1) | |
| ]) | |
| ) | |
| defcv( | |
| :identifier, | |
| choice([ | |
| lookahead_not(keyword) | |
| |> concat(ascii_char([?a..?z, ?A..?Z, ?_])) | |
| |> concat(ascii_char([?A..?Z, ?a..?z, ?0..?9, ?_]) |> repeat) | |
| |> concat(skip), | |
| string("@\"") |> concat(string_char |> repeat) |> concat(string("\"")) |> concat(skip) | |
| ]) | |
| ) | |
| # *** assembly *** | |
| defcv(:asmclobbers, colon |> concat(stringlist)) | |
| defcv(:asminput, colon |> concat(asminputlist) |> optional(asmclobbers)) | |
| defcv(:asmoutput, colon |> concat(asmoutputlist) |> optional(asminput)) | |
| defcv( | |
| :asmexpr, | |
| keyword_asm | |
| |> optional(keyword_volatile) | |
| |> concat(lparen) | |
| |> concat(expr) | |
| |> optional(asmoutput) | |
| |> concat(rparen) | |
| ) | |
| defcv( | |
| :asmoutputitem, | |
| lbracket | |
| |> concat(identifier) | |
| |> concat(rbracket) | |
| |> concat(stringliteral) | |
| |> concat(lparen) | |
| |> concat(minusrarrow |> choice([typeexpr, identifier])) | |
| |> concat(rparen) | |
| ) | |
| defcv( | |
| :asminputitem, | |
| lbracket | |
| |> concat(identifier) | |
| |> concat(rbracket) | |
| |> concat(stringliteral) | |
| |> concat(lparen) | |
| |> concat(expr) | |
| |> concat(rparen) | |
| ) | |
| # *** helper grammar *** | |
| defcv(:breaklabel, colon |> concat(identifier)) | |
| defcv(:blocklabel, identifier |> concat(colon)) | |
| defcv(:fieldinit, dot |> concat(identifier) |> concat(equal) |> concat(expr)) | |
| defcv( | |
| :whilecontinueexpr, | |
| colon |> concat(lparen) |> concat(assignexpr) |> concat(rparen) | |
| ) | |
| defcv( | |
| :linksection, | |
| keyword_linksection |> concat(lparen) |> concat(expr) |> concat(rparen) | |
| ) | |
| # fn specific | |
| defcv(:callconv, keyword_callconv |> concat(lparen) |> concat(expr) |> concat(rparen)) | |
| defcv(:paramtype, choice([keyword_anytype, typeexpr])) | |
| defcv( | |
| :paramdecl, | |
| choice([ | |
| optional(doc_comment) | |
| |> optional(choice([keyword_noalias, keyword_comptime])) | |
| |> optional(identifier |> concat(colon)) | |
| |> concat(paramtype), | |
| dot3 | |
| ]) | |
| ) | |
| # control flow prefixes | |
| defcv( | |
| :ifprefix, | |
| keyword_if |> concat(lparen) |> concat(expr) |> concat(rparen) |> optional(ptrpayload) | |
| ) | |
| defcv( | |
| :whileprefix, | |
| keyword_while | |
| |> concat(lparen) | |
| |> concat(expr) | |
| |> concat(rparen) | |
| |> optional(ptrpayload) | |
| |> optional(whilecontinueexpr) | |
| ) | |
| defcv( | |
| :ptrindexpayload, | |
| pipe | |
| |> optional(asterisk) | |
| |> concat(identifier) | |
| |> optional(comma |> concat(identifier)) | |
| |> concat(pipe) | |
| ) | |
| defcv( | |
| :forprefix, | |
| keyword_for |> concat(lparen) |> concat(expr) |> concat(rparen) |> concat(ptrindexpayload) | |
| ) | |
| # payloads | |
| defcv(:payload, pipe |> concat(identifier) |> concat(pipe)) | |
| defcv(:ptrpayload, pipe |> optional(asterisk) |> concat(identifier) |> concat(pipe)) | |
| # switch specific | |
| defcv(:switchitem, expr |> optional(dot3 |> concat(expr))) | |
| defcv( | |
| :switchcase, | |
| choice([ | |
| switchitem |> repeat(comma |> concat(switchitem)) |> optional(comma), | |
| keyword_else | |
| ]) | |
| ) | |
| defcv( | |
| :switchprong, | |
| switchcase |> concat(equalrarrow) |> optional(ptrpayload) |> concat(assignexpr) | |
| ) | |
| # operators | |
| defcv( | |
| :assignop, | |
| choice([ | |
| asteriskequal, | |
| slashequal, | |
| percentequal, | |
| plusequal, | |
| minusequal, | |
| larrow2equal, | |
| rarrow2equal, | |
| ampersandequal, | |
| caretequal, | |
| pipeequal, | |
| asteriskpercentequal, | |
| pluspercentequal, | |
| minuspercentequal, | |
| equal | |
| ]) | |
| ) | |
| defcv( | |
| :compareop, | |
| choice([ | |
| equalequal, | |
| exclamationmarkequal, | |
| larrow, | |
| rarrow, | |
| larrowequal, | |
| rarrowequal | |
| ]) | |
| ) | |
| defcv( | |
| :bitwiseop, | |
| choice([ampersand, caret, pipe, keyword_orelse, keyword_catch |> optional(payload)]) | |
| ) | |
| defcv(:bitshiftop, choice([larrow2, rarrow2])) | |
| defcv( | |
| :additionop, | |
| choice([ | |
| plus, | |
| minus, | |
| plus2, | |
| pluspercent, | |
| minuspercent | |
| ]) | |
| ) | |
| defcv( | |
| :multiplyop, | |
| choice([ | |
| pipe2, | |
| asterisk, | |
| slash, | |
| percent, | |
| asterisk2, | |
| asteriskpercent | |
| ]) | |
| ) | |
| defcv( | |
| :prefixop, | |
| choice([ | |
| exclamationmark, | |
| minus, | |
| tilde, | |
| minuspercent, | |
| ampersand, | |
| keyword_try, | |
| keyword_await | |
| ]) | |
| ) | |
| defcv( | |
| :prefixtypeop, | |
| choice([ | |
| questionmark, | |
| keyword_anyframe |> concat(minusrarrow), | |
| slicetypestart | |
| |> repeat(choice([bytealign, keyword_const, keyword_volatile, keyword_allowzero])), | |
| ptrtypestart | |
| |> repeat( | |
| keyword_align | |
| |> concat(lparen) | |
| |> concat(expr) | |
| |> optional(colon |> concat(integer) |> concat(colon) |> concat(integer)) | |
| |> choice([rparen, keyword_const, keyword_volatile, keyword_allowzero]) | |
| ), | |
| arraytypestart | |
| ]) | |
| ) | |
| defcv( | |
| :suffixop, | |
| choice([ | |
| lbracket | |
| |> concat(expr) | |
| |> optional(dot2 |> optional(optional(expr) |> optional(colon |> concat(expr)))) | |
| |> concat(rbracket), | |
| dot |> concat(identifier), | |
| dotasterisk, | |
| dotquestionmark | |
| ]) | |
| ) | |
| defcv(:fncallarguments, lparen |> concat(exprlist) |> concat(rparen)) | |
| # ptr specific | |
| defcv(:slicetypestart, lbracket |> optional(colon |> concat(expr)) |> concat(rbracket)) | |
| defcv( | |
| :ptrtypestart, | |
| choice([ | |
| asterisk, | |
| asterisk2, | |
| lbracket | |
| |> concat(asterisk) | |
| |> optional(choice([letterc, colon |> concat(expr)])) | |
| |> concat(rbracket) | |
| ]) | |
| ) | |
| defcv( | |
| :arraytypestart, | |
| lbracket |> concat(expr) |> optional(colon |> concat(expr)) |> concat(rbracket) | |
| ) | |
| # containerdecl specific | |
| defcv( | |
| :containerdecltype, | |
| choice([ | |
| keyword_struct, | |
| keyword_opaque, | |
| keyword_enum |> optional(lparen |> concat(expr) |> concat(rparen)), | |
| keyword_union | |
| |> optional( | |
| lparen | |
| |> concat( | |
| keyword_enum | |
| |> choice([optional(lparen |> concat(expr) |> concat(rparen)), expr]) | |
| ) | |
| |> concat(rparen) | |
| ) | |
| ]) | |
| ) | |
| defcv( | |
| :containerdeclauto, | |
| containerdecltype | |
| |> concat(lbrace) | |
| |> optional(container_doc_comment) | |
| |> concat(containermembers) | |
| |> concat(rbrace) | |
| ) | |
| # alignment | |
| defcv(:bytealign, keyword_align |> concat(lparen) |> concat(expr) |> concat(rparen)) | |
| # lists | |
| defcv( | |
| :identifierlist, | |
| repeat(optional(doc_comment) |> concat(identifier) |> concat(comma)) | |
| |> optional(optional(doc_comment) |> concat(identifier)) | |
| ) | |
| defcv(:switchpronglist, repeat(switchprong |> concat(comma)) |> optional(switchprong)) | |
| defcv( | |
| :asmoutputlist, | |
| repeat(asmoutputitem |> concat(comma)) |> optional(asmoutputitem) | |
| ) | |
| defcv(:asminputlist, repeat(asminputitem |> concat(comma)) |> optional(asminputitem)) | |
| defcv(:stringlist, repeat(stringliteral |> concat(comma)) |> optional(stringliteral)) | |
| defcv(:paramdecllist, repeat(paramdecl |> concat(comma)) |> optional(paramdecl)) | |
| defcv(:exprlist, repeat(expr |> concat(comma)) |> optional(expr)) | |
| # *** expression level *** | |
| defcv( | |
| :initlist, | |
| choice([ | |
| lbrace | |
| |> concat(fieldinit) | |
| |> repeat(comma |> concat(fieldinit)) | |
| |> optional(comma) | |
| |> concat(rbrace), | |
| lbrace | |
| |> concat(expr) | |
| |> repeat(comma |> concat(expr)) | |
| |> optional(comma) | |
| |> concat(rbrace), | |
| lbrace |> concat(rbrace) | |
| ]) | |
| ) | |
| defcv(:curlysuffixexpr, typeexpr |> optional(initlist)) | |
| defcv( | |
| :primaryexpr, | |
| choice([ | |
| asmexpr, | |
| ifexpr, | |
| keyword_break |> optional(breaklabel) |> optional(expr), | |
| keyword_comptime |> concat(expr), | |
| keyword_nosuspend |> concat(expr), | |
| keyword_continue |> optional(breaklabel), | |
| keyword_resume |> concat(expr), | |
| keyword_return |> optional(expr), | |
| optional(blocklabel) |> concat(loopexpr), | |
| block, | |
| curlysuffixexpr | |
| ]) | |
| ) | |
| defcv(:prefixexpr, repeat(prefixop) |> concat(primaryexpr)) | |
| defcv(:multiplyexpr, prefixexpr |> optional(multiplyop |> concat(prefixexpr))) | |
| defcv(:additionexpr, multiplyexpr |> optional(additionop |> concat(multiplyexpr))) | |
| defcv(:bitshiftexpr, additionexpr |> optional(bitshiftop |> concat(additionexpr))) | |
| defcv(:bitwiseexpr, bitshiftexpr |> optional(bitwiseop |> concat(bitshiftexpr))) | |
| defcv(:compareexpr, bitwiseexpr |> optional(compareop |> concat(bitwiseexpr))) | |
| defcv(:boolandexpr, compareexpr |> optional(keyword_and |> concat(compareexpr))) | |
| defcv(:boolorexpr, boolandexpr |> optional(keyword_or |> concat(boolandexpr))) | |
| defcv(:expr, boolorexpr) | |
| defcv(:assignexpr, expr |> optional(assignop |> concat(expr))) | |
| defcv( | |
| :ifexpr, | |
| ifprefix |> concat(expr) |> optional(keyword_else |> optional(payload) |> concat(expr)) | |
| ) | |
| defcv(:block, lbrace |> repeat(statement) |> concat(rbrace)) | |
| defcv(:forexpr, forprefix |> concat(expr) |> optional(keyword_else |> concat(expr))) | |
| defcv( | |
| :whileexpr, | |
| whileprefix |> concat(expr) |> optional(keyword_else |> optional(payload) |> concat(expr)) | |
| ) | |
| defcv(:loopexpr, optional(keyword_inline) |> choice([forexpr, whileexpr])) | |
| defcv( | |
| :containerdecl, | |
| optional(choice([keyword_extern, keyword_packed])) |> concat(containerdeclauto) | |
| ) | |
| defcv( | |
| :errorsetdecl, | |
| keyword_error |> concat(lbrace) |> concat(identifierlist) |> concat(rbrace) | |
| ) | |
| defcv( | |
| :fnproto, | |
| keyword_fn | |
| |> optional(identifier) | |
| |> concat(lparen) | |
| |> concat(paramdecllist) | |
| |> concat(rparen) | |
| |> optional(bytealign) | |
| |> optional(linksection) | |
| |> optional(callconv) | |
| |> optional(exclamationmark) | |
| |> concat(typeexpr) | |
| ) | |
| defcv(:groupedexpr, lparen |> concat(expr) |> concat(rparen)) | |
| defcv( | |
| :fortypeexpr, | |
| forprefix |> concat(typeexpr) |> optional(keyword_else |> concat(typeexpr)) | |
| ) | |
| defcv( | |
| :whiletypeexpr, | |
| whileprefix | |
| |> concat(typeexpr) | |
| |> optional(keyword_else |> optional(payload) |> concat(typeexpr)) | |
| ) | |
| defcv(:looptypeexpr, optional(keyword_inline) |> choice([fortypeexpr, whiletypeexpr])) | |
| defcv( | |
| :labeledtypeexpr, | |
| choice([ | |
| blocklabel |> concat(block), | |
| optional(blocklabel) |> concat(looptypeexpr) | |
| ]) | |
| ) | |
| defcv( | |
| :iftypeexpr, | |
| ifprefix | |
| |> concat(typeexpr) | |
| |> optional(keyword_else |> optional(payload) |> concat(typeexpr)) | |
| ) | |
| defcv( | |
| :switchexpr, | |
| keyword_switch | |
| |> concat(lparen) | |
| |> concat(expr) | |
| |> concat(rparen) | |
| |> concat(lbrace) | |
| |> concat(switchpronglist) | |
| |> concat(rbrace) | |
| ) | |
| defcv( | |
| :primarytypeexpr, | |
| choice([ | |
| builtinidentifier |> concat(fncallarguments), | |
| char_literal, | |
| containerdecl, | |
| dot |> concat(identifier), | |
| dot |> concat(initlist), | |
| errorsetdecl, | |
| float, | |
| fnproto, | |
| groupedexpr, | |
| labeledtypeexpr, | |
| identifier, | |
| iftypeexpr, | |
| integer, | |
| keyword_comptime |> concat(typeexpr), | |
| keyword_error |> concat(dot) |> concat(identifier), | |
| keyword_anyframe, | |
| keyword_unreachable, | |
| stringliteral, | |
| switchexpr | |
| ]) | |
| ) | |
| defcv( | |
| :suffixexpr, | |
| choice([ | |
| keyword_async |> concat(primarytypeexpr) |> repeat(suffixop) |> concat(fncallarguments), | |
| primarytypeexpr |> repeat(choice([suffixop, fncallarguments])) | |
| ]) | |
| ) | |
| defcv(:errorunionexpr, suffixexpr |> optional(exclamationmark |> concat(typeexpr))) | |
| defcv(:typeexpr, repeat(prefixtypeop) |> concat(errorunionexpr)) | |
| # *** Top level *** | |
| defcv( | |
| :testdecl, | |
| optional(doc_comment) | |
| |> concat(keyword_test) | |
| |> concat(optional(stringliteralsingle)) | |
| |> concat(block) | |
| ) | |
| defcv( | |
| :toplevelcomptime, | |
| optional(doc_comment) |> concat(keyword_comptime) |> concat(block) | |
| ) | |
| defcv( | |
| :containerdeclarations, | |
| choice([ | |
| testdecl |> concat(containerdeclarations), | |
| toplevelcomptime |> concat(containerdeclarations), | |
| optional(doc_comment) | |
| |> optional(keyword_pub) | |
| |> concat(topleveldecl) | |
| |> concat(containerdeclarations) | |
| ]) | |
| ) | |
| defcv( | |
| :containerfield, | |
| optional(doc_comment) | |
| |> optional(keyword_comptime) | |
| |> concat(identifier) | |
| |> optional(colon |> concat(typeexpr) |> optional(bytealign)) | |
| |> optional(equal |> concat(expr)) | |
| ) | |
| defcv( | |
| :containermembers, | |
| containerdeclarations | |
| |> repeat(containerfield |> concat(comma)) | |
| |> choice([containerfield, containerdeclarations]) | |
| ) | |
| defcv( | |
| :vardecl, | |
| choice([keyword_const, keyword_var]) | |
| |> concat(identifier) | |
| |> optional(colon |> concat(typeexpr)) | |
| |> optional(bytealign) | |
| |> optional(linksection) | |
| |> optional(equal |> concat(expr)) | |
| |> concat(semicolon) | |
| ) | |
| defcv( | |
| :topleveldecl, | |
| choice([ | |
| choice([ | |
| keyword_export, | |
| keyword_extern |> optional(stringliteralsingle), | |
| choice([keyword_inline, keyword_noinline]) | |
| ]) | |
| |> optional | |
| |> concat(fnproto) | |
| |> choice([semicolon, block]), | |
| choice([keyword_export, keyword_extern |> optional(stringliteralsingle)]) | |
| |> optional | |
| |> optional(keyword_threadlocal) | |
| |> concat(vardecl), | |
| keyword_usingnamespace |> concat(expr) |> concat(semicolon) | |
| ]) | |
| ) | |
| # *** block level *** | |
| defcv(:blockexpr, optional(blocklabel) |> concat(block)) | |
| defcv(:blockexprstatement, choice([blockexpr, assignexpr |> concat(semicolon)])) | |
| defcv( | |
| :ifstatement, | |
| choice([ | |
| ifprefix | |
| |> concat(blockexpr) | |
| |> optional(keyword_else |> optional(payload) |> concat(statement)), | |
| ifprefix | |
| |> concat(assignexpr) | |
| |> choice([semicolon, keyword_else |> optional(payload) |> concat(statement)]) | |
| ]) | |
| ) | |
| defcv( | |
| :forstatement, | |
| choice([ | |
| forprefix |> concat(blockexpr) |> optional(keyword_else |> concat(statement)), | |
| forprefix |> concat(assignexpr) |> choice([semicolon, keyword_else |> concat(statement)]) | |
| ]) | |
| ) | |
| defcv( | |
| :whilestatement, | |
| choice([ | |
| whileprefix | |
| |> concat(blockexpr) | |
| |> optional(keyword_else |> optional(payload) |> concat(statement)), | |
| whileprefix | |
| |> concat(assignexpr) | |
| |> choice([semicolon, keyword_else |> optional(payload) |> concat(statement)]) | |
| ]) | |
| ) | |
| defcv( | |
| :loopstatement, | |
| optional(keyword_inline) |> choice([forstatement, whilestatement]) | |
| ) | |
| defcv(:labeledstatement, optional(blocklabel) |> choice([block, loopstatement])) | |
| defcv( | |
| :statement, | |
| choice([ | |
| optional(keyword_comptime) |> concat(vardecl), | |
| keyword_comptime |> concat(blockexprstatement), | |
| keyword_nosuspend |> concat(blockexprstatement), | |
| keyword_suspend |> concat(blockexprstatement), | |
| keyword_defer |> concat(blockexprstatement), | |
| keyword_errdefer |> optional(payload) |> concat(blockexprstatement), | |
| ifstatement, | |
| labeledstatement, | |
| switchexpr, | |
| assignexpr |> concat(semicolon) | |
| ]) | |
| ) | |
| defcv( | |
| :root, | |
| skip |> optional(container_doc_comment) |> concat(containermembers) |> concat(eof) | |
| ) | |
| defparsec(:zig_src, root, debug: true) | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment