diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index fca150c..9c8c0e1 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -47,11 +47,10 @@ jobs: - uses: actions/cache@v3 id: zig-cache with: - path: test/_support/zig-0.14.0 - key: ${{ runner.os }}-zig-${{ steps.zig-version.outputs.stdout }} + path: test/_support/zig-0.15.1 + key: ${{ runner.os }}-zig-0.15.1 - name: Run Tests env: - RUNNING_CI: "TRUE" - ZIGLER_TEST_BLAS: "TRUE" - run: mix test --exclude no_ci + RUNNING_CI: "true" + run: mix test diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 761365d..6fb5de6 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -35,6 +35,4 @@ jobs: run: mix compile - name: Run Tests - env: - RUNNING_CI: "TRUE" run: mix test \ No newline at end of file diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..43e9701 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +elixir 1.18.3-otp-27 +erlang 27.3.4 diff --git a/lib/grammar/grammar.0.14.y b/lib/grammar/grammar.0.14.y new file mode 100644 index 0000000..a4027bb --- /dev/null +++ b/lib/grammar/grammar.0.14.y @@ -0,0 +1,581 @@ +Root <- skip container_doc_comment? ContainerMembers eof + +# *** Top level *** +ContainerMembers <- ContainerDeclaration* (ContainerField COMMA)* (ContainerField / ContainerDeclaration*) + +ContainerDeclaration <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl + +TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block + +ComptimeDecl <- KEYWORD_comptime Block + +Decl + <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block) + / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? GlobalVarDecl + / KEYWORD_usingnamespace Expr SEMICOLON + +FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr + +VarDeclProto <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? + +GlobalVarDecl <- VarDeclProto (EQUAL Expr)? SEMICOLON + +ContainerField <- doc_comment? KEYWORD_comptime? !KEYWORD_fn (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)? + +# *** Block Level *** +Statement + <- KEYWORD_comptime ComptimeStatement + / KEYWORD_nosuspend BlockExprStatement + / KEYWORD_suspend BlockExprStatement + / KEYWORD_defer BlockExprStatement + / KEYWORD_errdefer Payload? BlockExprStatement + / IfStatement + / LabeledStatement + / BlockLabel? SwitchExpr + / VarDeclExprStatement + +ComptimeStatement + <- BlockExpr + / VarDeclExprStatement + +IfStatement + <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )? + / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) + +LabeledStatement <- BlockLabel? (Block / LoopStatement) + +LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) + +ForStatement + <- ForPrefix BlockExpr ( KEYWORD_else Statement )? + / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement ) + +WhileStatement + <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? + / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) + +BlockExprStatement + <- BlockExpr + / AssignExpr SEMICOLON + +BlockExpr <- BlockLabel? Block + +# An expression, assignment, or any destructure, as a statement. +VarDeclExprStatement + <- VarDeclProto (COMMA (VarDeclProto / Expr))* EQUAL Expr SEMICOLON + / Expr (AssignOp Expr / (COMMA (VarDeclProto / Expr))+ EQUAL Expr)? SEMICOLON + +# *** Expression Level *** + +# An assignment or a destructure whose LHS are all lvalue expressions. +AssignExpr <- Expr (AssignOp Expr / (COMMA Expr)+ EQUAL Expr)? + +SingleAssignExpr <- Expr (AssignOp Expr)? + +Expr <- BoolOrExpr + +BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* + +BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)* + +CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? + +BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* + +BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* + +AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* + +MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* + +PrefixExpr <- PrefixOp* PrimaryExpr + +PrimaryExpr + <- AsmExpr + / IfExpr + / KEYWORD_break BreakLabel? Expr? + / KEYWORD_comptime Expr + / KEYWORD_nosuspend Expr + / KEYWORD_continue BreakLabel? Expr? + / KEYWORD_resume Expr + / KEYWORD_return Expr? + / BlockLabel? LoopExpr + / BlockLabel SwitchExpr + / Block + / CurlySuffixExpr + +IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)? + +Block <- LBRACE Statement* RBRACE + +LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr) + +ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? + +WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? + +CurlySuffixExpr <- TypeExpr InitList? + +InitList + <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE + / LBRACE Expr (COMMA Expr)* COMMA? RBRACE + / LBRACE RBRACE + +TypeExpr <- PrefixTypeOp* ErrorUnionExpr + +ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)? + +SuffixExpr + <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments + / PrimaryTypeExpr (SuffixOp / FnCallArguments)* + +PrimaryTypeExpr + <- BUILTINIDENTIFIER FnCallArguments + / CHAR_LITERAL + / ContainerDecl + / DOT IDENTIFIER + / DOT InitList + / ErrorSetDecl + / FLOAT + / FnProto + / GroupedExpr + / LabeledTypeExpr + / IDENTIFIER + / IfTypeExpr + / INTEGER + / KEYWORD_comptime TypeExpr + / KEYWORD_error DOT IDENTIFIER + / KEYWORD_anyframe + / KEYWORD_unreachable + / STRINGLITERAL + / SwitchExpr + +ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto + +ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE + +GroupedExpr <- LPAREN Expr RPAREN + +IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? + +LabeledTypeExpr + <- BlockLabel Block + / BlockLabel? LoopTypeExpr + +LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr) + +ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? + +WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? + +SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE + +# *** Assembly *** +AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN + +AsmOutput <- COLON AsmOutputList AsmInput? + +AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN + +AsmInput <- COLON AsmInputList AsmClobbers? + +AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN + +AsmClobbers <- COLON StringList + +# *** Helper grammar *** +BreakLabel <- COLON IDENTIFIER + +BlockLabel <- IDENTIFIER COLON + +FieldInit <- DOT IDENTIFIER EQUAL Expr + +WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN + +LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN + +AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN + +# Fn specific +CallConv <- KEYWORD_callconv LPAREN Expr RPAREN + +ParamDecl + <- doc_comment? (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType + / DOT3 + +ParamType + <- KEYWORD_anytype + / TypeExpr + +# Control flow prefixes +IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? + +WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? + +ForPrefix <- KEYWORD_for LPAREN ForArgumentsList RPAREN PtrListPayload + +# Payloads +Payload <- PIPE IDENTIFIER PIPE + +PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE + +PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE + +PtrListPayload <- PIPE ASTERISK? IDENTIFIER (COMMA ASTERISK? IDENTIFIER)* COMMA? PIPE + +# Switch specific +SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? SingleAssignExpr + +SwitchCase + <- SwitchItem (COMMA SwitchItem)* COMMA? + / KEYWORD_else + +SwitchItem <- Expr (DOT3 Expr)? + +# For specific +ForArgumentsList <- ForItem (COMMA ForItem)* COMMA? + +ForItem <- Expr (DOT2 Expr?)? + +# Operators +AssignOp + <- ASTERISKEQUAL + / ASTERISKPIPEEQUAL + / SLASHEQUAL + / PERCENTEQUAL + / PLUSEQUAL + / PLUSPIPEEQUAL + / MINUSEQUAL + / MINUSPIPEEQUAL + / LARROW2EQUAL + / LARROW2PIPEEQUAL + / RARROW2EQUAL + / AMPERSANDEQUAL + / CARETEQUAL + / PIPEEQUAL + / ASTERISKPERCENTEQUAL + / PLUSPERCENTEQUAL + / MINUSPERCENTEQUAL + / EQUAL + +CompareOp + <- EQUALEQUAL + / EXCLAMATIONMARKEQUAL + / LARROW + / RARROW + / LARROWEQUAL + / RARROWEQUAL + +BitwiseOp + <- AMPERSAND + / CARET + / PIPE + / KEYWORD_orelse + / KEYWORD_catch Payload? + +BitShiftOp + <- LARROW2 + / RARROW2 + / LARROW2PIPE + +AdditionOp + <- PLUS + / MINUS + / PLUS2 + / PLUSPERCENT + / MINUSPERCENT + / PLUSPIPE + / MINUSPIPE + +MultiplyOp + <- PIPE2 + / ASTERISK + / SLASH + / PERCENT + / ASTERISK2 + / ASTERISKPERCENT + / ASTERISKPIPE + +PrefixOp + <- EXCLAMATIONMARK + / MINUS + / TILDE + / MINUSPERCENT + / AMPERSAND + / KEYWORD_try + / KEYWORD_await + +PrefixTypeOp + <- QUESTIONMARK + / KEYWORD_anyframe MINUSRARROW + / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* + / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* + / ArrayTypeStart + +SuffixOp + <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET + / DOT IDENTIFIER + / DOTASTERISK + / DOTQUESTIONMARK + +FnCallArguments <- LPAREN ExprList RPAREN + +# Ptr specific +SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET + +PtrTypeStart + <- ASTERISK + / ASTERISK2 + / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET + +ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET + +# ContainerDecl specific +ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE + +ContainerDeclType + <- KEYWORD_struct (LPAREN Expr RPAREN)? + / KEYWORD_opaque + / KEYWORD_enum (LPAREN Expr RPAREN)? + / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? + +# Alignment +ByteAlign <- KEYWORD_align LPAREN Expr RPAREN + +# Lists +IdentifierList <- (doc_comment? IDENTIFIER COMMA)* (doc_comment? IDENTIFIER)? + +SwitchProngList <- (SwitchProng COMMA)* SwitchProng? + +AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem? + +AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? + +StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? + +ParamDeclList <- (ParamDecl COMMA)* ParamDecl? + +ExprList <- (Expr COMMA)* Expr? + +# *** Tokens *** +eof <- !. +bin <- [01] +bin_ <- '_'? bin +oct <- [0-7] +oct_ <- '_'? oct +hex <- [0-9a-fA-F] +hex_ <- '_'? hex +dec <- [0-9] +dec_ <- '_'? dec + +bin_int <- bin bin_* +oct_int <- oct oct_* +dec_int <- dec dec_* +hex_int <- hex hex_* + +ox80_oxBF <- [\200-\277] +oxF4 <- '\364' +ox80_ox8F <- [\200-\217] +oxF1_oxF3 <- [\361-\363] +oxF0 <- '\360' +ox90_0xBF <- [\220-\277] +oxEE_oxEF <- [\356-\357] +oxED <- '\355' +ox80_ox9F <- [\200-\237] +oxE1_oxEC <- [\341-\354] +oxE0 <- '\340' +oxA0_oxBF <- [\240-\277] +oxC2_oxDF <- [\302-\337] + +# From https://lemire.me/blog/2018/05/09/how-quickly-can-you-check-that-a-string-is-valid-unicode-utf-8/ +# First Byte Second Byte Third Byte Fourth Byte +# [0x00,0x7F] +# [0xC2,0xDF] [0x80,0xBF] +# 0xE0 [0xA0,0xBF] [0x80,0xBF] +# [0xE1,0xEC] [0x80,0xBF] [0x80,0xBF] +# 0xED [0x80,0x9F] [0x80,0xBF] +# [0xEE,0xEF] [0x80,0xBF] [0x80,0xBF] +# 0xF0 [0x90,0xBF] [0x80,0xBF] [0x80,0xBF] +# [0xF1,0xF3] [0x80,0xBF] [0x80,0xBF] [0x80,0xBF] +# 0xF4 [0x80,0x8F] [0x80,0xBF] [0x80,0xBF] + +mb_utf8_literal <- + oxF4 ox80_ox8F ox80_oxBF ox80_oxBF + / oxF1_oxF3 ox80_oxBF ox80_oxBF ox80_oxBF + / oxF0 ox90_0xBF ox80_oxBF ox80_oxBF + / oxEE_oxEF ox80_oxBF ox80_oxBF + / oxED ox80_ox9F ox80_oxBF + / oxE1_oxEC ox80_oxBF ox80_oxBF + / oxE0 oxA0_oxBF ox80_oxBF + / oxC2_oxDF ox80_oxBF + +ascii_char_not_nl_slash_squote <- [\000-\011\013-\046\050-\133\135-\177] + +char_escape + <- "\\x" hex hex + / "\\u{" hex+ "}" + / "\\" [nr\\t'"] +char_char + <- mb_utf8_literal + / char_escape + / ascii_char_not_nl_slash_squote + +string_char + <- char_escape + / [^\\"\n] + +container_doc_comment <- ('//!' [^\n]* [ \n]* skip)+ +doc_comment <- ('///' [^\n]* [ \n]* skip)+ +line_comment <- '//' ![!/][^\n]* / '////' [^\n]* +line_string <- ("\\\\" [^\n]* [ \n]*)+ +skip <- ([ \n] / line_comment)* + +CHAR_LITERAL <- "'" char_char "'" skip +FLOAT + <- "0x" hex_int "." hex_int ([pP] [-+]? dec_int)? skip + / dec_int "." dec_int ([eE] [-+]? dec_int)? skip + / "0x" hex_int [pP] [-+]? dec_int skip + / dec_int [eE] [-+]? dec_int skip +INTEGER + <- "0b" bin_int skip + / "0o" oct_int skip + / "0x" hex_int skip + / dec_int skip +STRINGLITERALSINGLE <- "\"" string_char* "\"" skip +STRINGLITERAL + <- STRINGLITERALSINGLE + / (line_string skip)+ +IDENTIFIER + <- !keyword [A-Za-z_] [A-Za-z0-9_]* skip + / "@" STRINGLITERALSINGLE +BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip + + +AMPERSAND <- '&' ![=] skip +AMPERSANDEQUAL <- '&=' skip +ASTERISK <- '*' ![*%=|] skip +ASTERISK2 <- '**' skip +ASTERISKEQUAL <- '*=' skip +ASTERISKPERCENT <- '*%' ![=] skip +ASTERISKPERCENTEQUAL <- '*%=' skip +ASTERISKPIPE <- '*|' ![=] skip +ASTERISKPIPEEQUAL <- '*|=' skip +CARET <- '^' ![=] skip +CARETEQUAL <- '^=' skip +COLON <- ':' skip +COMMA <- ',' skip +DOT <- '.' ![*.?] skip +DOT2 <- '..' ![.] skip +DOT3 <- '...' skip +DOTASTERISK <- '.*' skip +DOTQUESTIONMARK <- '.?' skip +EQUAL <- '=' ![>=] skip +EQUALEQUAL <- '==' skip +EQUALRARROW <- '=>' skip +EXCLAMATIONMARK <- '!' ![=] skip +EXCLAMATIONMARKEQUAL <- '!=' skip +LARROW <- '<' ![<=] skip +LARROW2 <- '<<' ![=|] skip +LARROW2EQUAL <- '<<=' skip +LARROW2PIPE <- '<<|' ![=] skip +LARROW2PIPEEQUAL <- '<<|=' skip +LARROWEQUAL <- '<=' skip +LBRACE <- '{' skip +LBRACKET <- '[' skip +LPAREN <- '(' skip +MINUS <- '-' ![%=>|] skip +MINUSEQUAL <- '-=' skip +MINUSPERCENT <- '-%' ![=] skip +MINUSPERCENTEQUAL <- '-%=' skip +MINUSPIPE <- '-|' ![=] skip +MINUSPIPEEQUAL <- '-|=' skip +MINUSRARROW <- '->' skip +PERCENT <- '%' ![=] skip +PERCENTEQUAL <- '%=' skip +PIPE <- '|' ![|=] skip +PIPE2 <- '||' skip +PIPEEQUAL <- '|=' skip +PLUS <- '+' ![%+=|] skip +PLUS2 <- '++' skip +PLUSEQUAL <- '+=' skip +PLUSPERCENT <- '+%' ![=] skip +PLUSPERCENTEQUAL <- '+%=' skip +PLUSPIPE <- '+|' ![=] skip +PLUSPIPEEQUAL <- '+|=' skip +LETTERC <- 'c' skip +QUESTIONMARK <- '?' skip +RARROW <- '>' ![>=] skip +RARROW2 <- '>>' ![=] skip +RARROW2EQUAL <- '>>=' skip +RARROWEQUAL <- '>=' skip +RBRACE <- '}' skip +RBRACKET <- ']' skip +RPAREN <- ')' skip +SEMICOLON <- ';' skip +SLASH <- '/' ![=] skip +SLASHEQUAL <- '/=' skip +TILDE <- '~' skip + +end_of_word <- ![a-zA-Z0-9_] skip +KEYWORD_addrspace <- 'addrspace' end_of_word +KEYWORD_align <- 'align' end_of_word +KEYWORD_allowzero <- 'allowzero' end_of_word +KEYWORD_and <- 'and' end_of_word +KEYWORD_anyframe <- 'anyframe' end_of_word +KEYWORD_anytype <- 'anytype' end_of_word +KEYWORD_asm <- 'asm' end_of_word +KEYWORD_async <- 'async' end_of_word +KEYWORD_await <- 'await' end_of_word +KEYWORD_break <- 'break' end_of_word +KEYWORD_callconv <- 'callconv' end_of_word +KEYWORD_catch <- 'catch' end_of_word +KEYWORD_comptime <- 'comptime' end_of_word +KEYWORD_const <- 'const' end_of_word +KEYWORD_continue <- 'continue' end_of_word +KEYWORD_defer <- 'defer' end_of_word +KEYWORD_else <- 'else' end_of_word +KEYWORD_enum <- 'enum' end_of_word +KEYWORD_errdefer <- 'errdefer' end_of_word +KEYWORD_error <- 'error' end_of_word +KEYWORD_export <- 'export' end_of_word +KEYWORD_extern <- 'extern' end_of_word +KEYWORD_fn <- 'fn' end_of_word +KEYWORD_for <- 'for' end_of_word +KEYWORD_if <- 'if' end_of_word +KEYWORD_inline <- 'inline' end_of_word +KEYWORD_noalias <- 'noalias' end_of_word +KEYWORD_nosuspend <- 'nosuspend' end_of_word +KEYWORD_noinline <- 'noinline' end_of_word +KEYWORD_opaque <- 'opaque' end_of_word +KEYWORD_or <- 'or' end_of_word +KEYWORD_orelse <- 'orelse' end_of_word +KEYWORD_packed <- 'packed' end_of_word +KEYWORD_pub <- 'pub' end_of_word +KEYWORD_resume <- 'resume' end_of_word +KEYWORD_return <- 'return' end_of_word +KEYWORD_linksection <- 'linksection' end_of_word +KEYWORD_struct <- 'struct' end_of_word +KEYWORD_suspend <- 'suspend' end_of_word +KEYWORD_switch <- 'switch' end_of_word +KEYWORD_test <- 'test' end_of_word +KEYWORD_threadlocal <- 'threadlocal' end_of_word +KEYWORD_try <- 'try' end_of_word +KEYWORD_union <- 'union' end_of_word +KEYWORD_unreachable <- 'unreachable' end_of_word +KEYWORD_usingnamespace <- 'usingnamespace' end_of_word +KEYWORD_var <- 'var' end_of_word +KEYWORD_volatile <- 'volatile' end_of_word +KEYWORD_while <- 'while' end_of_word + +keyword <- KEYWORD_addrspace / 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 \ No newline at end of file diff --git a/lib/grammar/grammar.y b/lib/grammar/grammar.y index a4027bb..1748933 100644 --- a/lib/grammar/grammar.y +++ b/lib/grammar/grammar.y @@ -12,7 +12,6 @@ ComptimeDecl <- KEYWORD_comptime Block Decl <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block) / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? GlobalVarDecl - / KEYWORD_usingnamespace Expr SEMICOLON FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr @@ -126,8 +125,7 @@ TypeExpr <- PrefixTypeOp* ErrorUnionExpr ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)? SuffixExpr - <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments - / PrimaryTypeExpr (SuffixOp / FnCallArguments)* + <- PrimaryTypeExpr (SuffixOp / FnCallArguments)* PrimaryTypeExpr <- BUILTINIDENTIFIER FnCallArguments @@ -181,7 +179,7 @@ AsmInput <- COLON AsmInputList AsmClobbers? AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN -AsmClobbers <- COLON StringList +AsmClobbers <- COLON PrimaryTypeExpr # *** Helper grammar *** BreakLabel <- COLON IDENTIFIER @@ -303,7 +301,6 @@ PrefixOp / MINUSPERCENT / AMPERSAND / KEYWORD_try - / KEYWORD_await PrefixTypeOp <- QUESTIONMARK @@ -351,8 +348,6 @@ AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem? AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? -StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? - ParamDeclList <- (ParamDecl COMMA)* ParamDecl? ExprList <- (Expr COMMA)* Expr? @@ -524,8 +519,6 @@ KEYWORD_and <- 'and' end_of_word KEYWORD_anyframe <- 'anyframe' end_of_word KEYWORD_anytype <- 'anytype' end_of_word KEYWORD_asm <- 'asm' end_of_word -KEYWORD_async <- 'async' end_of_word -KEYWORD_await <- 'await' end_of_word KEYWORD_break <- 'break' end_of_word KEYWORD_callconv <- 'callconv' end_of_word KEYWORD_catch <- 'catch' end_of_word @@ -562,14 +555,13 @@ KEYWORD_threadlocal <- 'threadlocal' end_of_word KEYWORD_try <- 'try' end_of_word KEYWORD_union <- 'union' end_of_word KEYWORD_unreachable <- 'unreachable' end_of_word -KEYWORD_usingnamespace <- 'usingnamespace' end_of_word KEYWORD_var <- 'var' end_of_word KEYWORD_volatile <- 'volatile' end_of_word KEYWORD_while <- 'while' end_of_word keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and - / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async - / KEYWORD_await / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch + / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm + / 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 @@ -578,4 +570,4 @@ keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and / 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 \ No newline at end of file + / KEYWORD_var / KEYWORD_volatile / KEYWORD_while \ No newline at end of file diff --git a/lib/zig.parser.ex b/lib/zig.parser.ex index cd8c8b1..791d645 100644 --- a/lib/zig.parser.ex +++ b/lib/zig.parser.ex @@ -31,7 +31,7 @@ defmodule Zig.Parser do alias Zig.Parser.VarDeclExprStatement alias Zig.Parser.While - @keywords ~w[addrspace align allowzero and anyframe anytype asm async await break callconv catch comptime const continue defer else enum errdefer error export extern fn for if inline noalias nosuspend noinline opaque or orelse packed pub resume return linksection struct suspend switch test threadlocal try union unreachable usingnamespace var volatile while]a + @keywords ~w[addrspace align allowzero and anyframe anytype asm break callconv catch comptime const continue defer else enum errdefer error export extern fn for if inline noalias nosuspend noinline opaque or orelse packed pub resume return linksection struct suspend switch test threadlocal try union unreachable var volatile while]a @keyword_mapping Enum.map(@keywords, &{:"KEYWORD_#{&1}", [token: &1]}) @sub_operators %{ diff --git a/lib/zig.parser/asm.ex b/lib/zig.parser/asm.ex index 7a443d9..5716c54 100644 --- a/lib/zig.parser/asm.ex +++ b/lib/zig.parser/asm.ex @@ -54,8 +54,8 @@ defmodule Zig.Parser.Asm do end end - defp parse_rest([{:StringList, clobbers}, :RPAREN], asm) do - %{asm | clobbers: parse_clobbers(clobbers, [])} + defp parse_rest([clobbers, :RPAREN], asm) do + %{asm | clobbers: clobbers} end defp parse_io( @@ -86,12 +86,4 @@ defmodule Zig.Parser.Asm do end defp parse_io([], so_far), do: Enum.reverse(so_far) - - defp parse_clobbers([], []), do: [] - - defp parse_clobbers([{:string, string}], so_far), do: Enum.reverse([string | so_far]) - - defp parse_clobbers([{:string, string}, :COMMA | rest], so_far) do - parse_clobbers(rest, [string | so_far]) - end end diff --git a/lib/zig.parser/container_declaration.ex b/lib/zig.parser/container_declaration.ex index 49ab6b0..092634c 100644 --- a/lib/zig.parser/container_declaration.ex +++ b/lib/zig.parser/container_declaration.ex @@ -39,14 +39,6 @@ defmodule Zig.Parser.ContainerDeclaration do parse(rest, new_attrs, so_far) end - defp parse([{:usingnamespace, namespace} | rest], attrs, so_far) do - if attrs do - parse(rest, nil, [{:usingnamespace, Keyword.keys(attrs), namespace} | so_far]) - else - parse(rest, nil, [{:usingnamespace, namespace} | so_far]) - end - end - defp parse([term | rest], nil, so_far) do parse(rest, nil, [term | so_far]) end diff --git a/lib/zig.parser/decl.ex b/lib/zig.parser/decl.ex index fdfc374..ea2ac0a 100644 --- a/lib/zig.parser/decl.ex +++ b/lib/zig.parser/decl.ex @@ -28,8 +28,6 @@ defmodule Zig.Parser.Decl do defp parse([:threadlocal | rest]), do: %{parse(rest) | threadlocal: true} - defp parse([:usingnamespace, payload, :SEMICOLON]), do: {:usingnamespace, payload} - defp parse([%Function{} = function, :SEMICOLON]), do: function defp parse([%Function{} = function, %Block{} = block]), do: %{function | block: block} diff --git a/lib/zig.parser/error_union_expr.ex b/lib/zig.parser/error_union_expr.ex index 5f43cbb..56e9602 100644 --- a/lib/zig.parser/error_union_expr.ex +++ b/lib/zig.parser/error_union_expr.ex @@ -3,8 +3,6 @@ defmodule Zig.Parser.ErrorUnionExpr do {rest, [parse(args) | rest_args], context} end - defp parse([:async | rest]), do: {:async, parse(rest)} - defp parse([identifier]), do: identifier defp parse([_ | _] = args) do diff --git a/lib/zig.parser/expr.ex b/lib/zig.parser/expr.ex index b2c6c72..1a591c6 100644 --- a/lib/zig.parser/expr.ex +++ b/lib/zig.parser/expr.ex @@ -6,12 +6,12 @@ defmodule Zig.Parser.Expr do # implements the shunting yard algorithm to get correct pairing of operators. - @prefix_operators ~w[! - ~ -% & try await]a + @prefix_operators ~w[! - ~ -% & try]a @infix_operators ~w[ * / % ** *% *| || - + - ++ +% -% +| -| - << >> <<| + + - ++ +% -% +| -| + << >> <<| & ^ | orelse catch == != < > <= >= and or]a diff --git a/lib/zig.parser/usingnamespace.ex b/lib/zig.parser/usingnamespace.ex deleted file mode 100644 index fe1408d..0000000 --- a/lib/zig.parser/usingnamespace.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule Zig.Parser.Usingnamespace do - defstruct [:namespace] -end diff --git a/mix.exs b/mix.exs index de30534..d27d477 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ZigParser.MixProject do def project do [ app: :zig_parser, - version: "0.5.1", + version: "0.6.0", elixir: "~> 1.13", start_permanent: Mix.env() == :prod, description: "a zig parser in elixir", diff --git a/test/everything_test.exs b/test/everything_test.exs index cae339e..b7baefd 100644 --- a/test/everything_test.exs +++ b/test/everything_test.exs @@ -1,12 +1,12 @@ -if match?({:unix, _}, :os.type()) do +if match?({:unix, _}, :os.type()) and System.get_env("RUNNING_CI", "false") != "true" do defmodule ZigParserTest.EverythingHelper do @rejected MapSet.new(~w[ # PARSE TOO SLOW: - test/_support/zig-0.14.0/src/arch/x86_64/CodeGen.zig - test/_support/zig-0.14.0/lib/compiler_rt/udivmodti4_test.zig + test/_support/zig-0.15.1/src/arch/x86_64/CodeGen.zig + test/_support/zig-0.15.1/lib/compiler_rt/udivmodti4_test.zig ]) - def dir_walk("test/_support/zig-0.14.0/test/cases/compile_errors" <> _), do: [] + def dir_walk("test/_support/zig-0.15.1/test/cases/compile_errors" <> _), do: [] def dir_walk(dir) do {dirs, files} = @@ -26,7 +26,7 @@ if match?({:unix, _}, :os.type()) do alias ZigParserTest.EverythingHelper - parent_dir = "test/_support/zig-0.14.0" + parent_dir = "test/_support/zig-0.15.1" subdirs = ~W[lib src test] subdirs diff --git a/test/parser/asm_test.exs b/test/parser/asm_test.exs index 1698439..9ec52b6 100644 --- a/test/parser/asm_test.exs +++ b/test/parser/asm_test.exs @@ -12,18 +12,18 @@ defmodule Zig.Parser.AsmTest do # AsmInput <- COLON AsmInputList AsmClobbers? # AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? # AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN - # AsmClobbers <- COLON StringList + # AsmClobbers <- COLON PrimaryTypeExpression test "basic asm expression" do assert [%{value: %Asm{code: {:string, "syscall"}}}] = - Parser.parse(~S|const foo = asm("syscall" : : : );|).code + Parser.parse(~S|const foo = asm("syscall" : : : .{});|).code end test "asm expression location" do assert [_, %{value: %Asm{location: location}}] = Parser.parse(~S""" const bar = 1; - const foo = asm("syscall" : : : ); + const foo = asm("syscall" : : : .{}); """).code assert {2, 13} == location @@ -31,17 +31,17 @@ defmodule Zig.Parser.AsmTest do test "asm with volatile" do assert [%{value: %Asm{volatile: true}}] = - Parser.parse(~S|const foo = asm volatile("syscall" : : : );|).code + Parser.parse(~S|const foo = asm volatile("syscall" : : : .{});|).code end test "one output expression" do assert [%{value: %Asm{outputs: [{:ret, "={rax}", type: :usize}]}}] = - Parser.parse(~S|const foo = asm("syscall" : [ret] "={rax}" (-> usize) : : );|).code + Parser.parse(~S|const foo = asm("syscall" : [ret] "={rax}" (-> usize) : : .{});|).code end test "one output expression with an identifier" do assert [%{value: %Asm{outputs: [{:ret, "={rax}", var: :identifier}]}}] = - Parser.parse(~S|const foo = asm("syscall" : [ret] "={rax}" (identifier) : : );|).code + Parser.parse(~S|const foo = asm("syscall" : [ret] "={rax}" (identifier) : : .{});|).code end test "two output expressions" do @@ -54,13 +54,13 @@ defmodule Zig.Parser.AsmTest do } ] = Parser.parse( - ~S|const foo = asm("syscall" : [ret] "={rax}" (-> usize), [ret] "={rax}" (-> usize) : : );| + ~S|const foo = asm("syscall" : [ret] "={rax}" (-> usize), [ret] "={rax}" (-> usize) : : .{});| ).code end test "one input expression" do assert [%{value: %Asm{inputs: [{:number, "{rax}", var: :number}]}}] = - Parser.parse(~S|const foo = asm("syscall" : : [number] "{rax}" (number) : );|).code + Parser.parse(~S|const foo = asm("syscall" : : [number] "{rax}" (number) : .{});|).code end test "two input expressions" do @@ -72,18 +72,18 @@ defmodule Zig.Parser.AsmTest do } ] = Parser.parse( - ~S|const foo = asm("syscall" : : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) : );| + ~S|const foo = asm("syscall" : : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) : .{});| ).code end test "one clobber register" do - assert [%{value: %Asm{clobbers: ["rcx"]}}] = - Parser.parse(~S|const foo = asm("syscall" : : : "rcx");|).code + assert [%{value: %Asm{clobbers: %{values: %{rcx: true}}}}] = + Parser.parse(~S|const foo = asm("syscall" : : : .{.rcx = true});|).code end test "two clobber registers" do - assert [%{value: %Asm{clobbers: ["rcx", "r11"]}}] = - Parser.parse(~S|const foo = asm("syscall" : : : "rcx", "r11");|).code + assert [%{value: %Asm{clobbers: %{values: %{rcx: true, r11: true}}}}] = + Parser.parse(~S|const foo = asm("syscall" : : : .{.rcx = true, .r11 = true});|).code end test "with multiline string" do @@ -93,7 +93,7 @@ defmodule Zig.Parser.AsmTest do \\ this is \\ some \\ assembler code - : : : ); + : : : .{}); """).code assert code == " this is\n some\n assembler code\n" diff --git a/test/parser/decl_test.exs b/test/parser/decl_test.exs index ceaf1a8..6ef4d1c 100644 --- a/test/parser/decl_test.exs +++ b/test/parser/decl_test.exs @@ -9,7 +9,7 @@ defmodule Zig.Parser.Test.ContainerDeclTest do # Decl # <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) # / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDeclProto - # / KEYWORD_usingnamespace Expr SEMICOLON + # Expr SEMICOLON describe "FnProto decorator with no block" do test "export works" do @@ -71,22 +71,4 @@ defmodule Zig.Parser.Test.ContainerDeclTest do """).code end end - - describe "usingnamespace works" do - alias Zig.Parser.Struct - - test "with an identifier" do - assert [{:usingnamespace, :std}] = Parser.parse("usingnamespace std;").code - end - - test "with a struct" do - assert [{:usingnamespace, %Struct{}}] = - Parser.parse("usingnamespace struct{};").code - end - - test "with an import" do - assert [{:usingnamespace, {:call, :import, [string: "std"]}}] = - Parser.parse("usingnamespace @import(\"std\");").code - end - end end diff --git a/test/parser/operators_test.exs b/test/parser/operators_test.exs index 3c154ec..245222a 100644 --- a/test/parser/operators_test.exs +++ b/test/parser/operators_test.exs @@ -84,7 +84,7 @@ defmodule Zig.Parser.Test.OperatorsTest do end end - @unary_operators ~w[! - -% ~ & try await]a + @unary_operators ~w[! - -% ~ & try]a describe "unary prefix operators in expressions" do for op <- @unary_operators do diff --git a/test/parser/type_expr_test.exs b/test/parser/type_expr_test.exs index 4817f11..ab02610 100644 --- a/test/parser/type_expr_test.exs +++ b/test/parser/type_expr_test.exs @@ -357,23 +357,6 @@ defmodule Zig.Parser.Test.TypeExprTest do end end - describe "async function call" do - test "works in the simple case" do - assert [%{value: {:async, {:call, :bar, []}}}] = - Parser.parse("const foo = async bar();").code - end - - test "works in the more complex case" do - assert [ - %{ - value: - {:async, {:call, {:ref, [:bar, :baz, {:index, {:integer, 3}}, :quux]}, []}} - } - ] = - Parser.parse("const foo = async bar.baz[3].quux();").code - end - end - describe "as error unions" do test "basic error union" do assert [%{value: {:errorunion, :bar, :baz}}] = Parser.parse("const foo = bar!baz;").code