ソースを参照

支持try with resources语法

mxd 3 年 前
コミット
2737d166ba
2 ファイル変更54 行追加14 行削除
  1. 12 11
      src/scripts/parsing/ast.js
  2. 42 3
      src/scripts/parsing/parser.js

+ 12 - 11
src/scripts/parsing/ast.js

@@ -372,17 +372,18 @@ class UnaryOperation extends Node {
 }
 
 class TryStatement extends Node {
-	constructor(span, exceptionVarNode, tryBlock, catchBlock, finallyBlock) {
-		super(span)
-		this.exceptionVarNode = exceptionVarNode;
-		this.tryBlock = tryBlock;
-		this.catchBlock = catchBlock;
-		this.finallyBlock = finallyBlock;
-	}
-
-	expressions() {
-		return [...this.tryBlock, ...this.catchBlock, ...this.finallyBlock]
-	}
+    constructor(span, exceptionVarNode, tryBlock, tryResources, catchBlock, finallyBlock) {
+        super(span)
+        this.exceptionVarNode = exceptionVarNode;
+        this.tryBlock = tryBlock;
+        this.tryResources = tryResources;
+        this.catchBlock = catchBlock;
+        this.finallyBlock = finallyBlock;
+    }
+
+    expressions() {
+        return [...this.tryBlock, ...this.tryResources, ...this.catchBlock, ...this.finallyBlock]
+    }
 }
 
 class ForStatement extends Node {

+ 42 - 3
src/scripts/parsing/parser.js

@@ -128,7 +128,7 @@ export class Parser {
 		let result = null;
 		if (this.stream.match("import", false)) {
 			result = this.parseImport();
-		} else if (this.stream.match(["var", "let", "const"], false)) {
+		} else if (this.matchVarDefine()) {
 			result = this.parseVarDefine();
 		} else if (this.stream.match("if", false)) {
 			result = this.parseIfStatement();
@@ -154,7 +154,7 @@ export class Parser {
 			result = this.parseAssert();
 		} else {
 			let index = this.stream.makeIndex();
-			if (this.stream.match(TokenType.Identifier, true) && this.stream.match(TokenType.Identifier, false)) {
+			if (this.matchTypeDefine()) {
 				this.stream.resetIndex(index);
 				result = this.parseVarDefine();
 			}
@@ -169,6 +169,14 @@ export class Parser {
 		return result;
 	}
 
+	matchTypeDefine() {
+        return this.stream.match(TokenType.Identifier, true) && this.stream.match(TokenType.Identifier, false);
+    }
+
+    matchVarDefine() {
+        return this.stream.match(["var", "let", "const"], false);
+    }
+
 	checkKeyword(span) {
 		if (keywords.indexOf(span.getText()) > -1) {
 			throw new ParseException('变量名不能定义为关键字', span);
@@ -350,6 +358,37 @@ export class Parser {
 
 	parseTryStatement() {
 		let opening = this.stream.expect("try");
+		let tryResources = [];
+        if (this.stream.match("(", true)) {
+            if (this.stream.match(")", false)) {
+                // 空的 try-with-resource
+            } else {
+                while (!this.stream.match(")", false)) {
+                    if (this.stream.match(";", true)) {
+                        continue;
+                    }
+                    let result = null;
+                    if (this.matchVarDefine()) {
+                        result = this.parseVarDefine();
+                    } else {
+                        if (this.stream.matchAny(keywords, false)) {
+                            throw new ParseException("try 括号中只允许写赋值语句", this.stream.consume().getSpan());
+                        }
+                        let index = this.stream.makeIndex();
+                        if (this.matchTypeDefine()) {
+                            this.stream.resetIndex(index);
+                            result = this.parseVarDefine();
+                        }
+                        if (result == null) {
+                            this.stream.resetIndex(index);
+                            throw new ParseException("try 括号中只允许写赋值语句", this.stream.consume().getSpan());
+                        }
+                    }
+                    tryResources.push(result);
+                }
+            }
+            this.stream.expect(")");
+        }
 		let tryBlocks = this.parseFunctionBody();
 		let catchBlocks = [];
 		let finallyBlocks = [];
@@ -364,7 +403,7 @@ export class Parser {
 		if (this.stream.match("finally", true)) {
 			finallyBlocks = finallyBlocks.concat(this.parseFunctionBody());
 		}
-		return new TryStatement(new Span(opening.getSpan(), this.stream.getPrev().getSpan()), exception, tryBlocks, catchBlocks, finallyBlocks);
+		return new TryStatement(new Span(opening.getSpan(), this.stream.getPrev().getSpan()), exception, tryBlocks, tryResources, catchBlocks, finallyBlocks);
 	}
 
 	parseWhileStatement() {