Skip to content

Instantly share code, notes, and snippets.

@jackalcooper
Created December 9, 2022 08:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jackalcooper/73eed504164250f84a106b6950527eac to your computer and use it in GitHub Desktop.
Save jackalcooper/73eed504164250f84a106b6950527eac to your computer and use it in GitHub Desktop.
defmodule Kinda.Parser do
import NimbleParsec
# *** Tokens ***
container_doc_comment =
string("//!") |> repeat(ascii_char([?^, ?\n])) |> repeat([?\s, ?\n]) |> times(min: 1)
doc_comment =
string("///") |> repeat(ascii_char([?^, ?\n])) |> repeat([?\s, ?\n]) |> times(min: 1)
line_comment =
choice([
string("//") |> lookahead_not(ascii_char([?!, ?/])) |> repeat(ascii_char([?^, ?\n])),
string("////") |> lookahead_not(ascii_char([?\n])) |> repeat(ascii_char([?^, ?\n]))
])
skip = choice([ascii_char([?\s, ?\n]), line_comment]) |> repeat
builtinidentifier =
string("@")
|> ascii_char([?A..?Z, ?a..?z, ?_])
|> concat(ascii_char([?A..?Z, ?a..?z, ?0..?9, ?_]) |> repeat)
|> concat(skip)
ampersand = string("&") |> lookahead_not(ascii_char([?=])) |> concat(skip)
ampersandequal = string("&=") |> concat(skip)
asterisk = string("*") |> lookahead_not(ascii_char([?*, ?%, ?=])) |> concat(skip)
asterisk2 = string("**") |> concat(skip)
asteriskequal = string("*=") |> concat(skip)
asteriskpercent = string("*%") |> lookahead_not(ascii_char([?=])) |> concat(skip)
asteriskpercentequal = string("*%=") |> concat(skip)
caret = string("^") |> lookahead_not(ascii_char([?=])) |> concat(skip)
caretequal = string("^=") |> concat(skip)
colon = string(":") |> concat(skip)
comma = string(",") |> concat(skip)
dot = string(".") |> lookahead_not(ascii_char([?*, ?., ??])) |> concat(skip)
dot2 = string("..") |> lookahead_not(ascii_char([?.])) |> concat(skip)
dot3 = string("...") |> concat(skip)
dotasterisk = string(".*") |> concat(skip)
dotquestionmark = string(".?") |> concat(skip)
equal = string("=") |> lookahead_not(ascii_char([?>, ?=])) |> concat(skip)
equalequal = string("==") |> concat(skip)
equalrarrow = string("=>") |> concat(skip)
exclamationmark = string("!") |> lookahead_not(ascii_char([?=])) |> concat(skip)
exclamationmarkequal = string("!=") |> concat(skip)
larrow = string("<") |> lookahead_not(ascii_char([?<, ?=])) |> concat(skip)
larrow2 = string("<<") |> lookahead_not(ascii_char([?=])) |> concat(skip)
larrow2equal = string("<<=") |> concat(skip)
larrowequal = string("<=") |> concat(skip)
lbrace = string("{") |> concat(skip)
lbracket = string("[") |> concat(skip)
lparen = string("(") |> concat(skip)
minus = string("-") |> lookahead_not(ascii_char([?%, ?=, ?>])) |> concat(skip)
minusequal = string("-=") |> concat(skip)
minuspercent = string("-%") |> lookahead_not(ascii_char([?=])) |> concat(skip)
minuspercentequal = string("-%=") |> concat(skip)
minusrarrow = string("->") |> concat(skip)
percent = string("%") |> lookahead_not(ascii_char([?=])) |> concat(skip)
percentequal = string("%=") |> concat(skip)
pipe = string("|") |> lookahead_not(ascii_char([?|, ?=])) |> concat(skip)
pipe2 = string("||") |> concat(skip)
pipeequal = string("|=") |> concat(skip)
plus = string("+") |> lookahead_not(ascii_char([?%, ?+, ?=])) |> concat(skip)
plus2 = string("++") |> concat(skip)
plusequal = string("+=") |> concat(skip)
pluspercent = string("+%") |> lookahead_not(ascii_char([?=])) |> concat(skip)
pluspercentequal = string("+%=") |> concat(skip)
letterc = string("c") |> concat(skip)
questionmark = string("?") |> concat(skip)
rarrow = string(">") |> lookahead_not(ascii_char([?>, ?=])) |> concat(skip)
rarrow2 = string(">>") |> lookahead_not(ascii_char([?=])) |> concat(skip)
rarrow2equal = string(">>=") |> concat(skip)
rarrowequal = string(">=") |> concat(skip)
rbrace = string("}") |> concat(skip)
rbracket = string("]") |> concat(skip)
rparen = string(")") |> concat(skip)
semicolon = string(";") |> concat(skip)
slash = string("/") |> lookahead_not(ascii_char([?=])) |> concat(skip)
slashequal = string("/=") |> concat(skip)
tilde = string("~") |> concat(skip)
end_of_word = lookahead_not(ascii_char([?a..?z, ?A..?Z, ?0..?9, ?_])) |> concat(skip)
keyword_align = string("align") |> concat(end_of_word)
keyword_allowzero = string("allowzero") |> concat(end_of_word)
keyword_and = string("and") |> concat(end_of_word)
keyword_anyframe = string("anyframe") |> concat(end_of_word)
keyword_anytype = string("anytype") |> concat(end_of_word)
keyword_asm = string("asm") |> concat(end_of_word)
keyword_async = string("async") |> concat(end_of_word)
keyword_await = string("await") |> concat(end_of_word)
keyword_break = string("break") |> concat(end_of_word)
keyword_callconv = string("callconv") |> concat(end_of_word)
keyword_catch = string("catch") |> concat(end_of_word)
keyword_comptime = string("comptime") |> concat(end_of_word)
keyword_const = string("const") |> concat(end_of_word)
keyword_continue = string("continue") |> concat(end_of_word)
keyword_defer = string("defer") |> concat(end_of_word)
keyword_else = string("else") |> concat(end_of_word)
keyword_enum = string("enum") |> concat(end_of_word)
keyword_errdefer = string("errdefer") |> concat(end_of_word)
keyword_error = string("error") |> concat(end_of_word)
keyword_export = string("export") |> concat(end_of_word)
keyword_extern = string("extern") |> concat(end_of_word)
keyword_fn = string("fn") |> concat(end_of_word)
keyword_for = string("for") |> concat(end_of_word)
keyword_if = string("if") |> concat(end_of_word)
keyword_inline = string("inline") |> concat(end_of_word)
keyword_noalias = string("noalias") |> concat(end_of_word)
keyword_nosuspend = string("nosuspend") |> concat(end_of_word)
keyword_noinline = string("noinline") |> concat(end_of_word)
keyword_opaque = string("opaque") |> concat(end_of_word)
keyword_or = string("or") |> concat(end_of_word)
keyword_orelse = string("orelse") |> concat(end_of_word)
keyword_packed = string("packed") |> concat(end_of_word)
keyword_pub = string("pub") |> concat(end_of_word)
keyword_resume = string("resume") |> concat(end_of_word)
keyword_return = string("return") |> concat(end_of_word)
keyword_linksection = string("linksectio") |> concat(end_of_word)
keyword_struct = string("struct") |> concat(end_of_word)
keyword_suspend = string("suspend") |> concat(end_of_word)
keyword_switch = string("switch") |> concat(end_of_word)
keyword_test = string("test") |> concat(end_of_word)
keyword_threadlocal = string("threadloca") |> concat(end_of_word)
keyword_try = string("try") |> concat(end_of_word)
keyword_union = string("union") |> concat(end_of_word)
keyword_unreachable = string("unreachabl") |> concat(end_of_word)
keyword_usingnamespace = string("usingnamespac") |> concat(end_of_word)
keyword_var = string("var") |> concat(end_of_word)
keyword_volatile = string("volatile") |> concat(end_of_word)
keyword_while = string("while") |> concat(end_of_word)
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
])
eof = eos()
bin = ascii_char([?0..?1])
bin_ = optional(string("_")) |> concat(bin)
oct = ascii_char([?0..?7])
oct_ = optional(string("_")) |> concat(oct)
hex = ascii_char([?0..?9, ?a..?f, ?A..?F])
hex_ = optional(string("_")) |> concat(hex)
dec = ascii_char([?0..?9])
dec_ = optional(string("_")) |> concat(dec)
bin_int = bin |> concat(repeat(bin_))
oct_int = oct |> concat(repeat(oct_))
dec_int = dec |> concat(repeat(dec_))
hex_int = hex |> concat(repeat(hex_))
mb_utf8_literal = utf8_char([])
ascii_char_not_nl_slash_squote = ascii_char([0..11, 13..46, 46..50, 50..133, 135..177])
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, ?', ?"]))
])
char_char =
choice([
mb_utf8_literal,
char_escape,
ascii_char_not_nl_slash_squote
])
string_char = choice([char_escape, ascii_char([?^, ?\\, ?", ?\n])])
line_string =
string("\\\\")
|> concat(ascii_char([?^, ?\n]) |> repeat)
|> concat(ascii_char([?\s, ?\n]) |> repeat)
|> repeat
char_literal = string("'") |> concat(char_char) |> string("'") |> concat(skip)
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)
])
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)
])
stringliteralsingle =
string("\"") |> concat(repeat(string_char)) |> concat(string("\"")) |> concat(skip)
stringliteral =
choice([
stringliteralsingle,
line_string |> concat(skip) |> times(min: 1)
])
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)
])
# *** forward declare ***
expr = parsec(:expr_parsec)
typeexpr = parsec(:typeexpr_parsec)
assignexpr = parsec(:assignexpr_parsec)
stringlist = parsec(:stringlist_parsec)
asminputlist = parsec(:asminputlist_parsec)
asmoutputlist = parsec(:asmoutputlist_parsec)
ifexpr = parsec(:ifexpr_parsec)
ptrpayload = parsec(:ptrpayload_parsec)
slicetypestart = parsec(:slicetypestart_parsec)
bytealign = parsec(:bytealign_parsec)
ptrtypestart = parsec(:ptrtypestart_parsec)
arraytypestart = parsec(:arraytypestart_parsec)
exprlist = parsec(:exprlist_parsec)
containermembers = parsec(:containermembers_parsec)
loopexpr = parsec(:loopexpr_parsec)
block = parsec(:block_parsec)
statement = parsec(:statement_parsec)
containerdeclarations = parsec(:containerdeclarations_parsec)
topleveldecl = parsec(:topleveldecl_parsec)
# *** assembly ***
asmclobbers = colon |> concat(stringlist)
asminput = colon |> concat(asminputlist) |> optional(asmclobbers)
asmoutput = colon |> concat(asmoutputlist) |> optional(asminput)
asmexpr =
keyword_asm
|> optional(keyword_volatile)
|> concat(lparen)
|> concat(expr)
|> optional(asmoutput)
|> concat(rparen)
asmoutputitem =
lbracket
|> concat(identifier)
|> concat(rbracket)
|> concat(stringliteral)
|> concat(lparen)
|> concat(minusrarrow |> choice([typeexpr, identifier]))
|> concat(rparen)
asminputitem =
lbracket
|> concat(identifier)
|> concat(rbracket)
|> concat(stringliteral)
|> concat(lparen)
|> concat(expr)
|> concat(rparen)
# *** helper grammar ***
breaklabel = colon |> concat(identifier)
blocklabel = identifier |> concat(colon)
fieldinit = dot |> concat(identifier) |> concat(equal) |> concat(expr)
whilecontinueexpr = colon |> concat(lparen) |> concat(assignexpr) |> concat(rparen)
linksection = keyword_linksection |> concat(lparen) |> concat(expr) |> concat(rparen)
# fn specific
callconv = keyword_callconv |> concat(lparen) |> concat(expr) |> concat(rparen)
paramtype = choice([keyword_anytype, typeexpr])
paramdecl =
choice([
optional(doc_comment)
|> optional(choice([keyword_noalias, keyword_comptime]))
|> optional(identifier |> concat(colon))
|> concat(paramtype),
dot3
])
# control flow prefixes
ifprefix =
keyword_if |> concat(lparen) |> concat(expr) |> concat(rparen) |> optional(ptrpayload)
whileprefix =
keyword_while
|> concat(lparen)
|> concat(expr)
|> concat(rparen)
|> optional(ptrpayload)
|> optional(whilecontinueexpr)
ptrindexpayload =
pipe
|> optional(asterisk)
|> concat(identifier)
|> optional(comma |> concat(identifier))
|> concat(pipe)
forprefix =
keyword_for |> concat(lparen) |> concat(expr) |> concat(rparen) |> concat(ptrindexpayload)
# payloads
payload = pipe |> concat(identifier) |> concat(pipe)
ptrpayload = pipe |> optional(asterisk) |> concat(identifier) |> concat(pipe)
# switch specific
switchitem = expr |> optional(dot3 |> concat(expr))
switchcase =
choice([
switchitem |> repeat(comma |> concat(switchitem)) |> optional(comma),
keyword_else
])
switchprong = switchcase |> concat(equalrarrow) |> optional(ptrpayload) |> concat(assignexpr)
# operators
assignop =
choice([
asteriskequal,
slashequal,
percentequal,
plusequal,
minusequal,
larrow2equal,
rarrow2equal,
ampersandequal,
caretequal,
pipeequal,
asteriskpercentequal,
pluspercentequal,
minuspercentequal,
equal
])
compareop =
choice([
equalequal,
exclamationmarkequal,
larrow,
rarrow,
larrowequal,
rarrowequal
])
bitwiseop = choice([ampersand, caret, pipe, keyword_orelse, keyword_catch |> optional(payload)])
bitshiftop = choice([larrow2, rarrow2])
additionop =
choice([
plus,
minus,
plus2,
pluspercent,
minuspercent
])
multiplyop =
choice([
pipe2,
asterisk,
slash,
percent,
asterisk2,
asteriskpercent
])
prefixop =
choice([
exclamationmark,
minus,
tilde,
minuspercent,
ampersand,
keyword_try,
keyword_await
])
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
])
suffixop =
choice([
lbracket
|> concat(expr)
|> optional(dot2 |> optional(optional(expr) |> optional(colon |> concat(expr))))
|> concat(rbracket),
dot |> concat(identifier),
dotasterisk,
dotquestionmark
])
fncallarguments = lparen |> concat(exprlist) |> concat(rparen)
# ptr specific
slicetypestart = lbracket |> optional(colon |> concat(expr)) |> concat(rbracket)
ptrtypestart =
choice([
asterisk,
asterisk2,
lbracket
|> concat(asterisk)
|> optional(choice([letterc, colon |> concat(expr)]))
|> concat(rbracket)
])
arraytypestart = lbracket |> concat(expr) |> optional(colon |> concat(expr)) |> concat(rbracket)
# containerdecl specific
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)
)
])
containerdeclauto =
containerdecltype
|> concat(lbrace)
|> optional(container_doc_comment)
|> concat(containermembers)
|> concat(rbrace)
# alignment
bytealign = keyword_align |> concat(lparen) |> concat(expr) |> concat(rparen)
# lists
identifierlist =
repeat(optional(doc_comment) |> concat(identifier) |> concat(comma))
|> optional(optional(doc_comment) |> concat(identifier))
switchpronglist = repeat(switchprong |> concat(comma)) |> optional(switchprong)
asmoutputlist = repeat(asmoutputitem |> concat(comma)) |> optional(asmoutputitem)
asminputlist = repeat(asminputitem |> concat(comma)) |> optional(asminputitem)
stringlist = repeat(stringliteral |> concat(comma)) |> optional(stringliteral)
paramdecllist = repeat(paramdecl |> concat(comma)) |> optional(paramdecl)
exprlist = repeat(expr |> concat(comma)) |> optional(expr)
# *** expression level ***
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)
])
curlysuffixexpr = typeexpr |> optional(initlist)
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
])
prefixexpr = repeat(prefixop) |> concat(primaryexpr)
multiplyexpr = prefixexpr |> optional(multiplyop |> concat(prefixexpr))
additionexpr = multiplyexpr |> optional(additionop |> concat(multiplyexpr))
bitshiftexpr = additionexpr |> optional(bitshiftop |> concat(additionexpr))
bitwiseexpr = bitshiftexpr |> optional(bitwiseop |> concat(bitshiftexpr))
compareexpr = bitwiseexpr |> optional(compareop |> concat(bitwiseexpr))
boolandexpr = compareexpr |> optional(keyword_and |> concat(compareexpr))
boolorexpr = boolandexpr |> optional(keyword_or |> concat(boolandexpr))
expr = boolorexpr
assignexpr = expr |> optional(assignop |> concat(expr))
ifexpr = ifprefix |> concat(expr) |> optional([keyword_else, optional(payload), expr])
block = lbrace |> repeat(statement) |> concat(rbrace)
forexpr = forprefix |> concat(expr) |> optional(keyword_else |> concat(expr))
whileexpr =
whileprefix |> concat(expr) |> optional(keyword_else |> optional(payload) |> concat(expr))
loopexpr = optional(keyword_inline) |> choice([forexpr, whileexpr])
containerdecl = optional(choice([keyword_extern, keyword_packed])) |> concat(containerdeclauto)
errorsetdecl = keyword_error |> concat(lbrace) |> concat(identifierlist) |> concat(rbrace)
fnproto =
keyword_fn
|> optional(identifier)
|> concat(lparen)
|> concat(paramdecllist)
|> concat(rparen)
|> optional(bytealign)
|> optional(linksection)
|> optional(callconv)
|> optional(exclamationmark)
|> concat(typeexpr)
groupedexpr = lparen |> concat(expr) |> concat(rparen)
fortypeexpr = forprefix |> concat(typeexpr) |> optional(keyword_else |> concat(typeexpr))
whiletypeexpr =
whileprefix
|> concat(typeexpr)
|> optional(keyword_else |> optional(payload) |> concat(typeexpr))
looptypeexpr = optional(keyword_inline) |> choice([fortypeexpr, whiletypeexpr])
labeledtypeexpr =
choice([
blocklabel |> concat(block),
optional(blocklabel) |> concat(looptypeexpr)
])
iftypeexpr =
ifprefix
|> concat(typeexpr)
|> optional(keyword_else |> optional(payload) |> concat(typeexpr))
switchexpr =
keyword_switch
|> concat(lparen)
|> concat(expr)
|> concat(rparen)
|> concat(lbrace)
|> concat(switchpronglist)
|> concat(rbrace)
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
])
suffixexpr =
choice([
keyword_async |> concat(primarytypeexpr) |> repeat(suffixop) |> concat(fncallarguments),
primarytypeexpr |> repeat(choice([suffixop, fncallarguments]))
])
errorunionexpr = suffixexpr |> optional(exclamationmark |> concat(typeexpr))
typeexpr = repeat(prefixtypeop) |> concat(errorunionexpr)
# *** Top level ***
testdecl =
optional(doc_comment)
|> concat(keyword_test)
|> concat(optional(stringliteralsingle))
|> concat(block)
toplevelcomptime = optional(doc_comment) |> concat(keyword_comptime) |> concat(block)
containerdeclarations =
choice([
testdecl |> concat(containerdeclarations),
toplevelcomptime |> concat(containerdeclarations),
optional(doc_comment)
|> optional(keyword_pub)
|> concat(topleveldecl)
|> concat(containerdeclarations)
])
containerfield =
optional(doc_comment)
|> optional(keyword_comptime)
|> concat(identifier)
|> optional(colon |> concat(typeexpr) |> optional(bytealign))
|> optional(equal |> concat(expr))
containermembers =
containerdeclarations
|> repeat(containerfield |> concat(comma))
|> choice([containerfield, containerdeclarations])
vardecl =
choice([keyword_const, keyword_var])
|> concat(identifier)
|> optional(colon |> concat(typeexpr))
|> optional(bytealign)
|> optional(linksection)
|> optional(equal |> concat(expr))
|> concat(semicolon)
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 ***
blockexpr = optional(blocklabel) |> concat(block)
blockexprstatement = choice([blockexpr, assignexpr |> concat(semicolon)])
ifstatement =
choice([
ifprefix
|> concat(blockexpr)
|> optional(keyword_else |> optional(payload) |> concat(statement)),
ifprefix
|> concat(assignexpr)
|> choice([semicolon, keyword_else |> optional(payload) |> concat(statement)])
])
forstatement =
choice([
forprefix |> concat(blockexpr) |> optional(keyword_else |> concat(statement)),
forprefix |> concat(assignexpr) |> choice([semicolon, keyword_else |> concat(statement)])
])
whilestatement =
choice([
whileprefix
|> concat(blockexpr)
|> optional(keyword_else |> optional(payload) |> concat(statement)),
whileprefix
|> concat(assignexpr)
|> choice([semicolon, keyword_else |> optional(payload) |> concat(statement)])
])
loopstatement = optional(keyword_inline) |> choice([forstatement, whilestatement])
labeledstatement = optional(blocklabel) |> choice([block, loopstatement])
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)
])
root = skip |> optional(container_doc_comment) |> concat(containermembers) |> concat(eof)
defcombinatorp(:expr_parsec, expr, export_metadata: true)
defcombinatorp(:typeexpr_parsec, typeexpr, export_metadata: true)
defcombinatorp(:assignexpr_parsec, assignexpr, export_metadata: true)
defcombinatorp(:stringlist_parsec, stringlist, export_metadata: true)
defcombinatorp(:asminputlist_parsec, asminputlist, export_metadata: true)
defcombinatorp(:asmoutputlist_parsec, asmoutputlist, export_metadata: true)
defcombinatorp(:ifexpr_parsec, ifexpr, export_metadata: true)
defcombinatorp(:ptrpayload_parsec, ptrpayload, export_metadata: true)
defcombinatorp(:slicetypestart_parsec, slicetypestart, export_metadata: true)
defcombinatorp(:bytealign_parsec, bytealign, export_metadata: true)
defcombinatorp(:ptrtypestart_parsec, ptrtypestart, export_metadata: true)
defcombinatorp(:arraytypestart_parsec, arraytypestart, export_metadata: true)
defcombinatorp(:exprlist_parsec, exprlist, export_metadata: true)
defcombinatorp(:containermembers_parsec, containermembers, export_metadata: true)
defcombinatorp(:loopexpr_parsec, loopexpr, export_metadata: true)
defcombinatorp(:block_parsec, block, export_metadata: true)
defcombinatorp(:statement_parsec, statement, export_metadata: true)
defcombinatorp(:containerdeclarations_parsec, containerdeclarations, export_metadata: true)
defcombinatorp(:topleveldecl_parsec, topleveldecl, export_metadata: true)
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