| ... | ... | @@ -109,35 +109,284 @@ const Parser = struct { |
| 109 | 109 | fn staticAssertDeclaration(parser: *Parser) !?*Node {} |
| 110 | 110 | |
| 111 | 111 | /// DeclarationSpecifiers |
| 112 | | /// <- StorageClassSpecifier DeclarationSpecifiers? |
| 113 | | /// / TypeSpecifier DeclarationSpecifiers? |
| 114 | | /// / TypeQualifier DeclarationSpecifiers? |
| 115 | | /// / FunctionSpecifier DeclarationSpecifiers? |
| 116 | | /// / AlignmentSpecifier DeclarationSpecifiers? |
| 112 | /// <- (Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register |
| 113 | /// / Type |
| 114 | /// / Keyword_inline / Keyword_noreturn |
| 115 | /// / Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN)* |
| 117 | 116 | fn declarationSpecifiers(parser: *Parser) !*Node {} |
| 118 | 117 | |
| 119 | | /// StorageClassSpecifier |
| 120 | | /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register |
| 121 | | fn storageClassSpecifier(parser: *Parser) !*Node {} |
| 122 | | |
| 123 | | /// TypeSpecifier |
| 118 | /// Type |
| 124 | 119 | /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double |
| 125 | 120 | /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary / |
| 126 | 121 | /// / Keyword_atomic LPAREN TypeName RPAREN |
| 127 | 122 | /// / EnumSpecifier |
| 128 | 123 | /// / RecordSpecifier |
| 129 | 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 | 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 | 387 | /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn |
| 136 | 388 | fn functionSpecifier(parser: *Parser) !*Node {} |
| 137 | 389 | |
| 138 | | /// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN |
| 139 | | fn alignmentSpecifier(parser: *Parser) !*Node {} |
| 140 | | |
| 141 | 390 | /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? |
| 142 | 391 | fn enumSpecifier(parser: *Parser) !*Node {} |
| 143 | 392 | |
| ... | ... | @@ -148,19 +397,14 @@ const Parser = struct { |
| 148 | 397 | fn recordSpecifier(parser: *Parser) !*Node {} |
| 149 | 398 | |
| 150 | 399 | /// RecordField |
| 151 | | /// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON |
| 400 | /// <- Type* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON |
| 152 | 401 | /// \ StaticAssertDeclaration |
| 153 | 402 | fn recordField(parser: *Parser) !*Node {} |
| 154 | 403 | |
| 155 | 404 | /// TypeName |
| 156 | | /// <- SpecifierQualifer AbstractDeclarator? |
| 405 | /// <- Type* AbstractDeclarator? |
| 157 | 406 | fn typeName(parser: *Parser) !*Node {} |
| 158 | 407 | |
| 159 | | /// SpecifierQualifer |
| 160 | | /// <- TypeSpecifier SpecifierQualifer? |
| 161 | | /// / TypeQualifier SpecifierQualifer? |
| 162 | | fn specifierQualifer(parser: *Parser) !*Node {} |
| 163 | | |
| 164 | 408 | /// RecordDeclarator <- Declarator? (COLON ConstExpr)? |
| 165 | 409 | fn recordDeclarator(parser: *Parser) !*Node {} |
| 166 | 410 | |
| ... | ... | @@ -329,7 +573,7 @@ const Parser = struct { |
| 329 | 573 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 330 | 574 | node.@"else" = .{ |
| 331 | 575 | .tok = else_tok, |
| 332 | | .stmt = try parser.stmt(expr, .{ |
| 576 | .stmt = try parser.stmt(expr, .{ |
| 333 | 577 | .ExpectedStmt = .{ .token = it.index }, |
| 334 | 578 | }), |
| 335 | 579 | }; |
| ... | ... | @@ -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 | 679 | while (true) { |
| 436 | | const prev_tok = it.prev() orelse return; |
| 680 | const prev_tok = parser.it.prev() orelse return; |
| 437 | 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 | 683 | return; |
| 440 | 684 | } |
| 441 | 685 | } |
| ... | ... | @@ -450,4 +694,10 @@ const Parser = struct { |
| 450 | 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 | }; |