diff options
| -rw-r--r-- | doc/docgen.zig | 2 | ||||
| -rw-r--r-- | doc/langref.html.in | 444 | ||||
| -rw-r--r-- | src/parser.cpp | 2 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 4 | ||||
| -rw-r--r-- | src/tokenizer.hpp | 2 | ||||
| -rw-r--r-- | std/zig/ast.zig | 12 | ||||
| -rw-r--r-- | std/zig/parse.zig | 37 | ||||
| -rw-r--r-- | std/zig/parser_test.zig | 7 | ||||
| -rw-r--r-- | std/zig/render.zig | 28 | ||||
| -rw-r--r-- | std/zig/tokenizer.zig | 4 | ||||
| -rw-r--r-- | test/compile_errors.zig | 12 |
11 files changed, 314 insertions, 240 deletions
diff --git a/doc/docgen.zig b/doc/docgen.zig index 498719d774..2489e034bc 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -764,7 +764,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok std.zig.Token.Id.Keyword_pub, std.zig.Token.Id.Keyword_resume, std.zig.Token.Id.Keyword_return, - std.zig.Token.Id.Keyword_section, + std.zig.Token.Id.Keyword_linksection, std.zig.Token.Id.Keyword_stdcallcc, std.zig.Token.Id.Keyword_struct, std.zig.Token.Id.Keyword_suspend, diff --git a/doc/langref.html.in b/doc/langref.html.in index c61203dca6..a29b9be4c8 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7713,36 +7713,35 @@ fn readU32Be() u32 {} <p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/ziglang/zig/issues/663">issue #663</a></p> {#header_close#} {#header_open|Grammar#} - <pre><code class="nohighlight"> -Root <- skip ContainerMembers eof + <pre><code>Root <- skip ContainerMembers eof # *** Top level *** ContainerMembers - <- TestDecl ContainerMembers + <- TestDecl ContainerMembers / TopLevelComptime ContainerMembers / KEYWORD_pub? TopLevelDecl ContainerMembers / KEYWORD_pub? ContainerField COMMA ContainerMembers / KEYWORD_pub? ContainerField / -TestDecl <- KEYWORD_test STRINGLITERAL Block +TestDecl <- KEYWORD_test STRINGLITERAL Block -TopLevelComptime <- KEYWORD_comptime BlockExpr +TopLevelComptime <- KEYWORD_comptime BlockExpr TopLevelDecl - <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) + <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl / KEYWORD_use Expr SEMICOLON -FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? Section? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) +FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) -VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? Section? (EQUAL Expr)? SEMICOLON +VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON -ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? +ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? # *** Block Level *** Statement - <- KEYWORD_comptime? VarDecl + <- KEYWORD_comptime? VarDecl / KEYWORD_comptime BlockExprStatement / KEYWORD_suspend (SEMICOLON / BlockExprStatement) / KEYWORD_defer BlockExprStatement @@ -7753,50 +7752,50 @@ Statement / AssignExpr SEMICOLON IfStatement - <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )? + <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )? / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) -LabeledStatement <- BlockLabel? (Block / LoopStatement) +LabeledStatement <- BlockLabel? (Block / LoopStatement) -LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) +LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) ForStatement - <- ForPrefix BlockExpr ( KEYWORD_else Statement )? + <- ForPrefix BlockExpr ( KEYWORD_else Statement )? / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement ) WhileStatement - <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? + <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) BlockExprStatement - <- BlockExpr + <- BlockExpr / AssignExpr SEMICOLON -BlockExpr <- BlockLabel? Block +BlockExpr <- BlockLabel? Block # *** Expression Level *** -AssignExpr <- Expr (AssignOp Expr)? +AssignExpr <- Expr (AssignOp Expr)? -Expr <- KEYWORD_try* BoolOrExpr +Expr <- KEYWORD_try* BoolOrExpr -BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* +BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* -BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)* +BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)* -CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? +CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? -BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* +BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* -BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* +BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* -AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* +AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* -MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* +MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* -PrefixExpr <- PrefixOp* PrimaryExpr +PrefixExpr <- PrefixOp* PrimaryExpr PrimaryExpr - <- AsmExpr + <- AsmExpr / IfExpr / KEYWORD_break BreakLabel? Expr? / KEYWORD_cancel Expr @@ -7807,35 +7806,35 @@ PrimaryExpr / LabeledExpr / CurlySuffixExpr -IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)? +IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)? -LabeledExpr <- BlockLabel? (Block / LoopExpr) +LabeledExpr <- BlockLabel? (Block / LoopExpr) -Block <- LBRACE Statement* RBRACE +Block <- LBRACE Statement* RBRACE -LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr) +LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr) -ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? +ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? -WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? +WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? -CurlySuffixExpr <- TypeExpr InitList? +CurlySuffixExpr <- TypeExpr InitList? InitList - <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE + <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE / LBRACE Expr (COMMA Expr)* COMMA? RBRACE / LBRACE RBRACE -TypeExpr <- PrefixTypeOp* ErrorUnionExpr +TypeExpr <- PrefixTypeOp* ErrorUnionExpr -ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)? +ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)? SuffixExpr - <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets + <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)* PrimaryTypeExpr - <- BUILTININDENTIFIER FnCallArgumnets + <- BUILTININDENTIFIER FnCallArgumnets / CHAR_LITERAL / ContainerDecl / ErrorSetDecl @@ -7858,91 +7857,91 @@ PrimaryTypeExpr / STRINGLITERAL / SwitchExpr -ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto +ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto -ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE +ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE -GroupedExpr <- LPAREN Expr RPAREN +GroupedExpr <- LPAREN Expr RPAREN -IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? +IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? LabeledTypeExpr - <- BlockLabel Block + <- BlockLabel Block / BlockLabel? LoopTypeExpr -LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr) +LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr) -ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? +ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? -WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? +WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? -SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE +SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE # *** Assembly *** -AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN +AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN -AsmOutput <- COLON AsmOutputList AsmInput? +AsmOutput <- COLON AsmOutputList AsmInput? -AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN +AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN -AsmInput <- COLON AsmInputList AsmCloppers? +AsmInput <- COLON AsmInputList AsmCloppers? -AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN +AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN -AsmCloppers <- COLON StringList +AsmCloppers <- COLON StringList # *** Helper grammar *** -BreakLabel <- COLON IDENTIFIER +BreakLabel <- COLON IDENTIFIER -BlockLabel <- IDENTIFIER COLON +BlockLabel <- IDENTIFIER COLON -FieldInit <- DOT IDENTIFIER EQUAL Expr +FieldInit <- DOT IDENTIFIER EQUAL Expr -WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN +WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN -Section <- KEYWORD_section LPAREN Expr RPAREN +LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN # Fn specific FnCC - <- KEYWORD_nakedcc + <- KEYWORD_nakedcc / KEYWORD_stdcallcc / KEYWORD_extern / KEYWORD_async (LARROW TypeExpr RARROW)? -ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType +ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType ParamType - <- KEYWORD_var + <- KEYWORD_var / DOT3 / TypeExpr # Control flow prefixes -IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? +IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? -WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? +WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? -ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload +ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload # Payloads -Payload <- PIPE IDENTIFIER PIPE +Payload <- PIPE IDENTIFIER PIPE -PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE +PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE -PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE +PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE # Switch specific -SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr +SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr SwitchCase - <- SwitchItem (COMMA SwitchItem)* COMMA? + <- SwitchItem (COMMA SwitchItem)* COMMA? / KEYWORD_else -SwitchItem <- Expr (DOT3 Expr)? +SwitchItem <- Expr (DOT3 Expr)? # Operators AssignOp - <- ASTERISKEQUAL + <- ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL @@ -7958,7 +7957,7 @@ AssignOp / EQUAL CompareOp - <- EQUALEQUAL + <- EQUALEQUAL / EXCLAMATIONMARKEQUAL / LARROW / RARROW @@ -7966,25 +7965,25 @@ CompareOp / RARROWEQUAL BitwiseOp - <- AMPERSAND + <- AMPERSAND / CARET / PIPE / KEYWORD_orelse / KEYWORD_catch Payload? BitShiftOp - <- LARROW2 + <- LARROW2 / RARROW2 AdditionOp - <- PLUS + <- PLUS / MINUS / PLUS2 / PLUSPERCENT / MINUSPERCENT MultiplyOp - <- PIPE2 + <- PIPE2 / ASTERISK / SLASH / PERCENT @@ -7992,7 +7991,7 @@ MultiplyOp / ASTERISKPERCENT PrefixOp - <- EXCLAMATIONMARK + <- EXCLAMATIONMARK / MINUS / TILDE / MINUSPERCENT @@ -8001,77 +8000,77 @@ PrefixOp / KEYWORD_await PrefixTypeOp - <- QUESTIONMARK + <- QUESTIONMARK / KEYWORD_promise MINUSRARROW / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)* / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)* SuffixOp - <- LBRACKET Expr (DOT2 Expr?)? RBRACKET + <- LBRACKET Expr (DOT2 Expr?)? RBRACKET / DOT IDENTIFIER / DOTASTERISK / DOTQUESTIONMARK -AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)? +AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)? -FnCallArgumnets <- LPAREN ExprList RPAREN +FnCallArgumnets <- LPAREN ExprList RPAREN # Ptr specific -ArrayTypeStart <- LBRACKET Expr? RBRACKET +ArrayTypeStart <- LBRACKET Expr? RBRACKET PtrTypeStart - <- ASTERISK + <- ASTERISK / ASTERISK2 / LBRACKET ASTERISK RBRACKET # ContainerDecl specific -ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE +ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE ContainerDeclType - <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)? + <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)? / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? # Alignment -ByteAlign <- KEYWORD_align LPAREN Expr RPAREN +ByteAlign <- KEYWORD_align LPAREN Expr RPAREN # Lists -IdentifierList <- (IDENTIFIER COMMA)* IDENTIFIER? +IdentifierList <- (IDENTIFIER COMMA)* IDENTIFIER? -SwitchProngList <- (SwitchProng COMMA)* SwitchProng? +SwitchProngList <- (SwitchProng COMMA)* SwitchProng? -AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem? +AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem? -AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? +AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? -StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? +StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? -ParamDeclList <- (ParamDecl COMMA)* ParamDecl? +ParamDeclList <- (ParamDecl COMMA)* ParamDecl? -ExprList <- (Expr COMMA)* Expr? +ExprList <- (Expr COMMA)* Expr? # *** Tokens *** -eof <- !. -hex <- [0-9a-fA-F] +eof <- !. +hex <- [0-9a-fA-F] char_escape - <- "\\x" hex hex + <- "\\x" hex hex / "\\u" hex hex hex hex / "\\U" hex hex hex hex hex hex / "\\" [nr\\t'"] char_char - <- char_escape + <- char_escape / [^\\'\n] string_char - <- char_escape + <- char_escape / [^\\"\n] -line_comment <- '//'[^\n]* -line_string <- ("\\\\" [^\n]* [ \n]*)+ -line_cstring <- ("c\\\\" [^\n]* [ \n]*)+ -skip <- ([ \n] / line_comment)* +line_comment <- '//'[^\n]* +line_string <- ("\\\\" [^\n]* [ \n]*)+ +line_cstring <- ("c\\\\" [^\n]* [ \n]*)+ +skip <- ([ \n] / line_comment)* -CHAR_LITERAL <- "'" char_char "'" skip +CHAR_LITERAL <- "'" char_char "'" skip FLOAT - <- "0b" [01]+ "." [01]+ ([eE] [-+]? [01]+)? skip + <- "0b" [01]+ "." [01]+ ([eE] [-+]? [01]+)? skip / "0o" [0-7]+ "." [0-7]+ ([eE] [-+]? [0-7]+)? skip / "0x" hex+ "." hex+ ([pP] [-+]? hex+)? skip / [0-9]+ "." [0-9]+ ([eE] [-+]? [0-9]+)? skip @@ -8080,128 +8079,128 @@ FLOAT / "0x" hex+ "."? [pP] [-+]? hex+ skip / [0-9]+ "."? [eE] [-+]? [0-9]+ skip INTEGER - <- "0b" [01]+ skip + <- "0b" [01]+ skip / "0o" [0-7]+ skip / "0x" hex+ skip / [0-9]+ skip STRINGLITERAL - <- "c"? "\"" string_char* "\"" skip + <- "c"? "\"" string_char* "\"" skip / line_string skip / line_cstring skip IDENTIFIER - <- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip + <- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip / "@\"" string_char* "\"" skip -BUILTININDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip - - -AMPERSAND <- '&' ![=] skip -AMPERSANDEQUAL <- '&=' skip -ASTERISK <- '*' ![*%=] skip -ASTERISK2 <- '**' skip -ASTERISKEQUAL <- '*=' skip -ASTERISKPERCENT <- '*%' ![=] skip -ASTERISKPERCENTEQUAL <- '*%=' 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 -LARROWEQUAL <- '<=' skip -LBRACE <- '{' skip -LBRACKET <- '[' skip -LPAREN <- '(' skip -MINUS <- '-' ![%=>] skip -MINUSEQUAL <- '-=' skip -MINUSPERCENT <- '-%' ![=] skip -MINUSPERCENTEQUAL <- '-%=' skip -MINUSRARROW <- '->' skip -PERCENT <- '%' ![=] skip -PERCENTEQUAL <- '%=' skip -PIPE <- '|' ![|=] skip -PIPE2 <- '||' skip -PIPEEQUAL <- '|=' skip -PLUS <- '+' ![%+=] skip -PLUS2 <- '++' skip -PLUSEQUAL <- '+=' skip -PLUSPERCENT <- '+%' ![=] skip -PLUSPERCENTEQUAL <- '+%=' 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_align <- 'align' end_of_word -KEYWORD_and <- 'and' end_of_word -KEYWORD_anyerror <- 'anyerror' 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_cancel <- 'cancel' 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_false <- 'false' 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_nakedcc <- 'nakedcc' end_of_word -KEYWORD_noalias <- 'noalias' end_of_word -KEYWORD_null <- 'null' end_of_word -KEYWORD_or <- 'or' end_of_word -KEYWORD_orelse <- 'orelse' end_of_word -KEYWORD_packed <- 'packed' end_of_word -KEYWORD_promise <- 'promise' end_of_word -KEYWORD_pub <- 'pub' end_of_word -KEYWORD_resume <- 'resume' end_of_word -KEYWORD_return <- 'return' end_of_word -KEYWORD_section <- 'section' end_of_word -KEYWORD_stdcallcc <- 'stdcallcc' 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_true <- 'true' end_of_word -KEYWORD_try <- 'try' end_of_word -KEYWORD_undefined <- 'undefined' end_of_word -KEYWORD_union <- 'union' end_of_word -KEYWORD_unreachable <- 'unreachable' end_of_word -KEYWORD_use <- 'use' end_of_word -KEYWORD_var <- 'var' end_of_word -KEYWORD_volatile <- 'volatile' end_of_word -KEYWORD_while <- 'while' end_of_word - -keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm +BUILTININDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip + + +AMPERSAND <- '&' ![=] skip +AMPERSANDEQUAL <- '&=' skip +ASTERISK <- '*' ![*%=] skip +ASTERISK2 <- '**' skip +ASTERISKEQUAL <- '*=' skip +ASTERISKPERCENT <- '*%' ![=] skip +ASTERISKPERCENTEQUAL <- '*%=' 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 +LARROWEQUAL <- '<=' skip +LBRACE <- '{' skip +LBRACKET <- '[' skip +LPAREN <- '(' skip +MINUS <- '-' ![%=>] skip +MINUSEQUAL <- '-=' skip +MINUSPERCENT <- '-%' ![=] skip +MINUSPERCENTEQUAL <- '-%=' skip +MINUSRARROW <- '->' skip +PERCENT <- '%' ![=] skip +PERCENTEQUAL <- '%=' skip +PIPE <- '|' ![|=] skip +PIPE2 <- '||' skip +PIPEEQUAL <- '|=' skip +PLUS <- '+' ![%+=] skip +PLUS2 <- '++' skip +PLUSEQUAL <- '+=' skip +PLUSPERCENT <- '+%' ![=] skip +PLUSPERCENTEQUAL <- '+%=' 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_align <- 'align' end_of_word +KEYWORD_and <- 'and' end_of_word +KEYWORD_anyerror <- 'anyerror' 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_cancel <- 'cancel' 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_false <- 'false' 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_nakedcc <- 'nakedcc' end_of_word +KEYWORD_noalias <- 'noalias' end_of_word +KEYWORD_null <- 'null' end_of_word +KEYWORD_or <- 'or' end_of_word +KEYWORD_orelse <- 'orelse' end_of_word +KEYWORD_packed <- 'packed' end_of_word +KEYWORD_promise <- 'promise' 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_stdcallcc <- 'stdcallcc' 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_true <- 'true' end_of_word +KEYWORD_try <- 'try' end_of_word +KEYWORD_undefined <- 'undefined' end_of_word +KEYWORD_union <- 'union' end_of_word +KEYWORD_unreachable <- 'unreachable' end_of_word +KEYWORD_use <- 'use' end_of_word +KEYWORD_var <- 'var' end_of_word +KEYWORD_volatile <- 'volatile' end_of_word +KEYWORD_while <- 'while' end_of_word + +keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm / KEYWORD_async / KEYWORD_await / KEYWORD_break / KEYWORD_cancel / KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer @@ -8209,12 +8208,11 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm / KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline / KEYWORD_nakedcc / KEYWORD_noalias / KEYWORD_null / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub - / KEYWORD_resume / KEYWORD_return / KEYWORD_section + / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend / KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable - / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while -</code></pre> + / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre> {#header_close#} {#header_open|Zen#} <ul> diff --git a/src/parser.cpp b/src/parser.cpp index 0864e7ed1b..b5c67875de 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2082,7 +2082,7 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { // Section <- KEYWORD_section LPAREN Expr RPAREN static AstNode *ast_parse_section(ParseContext *pc) { - Token *first = eat_token_if(pc, TokenIdKeywordSection); + Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); if (first == nullptr) return nullptr; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 86a25b1aac..921ee4de09 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -140,7 +140,7 @@ static const struct ZigKeyword zig_keywords[] = { {"pub", TokenIdKeywordPub}, {"resume", TokenIdKeywordResume}, {"return", TokenIdKeywordReturn}, - {"section", TokenIdKeywordSection}, + {"linksection", TokenIdKeywordLinkSection}, {"stdcallcc", TokenIdKeywordStdcallCC}, {"struct", TokenIdKeywordStruct}, {"suspend", TokenIdKeywordSuspend}, @@ -1583,7 +1583,7 @@ const char * token_name(TokenId id) { case TokenIdKeywordPromise: return "promise"; case TokenIdKeywordPub: return "pub"; case TokenIdKeywordReturn: return "return"; - case TokenIdKeywordSection: return "section"; + case TokenIdKeywordLinkSection: return "linksection"; case TokenIdKeywordStdcallCC: return "stdcallcc"; case TokenIdKeywordStruct: return "struct"; case TokenIdKeywordSwitch: return "switch"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 2d0d7d56a4..1574e95571 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -82,7 +82,7 @@ enum TokenId { TokenIdKeywordPub, TokenIdKeywordResume, TokenIdKeywordReturn, - TokenIdKeywordSection, + TokenIdKeywordLinkSection, TokenIdKeywordStdcallCC, TokenIdKeywordStruct, TokenIdKeywordSuspend, diff --git a/std/zig/ast.zig b/std/zig/ast.zig index bf2c3593a4..bb2099fb75 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -503,6 +503,7 @@ pub const Node = struct { lib_name: ?*Node, type_node: ?*Node, align_node: ?*Node, + section_node: ?*Node, init_node: ?*Node, semicolon_token: TokenIndex, @@ -519,6 +520,11 @@ pub const Node = struct { i -= 1; } + if (self.section_node) |section_node| { + if (i < 1) return section_node; + i -= 1; + } + if (self.init_node) |init_node| { if (i < 1) return init_node; i -= 1; @@ -821,6 +827,7 @@ pub const Node = struct { body_node: ?*Node, lib_name: ?*Node, // populated if this is an extern declaration align_expr: ?*Node, // populated if align(A) is present + section_expr: ?*Node, // populated if linksection(A) is present pub const ParamList = SegmentedList(*Node, 2); @@ -845,6 +852,11 @@ pub const Node = struct { i -= 1; } + if (self.section_expr) |section_expr| { + if (i < 1) return section_expr; + i -= 1; + } + switch (self.return_type) { // TODO allow this and next prong to share bodies since the types are the same ReturnType.Explicit => |node| { diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 2fb811bc41..a216484d7d 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -291,6 +291,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { .body_node = null, .lib_name = ctx.lib_name, .align_expr = null, + .section_expr = null, }); try ctx.decls.push(&fn_proto.base); stack.append(State{ .FnDef = fn_proto }) catch unreachable; @@ -601,6 +602,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { .extern_export_token = ctx.extern_export_token, .type_node = null, .align_node = null, + .section_node = null, .init_node = null, .lib_name = ctx.lib_name, // initialized later @@ -622,7 +624,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.VarDeclAlign => |var_decl| { - try stack.append(State{ .VarDeclEq = var_decl }); + try stack.append(State{ .VarDeclSection = var_decl }); const next_token = nextToken(&tok_it, &tree); const next_token_index = next_token.index; @@ -637,6 +639,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { prevToken(&tok_it, &tree); continue; }, + State.VarDeclSection => |var_decl| { + try stack.append(State{ .VarDeclEq = var_decl }); + + const next_token = nextToken(&tok_it, &tree); + const next_token_index = next_token.index; + const next_token_ptr = next_token.ptr; + if (next_token_ptr.id == Token.Id.Keyword_linksection) { + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.section_node } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); + continue; + } + + prevToken(&tok_it, &tree); + continue; + }, State.VarDeclEq => |var_decl| { const token = nextToken(&tok_it, &tree); const token_index = token.index; @@ -719,7 +737,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.FnProtoAlign => |fn_proto| { - stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable; + stack.append(State{ .FnProtoSection = fn_proto }) catch unreachable; if (eatToken(&tok_it, &tree, Token.Id.Keyword_align)) |align_token| { try stack.append(State{ .ExpectToken = Token.Id.RParen }); @@ -728,6 +746,16 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { } continue; }, + State.FnProtoSection => |fn_proto| { + stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable; + + if (eatToken(&tok_it, &tree, Token.Id.Keyword_linksection)) |align_token| { + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.section_expr } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); + } + continue; + }, State.FnProtoReturnType => |fn_proto| { const token = nextToken(&tok_it, &tree); const token_index = token.index; @@ -1524,6 +1552,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { .body_node = null, .lib_name = null, .align_expr = null, + .section_expr = null, }); ctx.opt_ctx.store(&fn_proto.base); stack.append(State{ .FnProto = fn_proto }) catch unreachable; @@ -2579,6 +2608,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { .body_node = null, .lib_name = null, .align_expr = null, + .section_expr = null, }); opt_ctx.store(&fn_proto.base); stack.append(State{ .FnProto = fn_proto }) catch unreachable; @@ -2600,6 +2630,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { .body_node = null, .lib_name = null, .align_expr = null, + .section_expr = null, }); opt_ctx.store(&fn_proto.base); stack.append(State{ .FnProto = fn_proto }) catch unreachable; @@ -2985,12 +3016,14 @@ const State = union(enum) { VarDecl: VarDeclCtx, VarDeclAlign: *ast.Node.VarDecl, + VarDeclSection: *ast.Node.VarDecl, VarDeclEq: *ast.Node.VarDecl, VarDeclSemiColon: *ast.Node.VarDecl, FnDef: *ast.Node.FnProto, FnProto: *ast.Node.FnProto, FnProtoAlign: *ast.Node.FnProto, + FnProtoSection: *ast.Node.FnProto, FnProtoReturnType: *ast.Node.FnProto, ParamDecl: *ast.Node.FnProto, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 1744c9a067..2b60fb9b00 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,10 @@ +test "zig fmt: linksection" { + try testCanonical( + \\export var aoeu: u64 linksection(".text.derp") = 1234; + \\export nakedcc fn _start() linksection(".text.boot") noreturn {} + \\ + ); +} test "zig fmt: shebang line" { try testCanonical( \\#!/usr/bin/env zig diff --git a/std/zig/render.zig b/std/zig/render.zig index 832cb7fe86..e55a0beb93 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1148,6 +1148,17 @@ fn renderExpression( try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // ) } + if (fn_proto.section_expr) |section_expr| { + const section_rparen = tree.nextToken(section_expr.lastToken()); + const section_lparen = tree.prevToken(section_expr.firstToken()); + const section_kw = tree.prevToken(section_lparen); + + try renderToken(tree, stream, section_kw, indent, start_col, Space.None); // section + try renderToken(tree, stream, section_lparen, indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, section_expr, Space.None); + try renderToken(tree, stream, section_rparen, indent, start_col, Space.Space); // ) + } + switch (fn_proto.return_type) { ast.Node.FnProto.ReturnType.Explicit => |node| { return renderExpression(allocator, stream, tree, indent, start_col, node, space); @@ -1698,12 +1709,14 @@ fn renderVarDecl( try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or - var_decl.init_node != null)) Space.Space else Space.None; + var_decl.section_node != null or var_decl.init_node != null)) Space.Space else Space.None; try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space); if (var_decl.type_node) |type_node| { try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space); - const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None; + const s = if (var_decl.align_node != null or + var_decl.section_node != null or + var_decl.init_node != null) Space.Space else Space.None; try renderExpression(allocator, stream, tree, indent, start_col, type_node, s); } @@ -1714,6 +1727,17 @@ fn renderVarDecl( try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None); + const s = if (var_decl.section_node != null or var_decl.init_node != null) Space.Space else Space.None; + try renderToken(tree, stream, rparen, indent, start_col, s); // ) + } + + if (var_decl.section_node) |section_node| { + const lparen = tree.prevToken(section_node.firstToken()); + const section_kw = tree.prevToken(lparen); + const rparen = tree.nextToken(section_node.lastToken()); + try renderToken(tree, stream, section_kw, indent, start_col, Space.None); // linksection + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, section_node, Space.None); const s = if (var_decl.init_node != null) Space.Space else Space.None; try renderToken(tree, stream, rparen, indent, start_col, s); // ) } diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig index a3ba67052a..4941fe2cc2 100644 --- a/std/zig/tokenizer.zig +++ b/std/zig/tokenizer.zig @@ -46,7 +46,7 @@ pub const Token = struct { Keyword{ .bytes = "pub", .id = Id.Keyword_pub }, Keyword{ .bytes = "resume", .id = Id.Keyword_resume }, Keyword{ .bytes = "return", .id = Id.Keyword_return }, - Keyword{ .bytes = "section", .id = Id.Keyword_section }, + Keyword{ .bytes = "linksection", .id = Id.Keyword_linksection }, Keyword{ .bytes = "stdcallcc", .id = Id.Keyword_stdcallcc }, Keyword{ .bytes = "struct", .id = Id.Keyword_struct }, Keyword{ .bytes = "suspend", .id = Id.Keyword_suspend }, @@ -175,7 +175,7 @@ pub const Token = struct { Keyword_pub, Keyword_resume, Keyword_return, - Keyword_section, + Keyword_linksection, Keyword_stdcallcc, Keyword_struct, Keyword_suspend, diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 22be733d17..7339be7fad 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3867,32 +3867,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "setting a section on an extern variable", - \\extern var foo: i32 section(".text2"); + \\extern var foo: i32 linksection(".text2"); \\export fn entry() i32 { \\ return foo; \\} , - ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'", + ".tmp_source.zig:1:33: error: cannot set section of external variable 'foo'", ); cases.add( "setting a section on a local variable", \\export fn entry() i32 { - \\ var foo: i32 section(".text2") = 1234; + \\ var foo: i32 linksection(".text2") = 1234; \\ return foo; \\} , - ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'", + ".tmp_source.zig:2:30: error: cannot set section of local variable 'foo'", ); cases.add( "setting a section on an extern fn", - \\extern fn foo() section(".text2") void; + \\extern fn foo() linksection(".text2") void; \\export fn entry() void { \\ foo(); \\} , - ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'", + ".tmp_source.zig:1:29: error: cannot set section of external function 'foo'", ); cases.add( |
