| ... | @@ -109,35 +109,284 @@ const Parser = struct { | ... | @@ -109,35 +109,284 @@ const Parser = struct { |
| 109 | fn staticAssertDeclaration(parser: *Parser) !?*Node {} | 109 | fn staticAssertDeclaration(parser: *Parser) !?*Node {} |
| 110 | | 110 | |
| 111 | /// DeclarationSpecifiers | 111 | /// DeclarationSpecifiers |
| 112 | /// <- StorageClassSpecifier DeclarationSpecifiers? | 112 | /// <- (Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register |
| 113 | /// / TypeSpecifier DeclarationSpecifiers? | 113 | /// / Type |
| 114 | /// / TypeQualifier DeclarationSpecifiers? | 114 | /// / Keyword_inline / Keyword_noreturn |
| 115 | /// / FunctionSpecifier DeclarationSpecifiers? | 115 | /// / Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN)* |
| 116 | /// / AlignmentSpecifier DeclarationSpecifiers? | | |
| 117 | fn declarationSpecifiers(parser: *Parser) !*Node {} | 116 | fn declarationSpecifiers(parser: *Parser) !*Node {} |
| 118 | | 117 | |
| 119 | /// StorageClassSpecifier | 118 | /// Type |
| 120 | /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register | | |
| 121 | fn storageClassSpecifier(parser: *Parser) !*Node {} | | |
| 122 | | | |
| 123 | /// TypeSpecifier | | |
| 124 | /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double | 119 | /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double |
| 125 | /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary / | 120 | /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary / |
| 126 | /// / Keyword_atomic LPAREN TypeName RPAREN | 121 | /// / Keyword_atomic LPAREN TypeName RPAREN |
| 127 | /// / EnumSpecifier | 122 | /// / EnumSpecifier |
| 128 | /// / RecordSpecifier | 123 | /// / RecordSpecifier |
| 129 | /// / IDENTIFIER // typedef name | 124 | /// / IDENTIFIER // typedef name |
| 130 | fn typeSpecifier(parser: *Parser) !*Node {} | 125 | /// / TypeQualifier |
| | 126 | fn type(parser: *Parser, type: *Node.Type) !bool { |
| | 127 | while (try parser.typeQualifier(type.qualifiers)) {} |
| | 128 | blk: { |
| | 129 | if (parser.eatToken(.Keyword_void)) |tok| { |
| | 130 | if (type.specifier != .None) |
| | 131 | break :blk; |
| | 132 | type.specifier = .{ .Void = tok }; |
| | 133 | return true; |
| | 134 | } else if (parser.eatToken(.Keyword_char)) |tok| { |
| | 135 | switch (type.specifier) { |
| | 136 | .None => { |
| | 137 | type.specifier = .{ |
| | 138 | .Char = .{ |
| | 139 | .char = tok, |
| | 140 | }, |
| | 141 | }; |
| | 142 | }, |
| | 143 | .Int => |int| { |
| | 144 | if (int.int != null) |
| | 145 | break :blk; |
| | 146 | type.specifier = .{ |
| | 147 | .Char = .{ |
| | 148 | .char = tok, |
| | 149 | .sign = int.sign, |
| | 150 | }, |
| | 151 | }; |
| | 152 | }, |
| | 153 | else => break :blk, |
| | 154 | } |
| | 155 | return true; |
| | 156 | } else if (parser.eatToken(.Keyword_short)) |tok| { |
| | 157 | switch (type.specifier) { |
| | 158 | .None => { |
| | 159 | type.specifier = .{ |
| | 160 | .Short = .{ |
| | 161 | .short = tok, |
| | 162 | }, |
| | 163 | }; |
| | 164 | }, |
| | 165 | .Int => |int| { |
| | 166 | if (int.int != null) |
| | 167 | break :blk; |
| | 168 | type.specifier = .{ |
| | 169 | .Short = .{ |
| | 170 | .short = tok, |
| | 171 | .sign = int.sign, |
| | 172 | }, |
| | 173 | }; |
| | 174 | }, |
| | 175 | else => break :blk, |
| | 176 | } |
| | 177 | return true; |
| | 178 | } else if (parser.eatToken(.Keyword_long)) |tok| { |
| | 179 | switch (type.specifier) { |
| | 180 | .None => { |
| | 181 | type.specifier = .{ |
| | 182 | .Long = .{ |
| | 183 | .long = tok, |
| | 184 | }, |
| | 185 | }; |
| | 186 | }, |
| | 187 | .Int => |int| { |
| | 188 | type.specifier = .{ |
| | 189 | .Long = .{ |
| | 190 | .long = tok, |
| | 191 | .sign = int.sign, |
| | 192 | .int = int.int, |
| | 193 | }, |
| | 194 | }; |
| | 195 | }, |
| | 196 | .Long => |*long| { |
| | 197 | if (long.longlong != null) |
| | 198 | break :blk; |
| | 199 | long.longlong = tok; |
| | 200 | }, |
| | 201 | .Double => |*double| { |
| | 202 | if (double.long != null) |
| | 203 | break :blk; |
| | 204 | double.long = tok; |
| | 205 | }, |
| | 206 | else => break :blk, |
| | 207 | } |
| | 208 | return true; |
| | 209 | } else if (parser.eatToken(.Keyword_int)) |tok| { |
| | 210 | switch (type.specifier) { |
| | 211 | .None => { |
| | 212 | type.specifier = .{ |
| | 213 | .Int = .{ |
| | 214 | .int = tok, |
| | 215 | }, |
| | 216 | }; |
| | 217 | }, |
| | 218 | .Short => |*short| { |
| | 219 | if (short.int != null) |
| | 220 | break :blk; |
| | 221 | short.int = tok; |
| | 222 | }, |
| | 223 | .Int => |*int| { |
| | 224 | if (int.int != null) |
| | 225 | break :blk; |
| | 226 | int.int = tok; |
| | 227 | }, |
| | 228 | .Long => |*long| { |
| | 229 | if (long.int != null) |
| | 230 | break :blk; |
| | 231 | long.int = tok; |
| | 232 | }, |
| | 233 | else => break :blk, |
| | 234 | } |
| | 235 | return true; |
| | 236 | } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| { |
| | 237 | switch (type.specifier) { |
| | 238 | .None => { |
| | 239 | type.specifier = .{ |
| | 240 | .Int = .{ |
| | 241 | .sign = tok, |
| | 242 | }, |
| | 243 | }; |
| | 244 | }, |
| | 245 | .Char => |*char| { |
| | 246 | if (char.sign != null) |
| | 247 | break :blk; |
| | 248 | char.sign = tok; |
| | 249 | }, |
| | 250 | .Short => |*short| { |
| | 251 | if (short.sign != null) |
| | 252 | break :blk; |
| | 253 | short.sign = tok; |
| | 254 | }, |
| | 255 | .Int => |*int| { |
| | 256 | if (int.sign != null) |
| | 257 | break :blk; |
| | 258 | int.sign = tok; |
| | 259 | }, |
| | 260 | .Long => |*long| { |
| | 261 | if (long.sign != null) |
| | 262 | break :blk; |
| | 263 | long.sign = tok; |
| | 264 | }, |
| | 265 | else => break :blk, |
| | 266 | } |
| | 267 | return true; |
| | 268 | } else if (parser.eatToken(.Keyword_float)) |tok| { |
| | 269 | if (type.specifier != .None) |
| | 270 | break :blk; |
| | 271 | type.specifier = .{ |
| | 272 | .Float = .{ |
| | 273 | .float = tok, |
| | 274 | }, |
| | 275 | }; |
| | 276 | return true; |
| | 277 | } else if (parser.eatToken(.Keyword_double)) |tok| { |
| | 278 | if (type.specifier != .None) |
| | 279 | break :blk; |
| | 280 | type.specifier = .{ |
| | 281 | .Double = .{ |
| | 282 | .double = tok, |
| | 283 | }, |
| | 284 | }; |
| | 285 | return true; |
| | 286 | } else if (parser.eatToken(.Keyword_complex)) |tok| { |
| | 287 | switch (type.specifier) { |
| | 288 | .None => { |
| | 289 | type.specifier = .{ |
| | 290 | .Double = .{ |
| | 291 | .complex = tok, |
| | 292 | .double = null |
| | 293 | }, |
| | 294 | }; |
| | 295 | }, |
| | 296 | .Float => |*float| { |
| | 297 | if (float.complex != null) |
| | 298 | break :blk; |
| | 299 | float.complex = tok; |
| | 300 | }, |
| | 301 | .Double => |*double| { |
| | 302 | if (double.complex != null) |
| | 303 | break :blk; |
| | 304 | double.complex = tok; |
| | 305 | }, |
| | 306 | else => break :blk, |
| | 307 | } |
| | 308 | return true; |
| | 309 | } if (parser.eatToken(.Keyword_bool)) |tok| { |
| | 310 | if (type.specifier != .None) |
| | 311 | break :blk; |
| | 312 | type.specifier = .{ .Bool = tok }; |
| | 313 | return true; |
| | 314 | } else if (parser.eatToken(.Keyword_atomic)) |tok| { |
| | 315 | if (type.specifier != .None) |
| | 316 | break :blk; |
| | 317 | _ = try parser.expectToken(.LParen); |
| | 318 | const name = try parser.expect(typeName, .{ |
| | 319 | .ExpectedTypeName = .{ .tok = it.index }, |
| | 320 | }); |
| | 321 | type.specifier.Atomic = .{ |
| | 322 | .atomic = tok, |
| | 323 | .typename = name, |
| | 324 | .rparen = try parser.expectToken(.RParen), |
| | 325 | }; |
| | 326 | return true; |
| | 327 | } else if (parser.eatToken(.Keyword_enum)) |tok| { |
| | 328 | if (type.specifier != .None) |
| | 329 | break :blk; |
| | 330 | @panic("TODO enum type"); |
| | 331 | // return true; |
| | 332 | } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| { |
| | 333 | if (type.specifier != .None) |
| | 334 | break :blk; |
| | 335 | @panic("TODO record type"); |
| | 336 | // return true; |
| | 337 | } else if (parser.eatToken(.Identifier)) |tok| { |
| | 338 | if (!parser.typedefs.contains(tok)) { |
| | 339 | parser.putBackToken(tok); |
| | 340 | return false; |
| | 341 | } |
| | 342 | type.specifier = .{ |
| | 343 | .Typedef = tok, |
| | 344 | }; |
| | 345 | return true; |
| | 346 | } |
| | 347 | } |
| | 348 | try parser.tree.errors.push(.{ |
| | 349 | .InvalidTypeSpecifier = .{ |
| | 350 | .token = parser.it.index, |
| | 351 | .type = type, |
| | 352 | }, |
| | 353 | }); |
| | 354 | return error.ParseError; |
| | 355 | } |
| 131 | | 356 | |
| 132 | /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic | 357 | /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic |
| 133 | fn typeQualifier(parser: *Parser) !*Node {} | 358 | fn typeQualifier(parser: *Parser, qualifiers: *Node.Qualifiers) !bool { |
| | 359 | if (parser.eatToken(.Keyword_const)) |tok| { |
| | 360 | if (qualifiers.@"const" != null) |
| | 361 | return parser.warning(.{ |
| | 362 | .DuplicateQualifier = .{ .token = tok }, |
| | 363 | }); |
| | 364 | qualifiers.@"const" = tok; |
| | 365 | } else if (parser.eatToken(.Keyword_restrict)) |tok| { |
| | 366 | if (qualifiers.atomic != null) |
| | 367 | return parser.warning(.{ |
| | 368 | .DuplicateQualifier = .{ .token = tok }, |
| | 369 | }); |
| | 370 | qualifiers.atomic = tok; |
| | 371 | } else if (parser.eatToken(.Keyword_volatile)) |tok| { |
| | 372 | if (qualifiers.@"volatile" != null) |
| | 373 | return parser.warning(.{ |
| | 374 | .DuplicateQualifier = .{ .token = tok }, |
| | 375 | }); |
| | 376 | qualifiers.@"volatile" = tok; |
| | 377 | } else if (parser.eatToken(.Keyword_atomic)) |tok| { |
| | 378 | if (qualifiers.atomic != null) |
| | 379 | return parser.warning(.{ |
| | 380 | .DuplicateQualifier = .{ .token = tok }, |
| | 381 | }); |
| | 382 | qualifiers.atomic = tok; |
| | 383 | } else return false; |
| | 384 | return true; |
| | 385 | } |
| 134 | | 386 | |
| 135 | /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn | 387 | /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn |
| 136 | fn functionSpecifier(parser: *Parser) !*Node {} | 388 | fn functionSpecifier(parser: *Parser) !*Node {} |
| 137 | | 389 | |
| 138 | /// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN | | |
| 139 | fn alignmentSpecifier(parser: *Parser) !*Node {} | | |
| 140 | | | |
| 141 | /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? | 390 | /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? |
| 142 | fn enumSpecifier(parser: *Parser) !*Node {} | 391 | fn enumSpecifier(parser: *Parser) !*Node {} |
| 143 | | 392 | |
| ... | @@ -148,19 +397,14 @@ const Parser = struct { | ... | @@ -148,19 +397,14 @@ const Parser = struct { |
| 148 | fn recordSpecifier(parser: *Parser) !*Node {} | 397 | fn recordSpecifier(parser: *Parser) !*Node {} |
| 149 | | 398 | |
| 150 | /// RecordField | 399 | /// RecordField |
| 151 | /// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON | 400 | /// <- Type* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON |
| 152 | /// \ StaticAssertDeclaration | 401 | /// \ StaticAssertDeclaration |
| 153 | fn recordField(parser: *Parser) !*Node {} | 402 | fn recordField(parser: *Parser) !*Node {} |
| 154 | | 403 | |
| 155 | /// TypeName | 404 | /// TypeName |
| 156 | /// <- SpecifierQualifer AbstractDeclarator? | 405 | /// <- Type* AbstractDeclarator? |
| 157 | fn typeName(parser: *Parser) !*Node {} | 406 | fn typeName(parser: *Parser) !*Node {} |
| 158 | | 407 | |
| 159 | /// SpecifierQualifer | | |
| 160 | /// <- TypeSpecifier SpecifierQualifer? | | |
| 161 | /// / TypeQualifier SpecifierQualifer? | | |
| 162 | fn specifierQualifer(parser: *Parser) !*Node {} | | |
| 163 | | | |
| 164 | /// RecordDeclarator <- Declarator? (COLON ConstExpr)? | 408 | /// RecordDeclarator <- Declarator? (COLON ConstExpr)? |
| 165 | fn recordDeclarator(parser: *Parser) !*Node {} | 409 | fn recordDeclarator(parser: *Parser) !*Node {} |
| 166 | | 410 | |
| ... | @@ -329,7 +573,7 @@ const Parser = struct { | ... | @@ -329,7 +573,7 @@ const Parser = struct { |
| 329 | if (parser.eatToken(.Keyword_else)) |else_tok| { | 573 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 330 | node.@"else" = .{ | 574 | node.@"else" = .{ |
| 331 | .tok = else_tok, | 575 | .tok = else_tok, |
| 332 | .stmt = try parser.stmt(expr, .{ | 576 | .stmt = try parser.stmt(expr, .{ |
| 333 | .ExpectedStmt = .{ .token = it.index }, | 577 | .ExpectedStmt = .{ .token = it.index }, |
| 334 | }), | 578 | }), |
| 335 | }; | 579 | }; |
| ... | @@ -431,11 +675,11 @@ const Parser = struct { | ... | @@ -431,11 +675,11 @@ const Parser = struct { |
| 431 | } | 675 | } |
| 432 | } | 676 | } |
| 433 | | 677 | |
| 434 | fn putBackToken(it: *TokenIterator, putting_back: TokenIndex) void { | 678 | fn putBackToken(parser: *Parser, putting_back: TokenIndex) void { |
| 435 | while (true) { | 679 | while (true) { |
| 436 | const prev_tok = it.prev() orelse return; | 680 | const prev_tok = parser.it.prev() orelse return; |
| 437 | if (next_tok.id == .LineComment or next_tok.id == .MultiLineComment) continue; | 681 | if (next_tok.id == .LineComment or next_tok.id == .MultiLineComment) continue; |
| 438 | assert(it.list.at(putting_back) == prev_tok); | 682 | assert(parser.it.list.at(putting_back) == prev_tok); |
| 439 | return; | 683 | return; |
| 440 | } | 684 | } |
| 441 | } | 685 | } |
| ... | @@ -450,4 +694,10 @@ const Parser = struct { | ... | @@ -450,4 +694,10 @@ const Parser = struct { |
| 450 | return error.ParseError; | 694 | return error.ParseError; |
| 451 | }; | 695 | }; |
| 452 | } | 696 | } |
| | 697 | |
| | 698 | fn warning(parser: *Parser, err: ast.Error) Error { |
| | 699 | // if (parser.warnaserror) |
| | 700 | try parser.tree.errors.push(err); |
| | 701 | return error.ParseError; |
| | 702 | } |
| 453 | }; | 703 | }; |