add synchronization to the parser
This commit is contained in:
		
							parent
							
								
									084c5cc6ee
								
							
						
					
					
						commit
						7ddd37b725
					
				
					 2 changed files with 41 additions and 24 deletions
				
			
		|  | @ -38,10 +38,12 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { | |||
| 
 | ||||
|     var parser = parsers.Parser.init(allocator, &scan); | ||||
|     var root = try parser.parse(); | ||||
|     var it = root.Root.iterator(); | ||||
|     if (root == null) { | ||||
|         return Result.ParseError; | ||||
|     } | ||||
| 
 | ||||
|     std.debug.warn("parse tree\n"); | ||||
|     //printer.printNode(root, 0); | ||||
|     printer.printNode(root.?, 0); | ||||
| 
 | ||||
|     return Result.Ok; | ||||
| } | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ const scanners = @import("scanners.zig"); | |||
| const main = @import("main.zig"); | ||||
| const ast = @import("ast.zig"); | ||||
| const tokens = @import("tokens.zig"); | ||||
| const err = @import("errors.zig"); | ||||
| const ereport = @import("errors.zig"); | ||||
| const printer = @import("ast_printer.zig"); | ||||
| 
 | ||||
| const Allocator = std.mem.Allocator; | ||||
|  | @ -44,12 +44,31 @@ pub const Parser = struct { | |||
|         self.tokens.deinit(); | ||||
|     } | ||||
| 
 | ||||
|     fn doError(self: *Parser, comptime fmt: []const u8, args: ...) void { | ||||
|     fn doError(self: *Parser, comptime fmt: []const u8, args: ...) ParseError { | ||||
|         self.hadError = true; | ||||
| 
 | ||||
|         std.debug.warn("parser error at line {}\n\t", self.scanner.line); | ||||
|         std.debug.warn(fmt, args); | ||||
|         std.debug.warn("\n"); | ||||
| 
 | ||||
|         return ParseError.CompileError; | ||||
|     } | ||||
| 
 | ||||
|     fn synchronize(self: *Parser) !void { | ||||
|         // TODO is it nextToken()? | ||||
|         _ = try self.nextToken(); | ||||
| 
 | ||||
|         while (!self.isAtEnd()) { | ||||
|             if (self.previous().typ == .Semicolon) return; | ||||
| 
 | ||||
|             // TODO add more "stmt"-"starting" tokens here | ||||
|             switch (self.peek().typ) { | ||||
|                 .Fn => return, | ||||
|                 else => {}, | ||||
|             } | ||||
| 
 | ||||
|             _ = try self.nextToken(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn peek(self: *Parser) Token { | ||||
|  | @ -60,11 +79,11 @@ pub const Parser = struct { | |||
|         return self.tokens.at(self.tokens.len - 2); | ||||
|     } | ||||
| 
 | ||||
|     fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError!void { | ||||
|     fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError { | ||||
|         if (token.typ == .EOF) { | ||||
|             err.report(token.line, " at end", msg); | ||||
|             ereport.report(token.line, " at end", msg); | ||||
|         } else { | ||||
|             err.reportFmt(token.line, " at '{}': {}", token.lexeme, msg); | ||||
|             ereport.reportFmt(token.line, " at '{}': {}", token.lexeme, msg); | ||||
|         } | ||||
| 
 | ||||
|         return ParseError.CompileError; | ||||
|  | @ -104,8 +123,7 @@ pub const Parser = struct { | |||
|             return tok; | ||||
|         } | ||||
| 
 | ||||
|         try self.tokenError(self.peek(), msg); | ||||
|         return ParseError.CompileError; | ||||
|         return self.tokenError(self.peek(), msg); | ||||
|     } | ||||
| 
 | ||||
|     /// Consume the current token. Gives default error messages | ||||
|  | @ -125,8 +143,7 @@ pub const Parser = struct { | |||
|             self.peek().typ, | ||||
|         ); | ||||
| 
 | ||||
|         try self.tokenError(self.peek(), buf); | ||||
|         return ParseError.CompileError; | ||||
|         return self.tokenError(self.peek(), buf); | ||||
|     } | ||||
| 
 | ||||
|     /// check() against multiple tokens | ||||
|  | @ -369,7 +386,7 @@ pub const Parser = struct { | |||
|         return expr; | ||||
|     } | ||||
| 
 | ||||
|     pub fn parse(self: *Parser) !*ast.Node { | ||||
|     pub fn parse(self: *Parser) !?*ast.Node { | ||||
|         var root = try Node.mkRoot(self.allocator); | ||||
| 
 | ||||
|         var token_opt: ?Token = null; | ||||
|  | @ -384,7 +401,10 @@ pub const Parser = struct { | |||
|             var token = token_opt.?; | ||||
|             if (token.typ == .EOF) break; | ||||
| 
 | ||||
|             var node = try self.parseTopDecl(); | ||||
|             var node = self.parseTopDecl() catch |err| { | ||||
|                 if (err == ParseError.CompileError) return null; | ||||
|                 return err; | ||||
|             }; | ||||
|             try root.Root.append(node.*); | ||||
|         } | ||||
| 
 | ||||
|  | @ -610,8 +630,7 @@ pub const Parser = struct { | |||
|             .Enum => try self.parseEnumDecl(), | ||||
| 
 | ||||
|             else => |typ| blk: { | ||||
|                 self.doError("expected Fn, Const, Struct, got {}\n", typ); | ||||
|                 return ParseError.CompileError; | ||||
|                 return self.doError("expected Fn, Const, Struct, got {}\n", typ); | ||||
|             }, | ||||
|         }; | ||||
|     } | ||||
|  | @ -840,8 +859,7 @@ pub const Parser = struct { | |||
|             .Get => |get| { | ||||
|                 switch (op.typ) { | ||||
|                     .ColonEqual => { | ||||
|                         self.doError("can not initialize struct field"); | ||||
|                         return ParseError.CompileError; | ||||
|                         return self.doError("can not initialize struct field"); | ||||
|                     }, | ||||
| 
 | ||||
|                     .Equal => return try self.mkSet(get.struc, get.name, value), | ||||
|  | @ -860,8 +878,7 @@ pub const Parser = struct { | |||
|             }, | ||||
| 
 | ||||
|             else => |expr_typ| { | ||||
|                 self.doError("Invalid assignment target {}", expr_typ); | ||||
|                 return ParseError.CompileError; | ||||
|                 return self.doError("Invalid assignment target {}", expr_typ); | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
|  | @ -997,7 +1014,7 @@ pub const Parser = struct { | |||
|                     expr = try self.mkGet(expr, name); | ||||
|                 } | ||||
|             } else { | ||||
|                 break; | ||||
|                 return self.tokenError(self.peek(), "Expect expression."); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -1031,8 +1048,7 @@ pub const Parser = struct { | |||
|         // <expr>{a: 10 b: 10} | ||||
|         // for this to work properly, <expr> must be Variable, since its a type. | ||||
|         if (ast.ExprType(expr.*) != .Variable) { | ||||
|             self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*)); | ||||
|             return ParseError.CompileError; | ||||
|             return self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*)); | ||||
|         } | ||||
| 
 | ||||
|         var inits = ast.StructInitList.init(self.allocator); | ||||
|  | @ -1096,8 +1112,7 @@ pub const Parser = struct { | |||
|             }, | ||||
| 
 | ||||
|             else => blk: { | ||||
|                 self.doError("expected literal, got {}", curtype); | ||||
|                 return ParseError.CompileError; | ||||
|                 return self.doError("expected literal, got {}", curtype); | ||||
|             }, | ||||
|         }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue