Commit 704374e512

Andrew Kelley <superjoe30@gmail.com>
2018-11-17 07:38:35
rename `section` keyword to `linksection`
add zig fmt support for this syntax closes #1152
1 parent 3862962
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,
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 &lt;- skip ContainerMembers eof
 
 # *** Top level ***
 ContainerMembers
-    <- TestDecl ContainerMembers
+    &lt;- TestDecl ContainerMembers
      / TopLevelComptime ContainerMembers
      / KEYWORD_pub? TopLevelDecl ContainerMembers
      / KEYWORD_pub? ContainerField COMMA ContainerMembers
      / KEYWORD_pub? ContainerField
      /
 
-TestDecl <- KEYWORD_test STRINGLITERAL Block
+TestDecl &lt;- KEYWORD_test STRINGLITERAL Block
 
-TopLevelComptime <- KEYWORD_comptime BlockExpr
+TopLevelComptime &lt;- KEYWORD_comptime BlockExpr
 
 TopLevelDecl
-    <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
+    &lt;- (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 &lt;- 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 &lt;- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
 
-ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
+ContainerField &lt;- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
 
 # *** Block Level ***
 Statement
-    <- KEYWORD_comptime? VarDecl
+    &lt;- 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 )?
+    &lt;- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )?
      / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
 
-LabeledStatement <- BlockLabel? (Block / LoopStatement)
+LabeledStatement &lt;- BlockLabel? (Block / LoopStatement)
 
-LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
+LoopStatement &lt;- KEYWORD_inline? (ForStatement / WhileStatement)
 
 ForStatement
-    <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
+    &lt;- ForPrefix BlockExpr ( KEYWORD_else Statement )?
      / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
 
 WhileStatement
-    <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
+    &lt;- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
      / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
 
 BlockExprStatement
-    <- BlockExpr
+    &lt;- BlockExpr
      / AssignExpr SEMICOLON
 
-BlockExpr <- BlockLabel? Block
+BlockExpr &lt;- BlockLabel? Block
 
 # *** Expression Level ***
-AssignExpr <- Expr (AssignOp Expr)?
+AssignExpr &lt;- Expr (AssignOp Expr)?
 
-Expr <- KEYWORD_try* BoolOrExpr
+Expr &lt;- KEYWORD_try* BoolOrExpr
 
-BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
+BoolOrExpr &lt;- BoolAndExpr (KEYWORD_or BoolAndExpr)*
 
-BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)*
+BoolAndExpr &lt;- CompareExpr (KEYWORD_and CompareExpr)*
 
-CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
+CompareExpr &lt;- BitwiseExpr (CompareOp BitwiseExpr)?
 
-BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
+BitwiseExpr &lt;- BitShiftExpr (BitwiseOp BitShiftExpr)*
 
-BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)*
+BitShiftExpr &lt;- AdditionExpr (BitShiftOp AdditionExpr)*
 
-AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)*
+AdditionExpr &lt;- MultiplyExpr (AdditionOp MultiplyExpr)*
 
-MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)*
+MultiplyExpr &lt;- PrefixExpr (MultiplyOp PrefixExpr)*
 
-PrefixExpr <- PrefixOp* PrimaryExpr
+PrefixExpr &lt;- PrefixOp* PrimaryExpr
 
 PrimaryExpr
-    <- AsmExpr
+    &lt;- AsmExpr
      / IfExpr
      / KEYWORD_break BreakLabel? Expr?
      / KEYWORD_cancel Expr
@@ -7807,35 +7806,35 @@ PrimaryExpr
      / LabeledExpr
      / CurlySuffixExpr
 
-IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
+IfExpr &lt;- IfPrefix Expr (KEYWORD_else Payload? Expr)?
 
-LabeledExpr <- BlockLabel? (Block / LoopExpr)
+LabeledExpr &lt;- BlockLabel? (Block / LoopExpr)
 
-Block <- LBRACE Statement* RBRACE
+Block &lt;- LBRACE Statement* RBRACE
 
-LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
+LoopExpr &lt;- KEYWORD_inline? (ForExpr / WhileExpr)
 
-ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
+ForExpr &lt;- ForPrefix Expr (KEYWORD_else Expr)?
 
-WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
+WhileExpr &lt;- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
 
-CurlySuffixExpr <- TypeExpr InitList?
+CurlySuffixExpr &lt;- TypeExpr InitList?
 
 InitList
-    <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
+    &lt;- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
      / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
      / LBRACE RBRACE
 
-TypeExpr <- PrefixTypeOp* ErrorUnionExpr
+TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr
 
-ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
+ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
 
 SuffixExpr
-    <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets
+    &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets
      / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)*
 
 PrimaryTypeExpr
-    <- BUILTININDENTIFIER FnCallArgumnets
+    &lt;- BUILTININDENTIFIER FnCallArgumnets
      / CHAR_LITERAL
      / ContainerDecl
      / ErrorSetDecl
@@ -7858,91 +7857,91 @@ PrimaryTypeExpr
      / STRINGLITERAL
      / SwitchExpr
 
-ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
+ContainerDecl &lt;- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
 
-ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
+ErrorSetDecl &lt;- KEYWORD_error LBRACE IdentifierList RBRACE
 
-GroupedExpr <- LPAREN Expr RPAREN
+GroupedExpr &lt;- LPAREN Expr RPAREN
 
-IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
+IfTypeExpr &lt;- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
 
 LabeledTypeExpr
-    <- BlockLabel Block
+    &lt;- BlockLabel Block
      / BlockLabel? LoopTypeExpr
 
-LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
+LoopTypeExpr &lt;- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
 
-ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
+ForTypeExpr &lt;- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
 
-WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
+WhileTypeExpr &lt;- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
 
-SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
+SwitchExpr &lt;- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
 
 # *** Assembly ***
-AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN
+AsmExpr &lt;- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN
 
-AsmOutput <- COLON AsmOutputList AsmInput?
+AsmOutput &lt;- COLON AsmOutputList AsmInput?
 
-AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
+AsmOutputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
 
-AsmInput <- COLON AsmInputList AsmCloppers?
+AsmInput &lt;- COLON AsmInputList AsmCloppers?
 
-AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
+AsmInputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
 
-AsmCloppers <- COLON StringList
+AsmCloppers &lt;- COLON StringList
 
 # *** Helper grammar ***
-BreakLabel <- COLON IDENTIFIER
+BreakLabel &lt;- COLON IDENTIFIER
 
-BlockLabel <- IDENTIFIER COLON
+BlockLabel &lt;- IDENTIFIER COLON
 
-FieldInit <- DOT IDENTIFIER EQUAL Expr
+FieldInit &lt;- DOT IDENTIFIER EQUAL Expr
 
-WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
+WhileContinueExpr &lt;- COLON LPAREN AssignExpr RPAREN
 
-Section <- KEYWORD_section LPAREN Expr RPAREN
+LinkSection &lt;- KEYWORD_linksection LPAREN Expr RPAREN
 
 # Fn specific
 FnCC
-    <- KEYWORD_nakedcc
+    &lt;- KEYWORD_nakedcc
      / KEYWORD_stdcallcc
      / KEYWORD_extern
      / KEYWORD_async (LARROW TypeExpr RARROW)?
 
-ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
+ParamDecl &lt;- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
 
 ParamType
-    <- KEYWORD_var
+    &lt;- KEYWORD_var
      / DOT3
      / TypeExpr
 
 # Control flow prefixes
-IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
+IfPrefix &lt;- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
 
-WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
+WhilePrefix &lt;- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
 
-ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
+ForPrefix &lt;- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
 
 # Payloads
-Payload <- PIPE IDENTIFIER PIPE
+Payload &lt;- PIPE IDENTIFIER PIPE
 
-PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
+PtrPayload &lt;- PIPE ASTERISK? IDENTIFIER PIPE
 
-PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
+PtrIndexPayload &lt;- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
 
 
 # Switch specific
-SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
+SwitchProng &lt;- SwitchCase EQUALRARROW PtrPayload? AssignExpr
 
 SwitchCase
-    <- SwitchItem (COMMA SwitchItem)* COMMA?
+    &lt;- SwitchItem (COMMA SwitchItem)* COMMA?
      / KEYWORD_else
 
-SwitchItem <- Expr (DOT3 Expr)?
+SwitchItem &lt;- Expr (DOT3 Expr)?
 
 # Operators
 AssignOp
-    <- ASTERISKEQUAL
+    &lt;- ASTERISKEQUAL
      / SLASHEQUAL
      / PERCENTEQUAL
      / PLUSEQUAL
@@ -7958,7 +7957,7 @@ AssignOp
      / EQUAL
 
 CompareOp
-    <- EQUALEQUAL
+    &lt;- EQUALEQUAL
      / EXCLAMATIONMARKEQUAL
      / LARROW
      / RARROW
@@ -7966,25 +7965,25 @@ CompareOp
      / RARROWEQUAL
 
 BitwiseOp
-    <- AMPERSAND
+    &lt;- AMPERSAND
      / CARET
      / PIPE
      / KEYWORD_orelse
      / KEYWORD_catch Payload?
 
 BitShiftOp
-    <- LARROW2
+    &lt;- LARROW2
      / RARROW2
 
 AdditionOp
-    <- PLUS
+    &lt;- PLUS
      / MINUS
      / PLUS2
      / PLUSPERCENT
      / MINUSPERCENT
 
 MultiplyOp
-    <- PIPE2
+    &lt;- PIPE2
      / ASTERISK
      / SLASH
      / PERCENT
@@ -7992,7 +7991,7 @@ MultiplyOp
      / ASTERISKPERCENT
 
 PrefixOp
-    <- EXCLAMATIONMARK
+    &lt;- EXCLAMATIONMARK
      / MINUS
      / TILDE
      / MINUSPERCENT
@@ -8001,77 +8000,77 @@ PrefixOp
      / KEYWORD_await
 
 PrefixTypeOp
-    <- QUESTIONMARK
+    &lt;- 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
+    &lt;- LBRACKET Expr (DOT2 Expr?)? RBRACKET
      / DOT IDENTIFIER
      / DOTASTERISK
      / DOTQUESTIONMARK
 
-AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)?
+AsyncPrefix &lt;- KEYWORD_async (LARROW PrefixExpr RARROW)?
 
-FnCallArgumnets <- LPAREN ExprList RPAREN
+FnCallArgumnets &lt;- LPAREN ExprList RPAREN
 
 # Ptr specific
-ArrayTypeStart <- LBRACKET Expr? RBRACKET
+ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
 
 PtrTypeStart
-    <- ASTERISK
+    &lt;- ASTERISK
      / ASTERISK2
      / LBRACKET ASTERISK RBRACKET
 
 # ContainerDecl specific
-ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
+ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
 
 ContainerDeclType
-    <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?
+    &lt;- (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 &lt;- KEYWORD_align LPAREN Expr RPAREN
 
 # Lists
-IdentifierList <- (IDENTIFIER COMMA)* IDENTIFIER?
+IdentifierList &lt;- (IDENTIFIER COMMA)* IDENTIFIER?
 
-SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
+SwitchProngList &lt;- (SwitchProng COMMA)* SwitchProng?
 
-AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem?
+AsmOutputList &lt;- (AsmOutputItem COMMA)* AsmOutputItem?
 
-AsmInputList <- (AsmInputItem COMMA)* AsmInputItem?
+AsmInputList &lt;- (AsmInputItem COMMA)* AsmInputItem?
 
-StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL?
+StringList &lt;- (STRINGLITERAL COMMA)* STRINGLITERAL?
 
-ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
+ParamDeclList &lt;- (ParamDecl COMMA)* ParamDecl?
 
-ExprList <- (Expr COMMA)* Expr?
+ExprList &lt;- (Expr COMMA)* Expr?
 
 # *** Tokens ***
-eof <- !.
-hex <- [0-9a-fA-F]
+eof &lt;- !.
+hex &lt;- [0-9a-fA-F]
 char_escape
-    <- "\\x" hex hex
+    &lt;- "\\x" hex hex
      / "\\u" hex hex hex hex
      / "\\U" hex hex hex hex hex hex
      / "\\" [nr\\t'"]
 char_char
-    <- char_escape
+    &lt;- char_escape
      / [^\\'\n]
 string_char
-    <- char_escape
+    &lt;- char_escape
      / [^\\"\n]
 
-line_comment <- '//'[^\n]*
-line_string <- ("\\\\" [^\n]* [ \n]*)+
-line_cstring <- ("c\\\\" [^\n]* [ \n]*)+
-skip <- ([ \n] / line_comment)*
+line_comment &lt;- '//'[^\n]*
+line_string &lt;- ("\\\\" [^\n]* [ \n]*)+
+line_cstring &lt;- ("c\\\\" [^\n]* [ \n]*)+
+skip &lt;- ([ \n] / line_comment)*
 
-CHAR_LITERAL <- "'" char_char "'" skip
+CHAR_LITERAL &lt;- "'" char_char "'" skip
 FLOAT
-    <- "0b" [01]+  "." [01]+  ([eE] [-+]? [01]+)?  skip
+    &lt;- "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
+    &lt;- "0b" [01]+  skip
      / "0o" [0-7]+ skip
      / "0x" hex+   skip
      /      [0-9]+ skip
 STRINGLITERAL
-    <- "c"? "\"" string_char* "\"" skip
+    &lt;- "c"? "\"" string_char* "\"" skip
      / line_string                 skip
      / line_cstring                skip
 IDENTIFIER
-    <- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip
+    &lt;- !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 &lt;- "@"[A-Za-z_][A-Za-z0-9_]* skip
+
+
+AMPERSAND            &lt;- '&'      ![=]      skip
+AMPERSANDEQUAL       &lt;- '&='               skip
+ASTERISK             &lt;- '*'      ![*%=]    skip
+ASTERISK2            &lt;- '**'               skip
+ASTERISKEQUAL        &lt;- '*='               skip
+ASTERISKPERCENT      &lt;- '*%'     ![=]      skip
+ASTERISKPERCENTEQUAL &lt;- '*%='              skip
+CARET                &lt;- '^'      ![=]      skip
+CARETEQUAL           &lt;- '^='               skip
+COLON                &lt;- ':'                skip
+COMMA                &lt;- ','                skip
+DOT                  &lt;- '.'      ![*.?]    skip
+DOT2                 &lt;- '..'     ![.]      skip
+DOT3                 &lt;- '...'              skip
+DOTASTERISK          &lt;- '.*'               skip
+DOTQUESTIONMARK      &lt;- '.?'               skip
+EQUAL                &lt;- '='      ![>=]     skip
+EQUALEQUAL           &lt;- '=='               skip
+EQUALRARROW          &lt;- '=>'               skip
+EXCLAMATIONMARK      &lt;- '!'      ![=]      skip
+EXCLAMATIONMARKEQUAL &lt;- '!='               skip
+LARROW               &lt;- '&lt;'      ![&lt;=]     skip
+LARROW2              &lt;- '&lt;&lt;'     ![=]      skip
+LARROW2EQUAL         &lt;- '&lt;&lt;='              skip
+LARROWEQUAL          &lt;- '&lt;='               skip
+LBRACE               &lt;- '{'                skip
+LBRACKET             &lt;- '['                skip
+LPAREN               &lt;- '('                skip
+MINUS                &lt;- '-'      ![%=>]    skip
+MINUSEQUAL           &lt;- '-='               skip
+MINUSPERCENT         &lt;- '-%'     ![=]      skip
+MINUSPERCENTEQUAL    &lt;- '-%='              skip
+MINUSRARROW          &lt;- '->'               skip
+PERCENT              &lt;- '%'      ![=]      skip
+PERCENTEQUAL         &lt;- '%='               skip
+PIPE                 &lt;- '|'      ![|=]     skip
+PIPE2                &lt;- '||'               skip
+PIPEEQUAL            &lt;- '|='               skip
+PLUS                 &lt;- '+'      ![%+=]    skip
+PLUS2                &lt;- '++'               skip
+PLUSEQUAL            &lt;- '+='               skip
+PLUSPERCENT          &lt;- '+%'     ![=]      skip
+PLUSPERCENTEQUAL     &lt;- '+%='              skip
+QUESTIONMARK         &lt;- '?'                skip
+RARROW               &lt;- '>'      ![>=]     skip
+RARROW2              &lt;- '>>'     ![=]      skip
+RARROW2EQUAL         &lt;- '>>='              skip
+RARROWEQUAL          &lt;- '>='               skip
+RBRACE               &lt;- '}'                skip
+RBRACKET             &lt;- ']'                skip
+RPAREN               &lt;- ')'                skip
+SEMICOLON            &lt;- ';'                skip
+SLASH                &lt;- '/'      ![=]      skip
+SLASHEQUAL           &lt;- '/='               skip
+TILDE                &lt;- '~'                skip
+
+end_of_word &lt;- ![a-zA-Z0-9_] skip
+KEYWORD_align       &lt;- 'align'       end_of_word
+KEYWORD_and         &lt;- 'and'         end_of_word
+KEYWORD_anyerror    &lt;- 'anyerror'    end_of_word
+KEYWORD_asm         &lt;- 'asm'         end_of_word
+KEYWORD_async       &lt;- 'async'       end_of_word
+KEYWORD_await       &lt;- 'await'       end_of_word
+KEYWORD_break       &lt;- 'break'       end_of_word
+KEYWORD_cancel      &lt;- 'cancel'      end_of_word
+KEYWORD_catch       &lt;- 'catch'       end_of_word
+KEYWORD_comptime    &lt;- 'comptime'    end_of_word
+KEYWORD_const       &lt;- 'const'       end_of_word
+KEYWORD_continue    &lt;- 'continue'    end_of_word
+KEYWORD_defer       &lt;- 'defer'       end_of_word
+KEYWORD_else        &lt;- 'else'        end_of_word
+KEYWORD_enum        &lt;- 'enum'        end_of_word
+KEYWORD_errdefer    &lt;- 'errdefer'    end_of_word
+KEYWORD_error       &lt;- 'error'       end_of_word
+KEYWORD_export      &lt;- 'export'      end_of_word
+KEYWORD_extern      &lt;- 'extern'      end_of_word
+KEYWORD_false       &lt;- 'false'       end_of_word
+KEYWORD_fn          &lt;- 'fn'          end_of_word
+KEYWORD_for         &lt;- 'for'         end_of_word
+KEYWORD_if          &lt;- 'if'          end_of_word
+KEYWORD_inline      &lt;- 'inline'      end_of_word
+KEYWORD_nakedcc     &lt;- 'nakedcc'     end_of_word
+KEYWORD_noalias     &lt;- 'noalias'     end_of_word
+KEYWORD_null        &lt;- 'null'        end_of_word
+KEYWORD_or          &lt;- 'or'          end_of_word
+KEYWORD_orelse      &lt;- 'orelse'      end_of_word
+KEYWORD_packed      &lt;- 'packed'      end_of_word
+KEYWORD_promise     &lt;- 'promise'     end_of_word
+KEYWORD_pub         &lt;- 'pub'         end_of_word
+KEYWORD_resume      &lt;- 'resume'      end_of_word
+KEYWORD_return      &lt;- 'return'      end_of_word
+KEYWORD_linksection &lt;- 'linksection' end_of_word
+KEYWORD_stdcallcc   &lt;- 'stdcallcc'   end_of_word
+KEYWORD_struct      &lt;- 'struct'      end_of_word
+KEYWORD_suspend     &lt;- 'suspend'     end_of_word
+KEYWORD_switch      &lt;- 'switch'      end_of_word
+KEYWORD_test        &lt;- 'test'        end_of_word
+KEYWORD_true        &lt;- 'true'        end_of_word
+KEYWORD_try         &lt;- 'try'         end_of_word
+KEYWORD_undefined   &lt;- 'undefined'   end_of_word
+KEYWORD_union       &lt;- 'union'       end_of_word
+KEYWORD_unreachable &lt;- 'unreachable' end_of_word
+KEYWORD_use         &lt;- 'use'         end_of_word
+KEYWORD_var         &lt;- 'var'         end_of_word
+KEYWORD_volatile    &lt;- 'volatile'    end_of_word
+KEYWORD_while       &lt;- 'while'       end_of_word
+
+keyword &lt;- 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>
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;
 
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";
src/tokenizer.hpp
@@ -82,7 +82,7 @@ enum TokenId {
     TokenIdKeywordPub,
     TokenIdKeywordResume,
     TokenIdKeywordReturn,
-    TokenIdKeywordSection,
+    TokenIdKeywordLinkSection,
     TokenIdKeywordStdcallCC,
     TokenIdKeywordStruct,
     TokenIdKeywordSuspend,
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| {
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,
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
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); // )
     }
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,
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(