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 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