aboutsummaryrefslogtreecommitdiff
path: root/src/js_parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/js_parser.zig')
-rw-r--r--src/js_parser.zig66
1 files changed, 61 insertions, 5 deletions
diff --git a/src/js_parser.zig b/src/js_parser.zig
index 746b72b76..5bd0fc8e1 100644
--- a/src/js_parser.zig
+++ b/src/js_parser.zig
@@ -7,7 +7,14 @@ const options = @import("options.zig");
const alloc = @import("alloc.zig");
usingnamespace @import("strings.zig");
-const Comment = js_ast._Comment;
+usingnamespace js_ast.G;
+const S = js_ast.S;
+const B = js_ast.B;
+const T = js_lexer.T;
+const E = js_ast.E;
+const Stmt = js_ast.Stmt;
+const Expr = js_ast.Expr;
+const Binding = js_ast.Binding;
const locModuleScope = logger.Loc.Empty;
const TempRef = struct {
@@ -537,10 +544,10 @@ const P = struct {
}
pub fn pushScopeForVisitPass(p: *P, kind: js_ast.Scope.Kind, loc: logger.Loc) !void {
- const order = try p.unshiftScopeOrder();
+ var order = try p.unshiftScopeOrder();
// Sanity-check that the scopes generated by the first and second passes match
- if (nql(order.loc, loc) or nql(order.scope.kind, kind)) {
+ if (!order.loc.eql(loc) or order.scope.kind != kind) {
std.debug.panic("Expected scope ({s}, {d}) in {s}, found scope ({s}, {d})", .{ kind, loc.start, p.source.path.pretty, order.scope.kind, order.loc.start });
}
@@ -591,6 +598,43 @@ const P = struct {
}
}
+ pub fn parseStmt(p: *P, opts: *ParseStatementOptions) js_ast.Stmt {
+ var loc = p.lexer.loc();
+ var stmt: js_ast.Stmt = undefined;
+
+ switch (p.lexer.token) {
+ js_lexer.T.t_semicolon => {
+ p.lexer.next();
+ return js_ast.Stmt.init(js_ast.S.Empty{}, loc);
+ },
+
+ js_lexer.T.t_export => {
+ var previousExportKeyword = p.es6_export_keyword;
+ if (opts.is_module_scope) {
+ p.es6_export_keyword = p.lexer.range();
+ } else if (!opts.is_namespace_scope) {
+ p.lexer.unexpected();
+ }
+ p.lexer.next();
+
+ // TypeScript decorators only work on class declarations
+ // "@decorator export class Foo {}"
+ // "@decorator export abstract class Foo {}"
+ // "@decorator export default class Foo {}"
+ // "@decorator export default abstract class Foo {}"
+ // "@decorator export declare class Foo {}"
+ // "@decorator export declare abstract class Foo {}"
+ if (opts.ts_decorators != null and p.lexer.token != js_lexer.T.t_class and p.lexer.token != js_lexer.T.t_default and !p.lexer.isContextualKeyword("abstract") and !p.lexer.isContextualKeyword("declare")) {
+ p.lexer.expected(js_lexer.T.t_class);
+ }
+ },
+
+ else => {},
+ }
+
+ return stmt;
+ }
+
pub fn parseStmtsUpTo(p: *P, eend: js_lexer.T, opts: *ParseStatementOptions) ![]js_ast.Stmt {
var stmts = List(js_ast.Stmt).init(p.allocator);
try stmts.ensureCapacity(1);
@@ -599,8 +643,20 @@ const P = struct {
opts.lexical_decl = .allow_all;
var isDirectivePrologue = true;
- while (true) {
- // var comments = p.lexer
+ run: while (true) {
+ if (p.lexer.comments_to_preserve_before) |comments| {
+ for (comments) |comment| {
+ try stmts.append(Stmt.init(S.Comment{
+ .text = comment.text,
+ }, p.lexer.loc()));
+ }
+ }
+
+ if (p.lexer.token == .t_end_of_file) {
+ break :run;
+ }
+
+ var stmt = p.parseStmt(opts);
}
return stmts.toOwnedSlice();