From 68998adb611233fc3b57073cf4827c2e7896ed61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A9=B9=E6=B1=89=E8=89=AF?= Date: Wed, 5 Apr 2017 11:08:02 +0800 Subject: [PATCH] =?UTF-8?q?'=E6=94=B9=E4=B8=BAmaven=E9=A1=B9=E7=9B=AE'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .classpath | 26 + .gitignore | 1 + .project | 23 + .settings/org.eclipse.jdt.core.prefs | 13 + .settings/org.eclipse.m2e.core.prefs | 4 + pom.xml | 6 + src/main/java/com/taozeyu/taolan/App.java | 23 + .../taolan/analysis/AnalysisDefine.java | 1610 ++++++++--------- .../taozeyu/taolan/analysis/AnalysisNode.java | 96 +- .../taolan/analysis/FirstSetConstructor.java | 410 ++--- .../taolan/analysis/LexicalAnalysis.java | 506 +++--- .../analysis/LexicalAnalysisException.java | 28 +- .../taolan/analysis/NonTerminalSymbol.java | 206 +-- .../taozeyu/taolan/analysis/SignParser.java | 186 +- .../taolan/analysis/SyntacticAnalysis.java | 376 ++-- .../analysis/SyntacticAnalysisException.java | 32 +- .../taolan/analysis/SyntacticDefine.java | 668 +++---- .../taolan/analysis/TerminalSymbol.java | 170 +- .../com/taozeyu/taolan/analysis/Token.java | 152 +- .../taolan/analysis/node/ArrayNode.java | 54 +- .../taolan/analysis/node/ChunkNode.java | 42 +- .../taolan/analysis/node/CommandNode.java | 50 +- .../taolan/analysis/node/ContainerNode.java | 74 +- .../analysis/node/DefineFunctionNode.java | 90 +- .../analysis/node/DefineVariableNode.java | 46 +- .../taolan/analysis/node/ElementNode.java | 144 +- .../taolan/analysis/node/ExpressionNode.java | 236 +-- .../taolan/analysis/node/ForEachLoopNode.java | 56 +- .../taolan/analysis/node/IfElseNode.java | 94 +- .../taolan/analysis/node/InvokerNode.java | 46 +- .../taolan/analysis/node/LambdaNode.java | 54 +- .../taolan/analysis/node/LoopChunkNode.java | 74 +- .../taolan/analysis/node/OperateNode.java | 40 +- .../taolan/analysis/node/StartChunkNode.java | 30 +- .../taolan/analysis/node/TryCatchNode.java | 118 +- .../taolan/analysis/node/WhenNode.java | 34 +- .../taolan/intermediatecode/ChunkContext.java | 124 +- .../taolan/intermediatecode/CodeChunk.java | 368 ++-- .../taolan/intermediatecode/CodeCreator.java | 510 +++--- .../intermediatecode/ExpressionGenerator.java | 848 ++++----- .../intermediatecode/FunctionGenerator.java | 324 ++-- .../intermediatecode/FunctionRecorder.java | 44 +- .../IntermediateCodeCreator.java | 66 +- .../IntermediateCodeExpression.java | 24 +- .../taolan/intermediatecode/JumpStack.java | 86 +- .../intermediatecode/LocalVariablePool.java | 52 +- .../PlaceholderReplacement.java | 156 +- .../intermediatecode/PositionPlaceholder.java | 48 +- .../intermediatecode/VariableGenerator.java | 86 +- .../intermediatecode/VariableRecorder.java | 78 +- .../taolan/virtualMachine/DataChunk.java | 0 .../taolan/virtualMachine/Interpreter.java | 0 .../taolan/virtualMachine/NativeFunction.java | 0 .../taolan/virtualMachine/Runtime.java | 0 .../virtualMachine/TaolanNativeObject.java | 0 .../taolan/virtualMachine/TaolanObject.java | 0 .../taozeyu/taolan/virtualMachine/Value.java | 0 .../taolan/virtualMachine/VirtualMachine.java | 2 +- .../nativeobject/ArrayNativeObject.java | 0 .../nativeobject/ContainerNativeObject.java | 0 src/main/java/script/test.t | 11 + src/{ => main/java}/system_lib/Array.t | 0 src/{ => main/java}/system_lib/Container.t | 0 src/{ => main/java}/system_lib/Error.t | 0 src/{ => main/java}/system_lib/Object.t | 0 65 files changed, 4376 insertions(+), 4269 deletions(-) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 pom.xml create mode 100644 src/main/java/com/taozeyu/taolan/App.java rename src/{ => main/java}/com/taozeyu/taolan/analysis/AnalysisDefine.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/AnalysisNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/FirstSetConstructor.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/LexicalAnalysis.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/LexicalAnalysisException.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/NonTerminalSymbol.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/SignParser.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/SyntacticAnalysis.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/SyntacticDefine.java (98%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/TerminalSymbol.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/Token.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/ArrayNode.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/ChunkNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/CommandNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/ContainerNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/DefineVariableNode.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/ElementNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/ExpressionNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/IfElseNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/InvokerNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/LambdaNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/LoopChunkNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/OperateNode.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/StartChunkNode.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/TryCatchNode.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/analysis/node/WhenNode.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/ChunkContext.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/CodeChunk.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/CodeCreator.java (98%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/ExpressionGenerator.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/JumpStack.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java (95%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/VariableGenerator.java (97%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/intermediatecode/VariableRecorder.java (96%) mode change 100755 => 100644 rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/DataChunk.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/Interpreter.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/NativeFunction.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/Runtime.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/TaolanNativeObject.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/TaolanObject.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/Value.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/VirtualMachine.java (99%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/nativeobject/ArrayNativeObject.java (100%) rename src/{ => main/java}/com/taozeyu/taolan/virtualMachine/nativeobject/ContainerNativeObject.java (100%) create mode 100644 src/main/java/script/test.t rename src/{ => main/java}/system_lib/Array.t (100%) rename src/{ => main/java}/system_lib/Container.t (100%) rename src/{ => main/java}/system_lib/Error.t (100%) rename src/{ => main/java}/system_lib/Object.t (100%) diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..9c865fb --- /dev/null +++ b/.classpath @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.project b/.project new file mode 100644 index 0000000..021be0c --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + TaolanTutorial + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..13b3428 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b3d993d --- /dev/null +++ b/pom.xml @@ -0,0 +1,6 @@ + + 4.0.0 + TaolanTutorial + TaolanTutorial + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/src/main/java/com/taozeyu/taolan/App.java b/src/main/java/com/taozeyu/taolan/App.java new file mode 100644 index 0000000..ddad594 --- /dev/null +++ b/src/main/java/com/taozeyu/taolan/App.java @@ -0,0 +1,23 @@ +package com.taozeyu.taolan; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.taozeyu.taolan.analysis.LexicalAnalysisException; +import com.taozeyu.taolan.analysis.SyntacticAnalysisException; +import com.taozeyu.taolan.intermediatecode.IntermediateCodeExpression; +import com.taozeyu.taolan.virtualMachine.VirtualMachine; + +public class App { + public static void main(String[] args) throws SyntacticAnalysisException, LexicalAnalysisException, IOException, IntermediateCodeExpression { + String base = App.class.getClassLoader().getResource("").getPath(); + String path = base + File.separator + "script" + File.separator + "test.t"; + File file = new File(path); + FileInputStream fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis); + VirtualMachine vm = VirtualMachine.instance(); + vm.run(isr); + } +} diff --git a/src/com/taozeyu/taolan/analysis/AnalysisDefine.java b/src/main/java/com/taozeyu/taolan/analysis/AnalysisDefine.java old mode 100755 new mode 100644 similarity index 97% rename from src/com/taozeyu/taolan/analysis/AnalysisDefine.java rename to src/main/java/com/taozeyu/taolan/analysis/AnalysisDefine.java index 7a6daca..e0acb8f --- a/src/com/taozeyu/taolan/analysis/AnalysisDefine.java +++ b/src/main/java/com/taozeyu/taolan/analysis/AnalysisDefine.java @@ -1,805 +1,805 @@ -package com.taozeyu.taolan.analysis; - -import java.io.PrintStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; -import com.taozeyu.taolan.analysis.Token.Type; -import com.taozeyu.taolan.analysis.node.ArrayNode; -import com.taozeyu.taolan.analysis.node.ChunkNode; -import com.taozeyu.taolan.analysis.node.CommandNode; -import com.taozeyu.taolan.analysis.node.DefineFunctionNode; -import com.taozeyu.taolan.analysis.node.DefineVariableNode; -import com.taozeyu.taolan.analysis.node.ElementNode; -import com.taozeyu.taolan.analysis.node.ElementNode.ElementType; -import com.taozeyu.taolan.analysis.node.OperateNode; -import com.taozeyu.taolan.analysis.node.StartChunkNode; -import com.taozeyu.taolan.analysis.node.WhenNode; -import com.taozeyu.taolan.analysis.node.ExpressionNode; -import com.taozeyu.taolan.analysis.node.ForEachLoopNode; -import com.taozeyu.taolan.analysis.node.IfElseNode; -import com.taozeyu.taolan.analysis.node.InvokerNode; -import com.taozeyu.taolan.analysis.node.LambdaNode; -import com.taozeyu.taolan.analysis.node.LoopChunkNode; -import com.taozeyu.taolan.analysis.node.TryCatchNode; - -class AnalysisDefine { - - private static final HashMap> containerMap = new HashMap<>(); - private static final Supplier containerNodeSupplier = new Supplier() { - @Override - public AnalysisNode get() { - return new DefaultContainerNode(); - } - }; - /** 仅可用于双目运算符 */ - private static final Supplier expressionDefaultNode = new Supplier() { - @Override - public AnalysisNode get() { - return new ExpressionDefaultNode(); - } - }; - private static final Pattern IntegerPattern = Pattern.compile("\\d+"); - - static { - creator(new Exp[] {Exp.Number}, () -> { - return new ElementNode() { - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(Type.Number != token.type) { - return; - } - Matcher matcher = IntegerPattern.matcher(token.value); - if(!matcher.matches()) { - throw new SyntacticAnalysisException(token); - } - if(this.value == null) { - this.type = ElementType.Integer; - this.value = token.value; - - } else { - this.type = ElementType.Number; - this.value += "." + token.value; - } - } - }; - }); - creator(new Exp[] {Exp.Variable}, () -> { - return new ElementNode() { - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(Type.Identifier == token.type) { - this.type = ElementType.Variable; - this.value = token.value; - - } else if(Type.Sign == token.type) { - if("@".equals(token.value)) { - this.fromThis = true; - } else if("@@".equals(token.value)) { - this.fromConstructor = true; - } - } - } - }; - }); - creator(new Exp[] {Exp.String}, () -> { - return new ElementNode() { - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(Type.Identifier == token.type || Type.String == token.type) { - this.type = ElementType.String; - this.value = token.value; - } - } - }; - }); - creator(new Exp[] {Exp.This, Exp.Null}, () -> { - return new ElementNode() { - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if("this".equals(token.value)) { - this.type = ElementType.This; - } else if("null".equals(token.value)) { - this.type = ElementType.Null; - } - } - }; - }); - creator(new Exp[] {Exp.Boolean}, () -> { - return new ElementNode() { - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - this.type = ElementType.Boolean; - this.value = token.value; - } - }; - }); - creator(new Exp[] {Exp.RegEx}, () -> { - return new ElementNode() { - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(Type.RegEx == token.type) { - this.type = ElementType.RegEx; - this.value = token.value; - } - } - }; - }); - creator(new Exp[] {Exp.L11Expression}, () -> { - return new ExpressionNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - analysisNode = tryGetSingleElement(analysisNode); - - if(analysisNode instanceof ExpressionNode) { - this.expressionOperands[0] = (ExpressionNode) analysisNode; - } - else if(analysisNode instanceof ElementNode) { - this.elementOperands[0] = (ElementNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException {} - }; - }); - creator(new Exp[] { - Exp.L10Expression, Exp.L8Expression, - Exp.L7Expression, Exp.L6Expression, - Exp.L5Expression, Exp.L4Expression, - Exp.L3Expression, Exp.L2Expression, - Exp.L0Expression, - - Exp.L10ParamExpression, Exp.L8ParamExpression, - Exp.L7ParamExpression, Exp.L6ParamExpression, - Exp.L5ParamExpression, Exp.L4ParamExpression, - Exp.L3ParamExpression, Exp.L2ParamExpression, - Exp.L0ParamExpression, - - }, expressionDefaultNode); - - creator(new Exp[] {Exp.L9Expression, Exp.L9ParamExpression}, () -> { - return new ExpressionNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - analysisNode = tryGetSingleElement(analysisNode); - if(analysisNode instanceof ExpressionNode) { - this.expressionOperands[0] = (ExpressionNode)analysisNode; - } else { - this.elementOperands[0] = (ElementNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) { - if(token.type == Type.Sign) { - this.sign = token.value; - } - } - }; - }); - creator(new Exp[] {Exp.L1Expression, Exp.L1ParamExpression}, () -> { - return new ExpressionNode() { - - private int hasSetOperands = 0; - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - analysisNode = tryGetSingleElement(analysisNode); - if(analysisNode instanceof ExpressionNode) { - this.expressionOperands[hasSetOperands] = (ExpressionNode)analysisNode; - } else { - this.elementOperands[hasSetOperands] = (ElementNode) analysisNode; - } - hasSetOperands++; - if(hasSetOperands >= 3) { - this.sign = "?:"; - } - } - - @Override - public void match(TerminalSymbol token) {} - }; - }); - creator(new Exp[] {Exp.Chunk}, () -> { - return new ChunkNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - analysisNode = expression; - } - lineList.add(analysisNode); - } - - @Override - public void match(TerminalSymbol token) { } - }; - }); - creator(new Exp[] {Exp.StartChunk}, () -> { - return new StartChunkNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ChunkNode) { - chunk = (ChunkNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) { } - }; - }); - creator(new Exp[] {Exp.Command}, () -> { - return new CommandNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - - if(analysisNode instanceof ExpressionNode) { - expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - - } else if(analysisNode instanceof WhenNode){ - condition = (WhenNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) { - if(token.type == Type.Keyword) { - command = token.value; - } - } - }; - }); - creator(new Exp[] {Exp.Operate}, () -> { - return new OperateNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - - if(analysisNode instanceof ExpressionNode) { - expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - - } else if(analysisNode instanceof WhenNode){ - condition = (WhenNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) { } - }; - }); - creator(new Exp[] {Exp.DefineVariableElement}, () -> { - return new DefineVariableNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - - if(analysisNode instanceof ExpressionNode) { - initValue = (ExpressionNode) analysisNode; - clearRedundancy(initValue); - } - } - - @Override - public void match(TerminalSymbol token) { - if(token.type == Type.Identifier) { - variableName = token.value; - } - } - }; - }); - creator(new Exp[] {Exp.DefineFunction}, () -> { - return new DefineFunctionNode() { - - private boolean nextIdentifyIsFunctionName = false; - private boolean hasHandledFunctionName = false; - - private boolean hasOperator = false; - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - parentExpression = expression; - AnalysisNode target = tryGetSingleElement(expression); - if(target instanceof ElementNode) { - ElementNode element = (ElementNode) target; - if(element.type == ElementType.Variable && !element.fromThis && !element.fromConstructor) { - functionName = element.value; - } - } - - } else if (analysisNode instanceof ChunkNode) { - body = (ChunkNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(token.type == Type.Keyword && "operator".equals(token.value)) { - hasOperator = true; - - } else if(hasOperator && token.type == Type.Sign) { - operator = token.value; - hasOperator = false; - - } else if(token.type == Type.Sign && "->".equals(token.value)) { - nextIdentifyIsFunctionName = true; - - } else if(token.type == Type.Identifier) { - if(!tryToHandleFunctionName(token.value)) { - paramNames.add(token.value); - } - } - } - - @Override - public void finish() throws SyntacticAnalysisException { - tryToHandleFunctionName(functionName); - } - - private boolean tryToHandleFunctionName(String name) throws SyntacticAnalysisException { - boolean success = false; - if(!hasHandledFunctionName) { - success = true; - if(nextIdentifyIsFunctionName) { - functionName = name; - } else { - success = false; - parentExpression = null; - } - if(functionName == null) { - throw new SyntacticAnalysisException(); - } - hasHandledFunctionName = true; - } - return success; - } - }; - }); - creator(new Exp[] {Exp.IfElseChunk}, () -> { - return new IfElseNode() { - - private boolean isNextCondition; - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - addExpression(expression); - } - else if(analysisNode instanceof ChunkNode) { - ChunkNode chunck = (ChunkNode) analysisNode; - if(isNextCondition) { - addChunk(chunck); - } else { - elseChuck = chunck; - } - } - } - - @Override - public void match(TerminalSymbol token) { - if(token.type == Type.Keyword) { - if("if".equals(token.value) || "elsif".equals(token.value)) { - isNextCondition = true; - - } else { - isNextCondition = false; - } - } - } - }; - }); - creator(new Exp[] {Exp.When}, () -> { - return new WhenNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - - if(analysisNode instanceof ExpressionNode) { - condition = (ExpressionNode) analysisNode; - clearRedundancy(condition); - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { } - }; - }); - creator(new Exp[] {Exp.TryCatch}, () -> { - return new TryCatchNode() { - - private String lastKeyword; - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - addErrorType(expression); - } - else if(analysisNode instanceof ChunkNode) { - ChunkNode chunk = (ChunkNode) analysisNode; - if(lastKeyword.equals("try")) { - tryChunk = chunk; - - } else if(lastKeyword.equals("finally")) { - finallyChunk = chunk; - - } else if(lastKeyword.equals("catch")) { - addChunk(chunk); - } - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(token.type == Type.Keyword) { - lastKeyword = token.value; - - } else if(token.type == Type.Identifier) { - addErrorName(token.value); - } - } - }; - }); - creator(new Exp[] {Exp.WhileChunk}, () -> { - return new LoopChunkNode() { - { - isWhile = true; - } - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - condition = (ExpressionNode) analysisNode; - clearRedundancy(condition); - } - else if(analysisNode instanceof ChunkNode) { - chunk = (ChunkNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException {} - }; - }); - creator(new Exp[] {Exp.DoUntilChunk}, () -> { - return new LoopChunkNode() { - { - isWhile = false; - } - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - condition = (ExpressionNode) analysisNode; - clearRedundancy(condition); - } - else if(analysisNode instanceof ChunkNode) { - chunk = (ChunkNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException {} - }; - }); - creator(new Exp[] {Exp.ForEachCommand}, containerNodeSupplier); - creator(new Exp[] {Exp.ForEachChunk}, () -> { - return new ForEachLoopNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof DefaultContainerNode) { - DefaultContainerNode container = (DefaultContainerNode) analysisNode; - List list = new LinkedList<>(); - if(beforeCommandList == null) { - beforeCommandList = list; - } else { - afterCommandList = list; - } - for(Object obj:container) { - if(obj instanceof ExpressionNode) { - list.add((ExpressionNode) obj); - ExpressionNode node = (ExpressionNode) obj; - clearRedundancy(node); - - } else if(obj instanceof DefineVariableNode) { - list.add((DefineVariableNode) obj); - } - } - } - else if(analysisNode instanceof ExpressionNode) { - loopCondition = (ExpressionNode) analysisNode; - clearRedundancy(loopCondition); - } - else if(analysisNode instanceof ChunkNode) { - chunk = (ChunkNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException {} - }; - }); - creator(new Exp[] {Exp.Lambda}, () -> { - return new LambdaNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ChunkNode) { - chunk = (ChunkNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(token.type == Type.Identifier) { - paramNameList.add(token.value); - } - } - }; - }); - creator(new Exp[] { - Exp.Invoker, Exp.InvokerBraceless, - Exp.InvokerBanLambda, Exp.InvokerBracelessBanLambda - }, () -> { - return new InvokerNode() { - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - paramList.add(expression); - - } else if(analysisNode instanceof LambdaNode) { - lambda = (LambdaNode) analysisNode; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException {} - }; - }); - creator(new Exp[] {Exp.Array}, () -> { - return new ElementNode() { - { - array = new ArrayNode(); - type = ElementType.Array; - } - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - array.content.add(expression); - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException {} - }; - }); - creator(new Exp[] {Exp.Container}, () -> { - return new ElementNode() { - { - container = new com.taozeyu.taolan.analysis.node.ContainerNode(); - type = ElementType.Container; - } - private String keyBuffered = null; - - @Override - public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { - if(analysisNode instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) analysisNode; - clearRedundancy(expression); - container.content.put(keyBuffered, expression); - } - else if(analysisNode instanceof ElementNode) { - keyBuffered = ((ElementNode) analysisNode).value; - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(token.type == Type.Identifier) { - keyBuffered = token.value; - } - } - }; - }); - } - - static AnalysisNode createContainer(Exp exp) { - Supplier supplier = containerMap.get(exp); - AnalysisNode analysisNode = null; - if(supplier != null) { - analysisNode = supplier.get(); - analysisNode.setExp(exp); - } - return analysisNode; - } - - private static void clearRedundancy(ExpressionNode node) { - if(node.sign == null && node.invoker == null && node.isExpression(0) && !node.any(1)) { - ExpressionNode child = node.getExpressionAt(0); - AnalysisNode target = tryGetSingleElement(child); - if(target instanceof ExpressionNode) { - node.copy((ExpressionNode) target); - } else { - node.clear(); - node.elementOperands[0] = (ElementNode) target; - } - - } else { - for(int i=0; i<3; ++i) { - if(node.isExpression(i)) { - ExpressionNode child = node.getExpressionAt(i); - AnalysisNode target = tryGetSingleElement(child); - if(target instanceof ElementNode) { - node.expressionOperands[i] = null; - node.elementOperands[i] = (ElementNode) target; - } - } - } - } - } - - private static void creator(Exp[] exps, Supplier supplier) { - for(Exp exp:exps) { - containerMap.put(exp, supplier); - } - } - - private static class DefaultContainerNode extends AnalysisNode implements Iterable{ - - private final LinkedList containerList = new LinkedList<>(); - - @Override - public Iterator iterator() { - return containerList.iterator(); - } - - @Override - public void match(AnalysisNode analysisNode) { - containerList.add(analysisNode); - } - - @Override - public void match(TerminalSymbol token) { - containerList.add(token); - } - - @Override - public void print(int retractNum, PrintStream out) { } - } - - private static class ExpressionDefaultNode extends ExpressionNode { - - private TerminalSymbol lastToken = null; - - @Override - public void match(AnalysisNode node) throws SyntacticAnalysisException { - if(node instanceof InvokerNode) { - if(isSecondPositionFilled()) { - ExpressionNode forked = this.fork(); - clear(); - expressionOperands[0] = forked; - } - InvokerNode invokerNode = (InvokerNode) node; - if(!invokerNode.paramList.isEmpty() || invokerNode.lambda != null) { - invoker = invokerNode; - } - } else { - node = tryGetSingleElement(node); - if(this.any(0)) { - forkIfSecondPositionFilled(); - setAnalysisNodeAt(node, 1); - - } else { - setAnalysisNodeAt(node, 0); - } - } - } - - @Override - public void match(TerminalSymbol token) throws SyntacticAnalysisException { - if(this.sign == null) { - if (token.type == Type.Sign || - (token.type == Type.Keyword && (token.value.equals("instanceof") || token.value.equals("is")))) { - this.sign = token.value; - this.lastToken = token; - } - } - else if(token.type == Type.Identifier) { - forkIfSecondPositionFilled(); - ElementNode element = createVariableElement(token.value); - setAnalysisNodeAt(element, 1); - } - } - - private void forkIfSecondPositionFilled() { - if(isSecondPositionFilled()) { - ExpressionNode forked = this.fork(); - this.clear(); - this.expressionOperands[0] = forked; - this.sign = lastToken.value; - lastToken = null; - } - } - - private void setAnalysisNodeAt(AnalysisNode analysisNode, int index) { - if(analysisNode instanceof ExpressionNode) { - this.expressionOperands[index] = (ExpressionNode) analysisNode; - } else { - this.elementOperands[index] = (ElementNode) analysisNode; - } - } - } - - private static AnalysisNode tryGetSingleElement(AnalysisNode node) { - if(node instanceof ExpressionNode) { - ExpressionNode expression = (ExpressionNode) node; - clearRedundancy(expression); - if(expression.sign == null && expression.invoker == null && expression.isElement(0)) { - node = expression.getElementAt(0); - } - } - return node; - } - - private static ElementNode createVariableElement(String varName) { - ElementNode element = new ElementNode() { - @Override - public void match(TerminalSymbol token) {} - - @Override - public void match(AnalysisNode analysisNode) {} - }; - element.type = ElementType.Variable; - element.value = varName; - return element; - } -} +package com.taozeyu.taolan.analysis; + +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; +import com.taozeyu.taolan.analysis.Token.Type; +import com.taozeyu.taolan.analysis.node.ArrayNode; +import com.taozeyu.taolan.analysis.node.ChunkNode; +import com.taozeyu.taolan.analysis.node.CommandNode; +import com.taozeyu.taolan.analysis.node.DefineFunctionNode; +import com.taozeyu.taolan.analysis.node.DefineVariableNode; +import com.taozeyu.taolan.analysis.node.ElementNode; +import com.taozeyu.taolan.analysis.node.ElementNode.ElementType; +import com.taozeyu.taolan.analysis.node.OperateNode; +import com.taozeyu.taolan.analysis.node.StartChunkNode; +import com.taozeyu.taolan.analysis.node.WhenNode; +import com.taozeyu.taolan.analysis.node.ExpressionNode; +import com.taozeyu.taolan.analysis.node.ForEachLoopNode; +import com.taozeyu.taolan.analysis.node.IfElseNode; +import com.taozeyu.taolan.analysis.node.InvokerNode; +import com.taozeyu.taolan.analysis.node.LambdaNode; +import com.taozeyu.taolan.analysis.node.LoopChunkNode; +import com.taozeyu.taolan.analysis.node.TryCatchNode; + +class AnalysisDefine { + + private static final HashMap> containerMap = new HashMap<>(); + private static final Supplier containerNodeSupplier = new Supplier() { + @Override + public AnalysisNode get() { + return new DefaultContainerNode(); + } + }; + /** 仅可用于双目运算符 */ + private static final Supplier expressionDefaultNode = new Supplier() { + @Override + public AnalysisNode get() { + return new ExpressionDefaultNode(); + } + }; + private static final Pattern IntegerPattern = Pattern.compile("\\d+"); + + static { + creator(new Exp[] {Exp.Number}, () -> { + return new ElementNode() { + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(Type.Number != token.type) { + return; + } + Matcher matcher = IntegerPattern.matcher(token.value); + if(!matcher.matches()) { + throw new SyntacticAnalysisException(token); + } + if(this.value == null) { + this.type = ElementType.Integer; + this.value = token.value; + + } else { + this.type = ElementType.Number; + this.value += "." + token.value; + } + } + }; + }); + creator(new Exp[] {Exp.Variable}, () -> { + return new ElementNode() { + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(Type.Identifier == token.type) { + this.type = ElementType.Variable; + this.value = token.value; + + } else if(Type.Sign == token.type) { + if("@".equals(token.value)) { + this.fromThis = true; + } else if("@@".equals(token.value)) { + this.fromConstructor = true; + } + } + } + }; + }); + creator(new Exp[] {Exp.String}, () -> { + return new ElementNode() { + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(Type.Identifier == token.type || Type.String == token.type) { + this.type = ElementType.String; + this.value = token.value; + } + } + }; + }); + creator(new Exp[] {Exp.This, Exp.Null}, () -> { + return new ElementNode() { + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if("this".equals(token.value)) { + this.type = ElementType.This; + } else if("null".equals(token.value)) { + this.type = ElementType.Null; + } + } + }; + }); + creator(new Exp[] {Exp.Boolean}, () -> { + return new ElementNode() { + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + this.type = ElementType.Boolean; + this.value = token.value; + } + }; + }); + creator(new Exp[] {Exp.RegEx}, () -> { + return new ElementNode() { + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(Type.RegEx == token.type) { + this.type = ElementType.RegEx; + this.value = token.value; + } + } + }; + }); + creator(new Exp[] {Exp.L11Expression}, () -> { + return new ExpressionNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + analysisNode = tryGetSingleElement(analysisNode); + + if(analysisNode instanceof ExpressionNode) { + this.expressionOperands[0] = (ExpressionNode) analysisNode; + } + else if(analysisNode instanceof ElementNode) { + this.elementOperands[0] = (ElementNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException {} + }; + }); + creator(new Exp[] { + Exp.L10Expression, Exp.L8Expression, + Exp.L7Expression, Exp.L6Expression, + Exp.L5Expression, Exp.L4Expression, + Exp.L3Expression, Exp.L2Expression, + Exp.L0Expression, + + Exp.L10ParamExpression, Exp.L8ParamExpression, + Exp.L7ParamExpression, Exp.L6ParamExpression, + Exp.L5ParamExpression, Exp.L4ParamExpression, + Exp.L3ParamExpression, Exp.L2ParamExpression, + Exp.L0ParamExpression, + + }, expressionDefaultNode); + + creator(new Exp[] {Exp.L9Expression, Exp.L9ParamExpression}, () -> { + return new ExpressionNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + analysisNode = tryGetSingleElement(analysisNode); + if(analysisNode instanceof ExpressionNode) { + this.expressionOperands[0] = (ExpressionNode)analysisNode; + } else { + this.elementOperands[0] = (ElementNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) { + if(token.type == Type.Sign) { + this.sign = token.value; + } + } + }; + }); + creator(new Exp[] {Exp.L1Expression, Exp.L1ParamExpression}, () -> { + return new ExpressionNode() { + + private int hasSetOperands = 0; + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + analysisNode = tryGetSingleElement(analysisNode); + if(analysisNode instanceof ExpressionNode) { + this.expressionOperands[hasSetOperands] = (ExpressionNode)analysisNode; + } else { + this.elementOperands[hasSetOperands] = (ElementNode) analysisNode; + } + hasSetOperands++; + if(hasSetOperands >= 3) { + this.sign = "?:"; + } + } + + @Override + public void match(TerminalSymbol token) {} + }; + }); + creator(new Exp[] {Exp.Chunk}, () -> { + return new ChunkNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + analysisNode = expression; + } + lineList.add(analysisNode); + } + + @Override + public void match(TerminalSymbol token) { } + }; + }); + creator(new Exp[] {Exp.StartChunk}, () -> { + return new StartChunkNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ChunkNode) { + chunk = (ChunkNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) { } + }; + }); + creator(new Exp[] {Exp.Command}, () -> { + return new CommandNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + + if(analysisNode instanceof ExpressionNode) { + expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + + } else if(analysisNode instanceof WhenNode){ + condition = (WhenNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) { + if(token.type == Type.Keyword) { + command = token.value; + } + } + }; + }); + creator(new Exp[] {Exp.Operate}, () -> { + return new OperateNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + + if(analysisNode instanceof ExpressionNode) { + expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + + } else if(analysisNode instanceof WhenNode){ + condition = (WhenNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) { } + }; + }); + creator(new Exp[] {Exp.DefineVariableElement}, () -> { + return new DefineVariableNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + + if(analysisNode instanceof ExpressionNode) { + initValue = (ExpressionNode) analysisNode; + clearRedundancy(initValue); + } + } + + @Override + public void match(TerminalSymbol token) { + if(token.type == Type.Identifier) { + variableName = token.value; + } + } + }; + }); + creator(new Exp[] {Exp.DefineFunction}, () -> { + return new DefineFunctionNode() { + + private boolean nextIdentifyIsFunctionName = false; + private boolean hasHandledFunctionName = false; + + private boolean hasOperator = false; + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + parentExpression = expression; + AnalysisNode target = tryGetSingleElement(expression); + if(target instanceof ElementNode) { + ElementNode element = (ElementNode) target; + if(element.type == ElementType.Variable && !element.fromThis && !element.fromConstructor) { + functionName = element.value; + } + } + + } else if (analysisNode instanceof ChunkNode) { + body = (ChunkNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(token.type == Type.Keyword && "operator".equals(token.value)) { + hasOperator = true; + + } else if(hasOperator && token.type == Type.Sign) { + operator = token.value; + hasOperator = false; + + } else if(token.type == Type.Sign && "->".equals(token.value)) { + nextIdentifyIsFunctionName = true; + + } else if(token.type == Type.Identifier) { + if(!tryToHandleFunctionName(token.value)) { + paramNames.add(token.value); + } + } + } + + @Override + public void finish() throws SyntacticAnalysisException { + tryToHandleFunctionName(functionName); + } + + private boolean tryToHandleFunctionName(String name) throws SyntacticAnalysisException { + boolean success = false; + if(!hasHandledFunctionName) { + success = true; + if(nextIdentifyIsFunctionName) { + functionName = name; + } else { + success = false; + parentExpression = null; + } + if(functionName == null) { + throw new SyntacticAnalysisException(); + } + hasHandledFunctionName = true; + } + return success; + } + }; + }); + creator(new Exp[] {Exp.IfElseChunk}, () -> { + return new IfElseNode() { + + private boolean isNextCondition; + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + addExpression(expression); + } + else if(analysisNode instanceof ChunkNode) { + ChunkNode chunck = (ChunkNode) analysisNode; + if(isNextCondition) { + addChunk(chunck); + } else { + elseChuck = chunck; + } + } + } + + @Override + public void match(TerminalSymbol token) { + if(token.type == Type.Keyword) { + if("if".equals(token.value) || "elsif".equals(token.value)) { + isNextCondition = true; + + } else { + isNextCondition = false; + } + } + } + }; + }); + creator(new Exp[] {Exp.When}, () -> { + return new WhenNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + + if(analysisNode instanceof ExpressionNode) { + condition = (ExpressionNode) analysisNode; + clearRedundancy(condition); + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { } + }; + }); + creator(new Exp[] {Exp.TryCatch}, () -> { + return new TryCatchNode() { + + private String lastKeyword; + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + addErrorType(expression); + } + else if(analysisNode instanceof ChunkNode) { + ChunkNode chunk = (ChunkNode) analysisNode; + if(lastKeyword.equals("try")) { + tryChunk = chunk; + + } else if(lastKeyword.equals("finally")) { + finallyChunk = chunk; + + } else if(lastKeyword.equals("catch")) { + addChunk(chunk); + } + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(token.type == Type.Keyword) { + lastKeyword = token.value; + + } else if(token.type == Type.Identifier) { + addErrorName(token.value); + } + } + }; + }); + creator(new Exp[] {Exp.WhileChunk}, () -> { + return new LoopChunkNode() { + { + isWhile = true; + } + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + condition = (ExpressionNode) analysisNode; + clearRedundancy(condition); + } + else if(analysisNode instanceof ChunkNode) { + chunk = (ChunkNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException {} + }; + }); + creator(new Exp[] {Exp.DoUntilChunk}, () -> { + return new LoopChunkNode() { + { + isWhile = false; + } + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + condition = (ExpressionNode) analysisNode; + clearRedundancy(condition); + } + else if(analysisNode instanceof ChunkNode) { + chunk = (ChunkNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException {} + }; + }); + creator(new Exp[] {Exp.ForEachCommand}, containerNodeSupplier); + creator(new Exp[] {Exp.ForEachChunk}, () -> { + return new ForEachLoopNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof DefaultContainerNode) { + DefaultContainerNode container = (DefaultContainerNode) analysisNode; + List list = new LinkedList<>(); + if(beforeCommandList == null) { + beforeCommandList = list; + } else { + afterCommandList = list; + } + for(Object obj:container) { + if(obj instanceof ExpressionNode) { + list.add((ExpressionNode) obj); + ExpressionNode node = (ExpressionNode) obj; + clearRedundancy(node); + + } else if(obj instanceof DefineVariableNode) { + list.add((DefineVariableNode) obj); + } + } + } + else if(analysisNode instanceof ExpressionNode) { + loopCondition = (ExpressionNode) analysisNode; + clearRedundancy(loopCondition); + } + else if(analysisNode instanceof ChunkNode) { + chunk = (ChunkNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException {} + }; + }); + creator(new Exp[] {Exp.Lambda}, () -> { + return new LambdaNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ChunkNode) { + chunk = (ChunkNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(token.type == Type.Identifier) { + paramNameList.add(token.value); + } + } + }; + }); + creator(new Exp[] { + Exp.Invoker, Exp.InvokerBraceless, + Exp.InvokerBanLambda, Exp.InvokerBracelessBanLambda + }, () -> { + return new InvokerNode() { + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + paramList.add(expression); + + } else if(analysisNode instanceof LambdaNode) { + lambda = (LambdaNode) analysisNode; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException {} + }; + }); + creator(new Exp[] {Exp.Array}, () -> { + return new ElementNode() { + { + array = new ArrayNode(); + type = ElementType.Array; + } + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + array.content.add(expression); + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException {} + }; + }); + creator(new Exp[] {Exp.Container}, () -> { + return new ElementNode() { + { + container = new com.taozeyu.taolan.analysis.node.ContainerNode(); + type = ElementType.Container; + } + private String keyBuffered = null; + + @Override + public void match(AnalysisNode analysisNode) throws SyntacticAnalysisException { + if(analysisNode instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) analysisNode; + clearRedundancy(expression); + container.content.put(keyBuffered, expression); + } + else if(analysisNode instanceof ElementNode) { + keyBuffered = ((ElementNode) analysisNode).value; + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(token.type == Type.Identifier) { + keyBuffered = token.value; + } + } + }; + }); + } + + static AnalysisNode createContainer(Exp exp) { + Supplier supplier = containerMap.get(exp); + AnalysisNode analysisNode = null; + if(supplier != null) { + analysisNode = supplier.get(); + analysisNode.setExp(exp); + } + return analysisNode; + } + + private static void clearRedundancy(ExpressionNode node) { + if(node.sign == null && node.invoker == null && node.isExpression(0) && !node.any(1)) { + ExpressionNode child = node.getExpressionAt(0); + AnalysisNode target = tryGetSingleElement(child); + if(target instanceof ExpressionNode) { + node.copy((ExpressionNode) target); + } else { + node.clear(); + node.elementOperands[0] = (ElementNode) target; + } + + } else { + for(int i=0; i<3; ++i) { + if(node.isExpression(i)) { + ExpressionNode child = node.getExpressionAt(i); + AnalysisNode target = tryGetSingleElement(child); + if(target instanceof ElementNode) { + node.expressionOperands[i] = null; + node.elementOperands[i] = (ElementNode) target; + } + } + } + } + } + + private static void creator(Exp[] exps, Supplier supplier) { + for(Exp exp:exps) { + containerMap.put(exp, supplier); + } + } + + private static class DefaultContainerNode extends AnalysisNode implements Iterable{ + + private final LinkedList containerList = new LinkedList<>(); + + @Override + public Iterator iterator() { + return containerList.iterator(); + } + + @Override + public void match(AnalysisNode analysisNode) { + containerList.add(analysisNode); + } + + @Override + public void match(TerminalSymbol token) { + containerList.add(token); + } + + @Override + public void print(int retractNum, PrintStream out) { } + } + + private static class ExpressionDefaultNode extends ExpressionNode { + + private TerminalSymbol lastToken = null; + + @Override + public void match(AnalysisNode node) throws SyntacticAnalysisException { + if(node instanceof InvokerNode) { + if(isSecondPositionFilled()) { + ExpressionNode forked = this.fork(); + clear(); + expressionOperands[0] = forked; + } + InvokerNode invokerNode = (InvokerNode) node; + if(!invokerNode.paramList.isEmpty() || invokerNode.lambda != null) { + invoker = invokerNode; + } + } else { + node = tryGetSingleElement(node); + if(this.any(0)) { + forkIfSecondPositionFilled(); + setAnalysisNodeAt(node, 1); + + } else { + setAnalysisNodeAt(node, 0); + } + } + } + + @Override + public void match(TerminalSymbol token) throws SyntacticAnalysisException { + if(this.sign == null) { + if (token.type == Type.Sign || + (token.type == Type.Keyword && (token.value.equals("instanceof") || token.value.equals("is")))) { + this.sign = token.value; + this.lastToken = token; + } + } + else if(token.type == Type.Identifier) { + forkIfSecondPositionFilled(); + ElementNode element = createVariableElement(token.value); + setAnalysisNodeAt(element, 1); + } + } + + private void forkIfSecondPositionFilled() { + if(isSecondPositionFilled()) { + ExpressionNode forked = this.fork(); + this.clear(); + this.expressionOperands[0] = forked; + this.sign = lastToken.value; + lastToken = null; + } + } + + private void setAnalysisNodeAt(AnalysisNode analysisNode, int index) { + if(analysisNode instanceof ExpressionNode) { + this.expressionOperands[index] = (ExpressionNode) analysisNode; + } else { + this.elementOperands[index] = (ElementNode) analysisNode; + } + } + } + + private static AnalysisNode tryGetSingleElement(AnalysisNode node) { + if(node instanceof ExpressionNode) { + ExpressionNode expression = (ExpressionNode) node; + clearRedundancy(expression); + if(expression.sign == null && expression.invoker == null && expression.isElement(0)) { + node = expression.getElementAt(0); + } + } + return node; + } + + private static ElementNode createVariableElement(String varName) { + ElementNode element = new ElementNode() { + @Override + public void match(TerminalSymbol token) {} + + @Override + public void match(AnalysisNode analysisNode) {} + }; + element.type = ElementType.Variable; + element.value = varName; + return element; + } +} diff --git a/src/com/taozeyu/taolan/analysis/AnalysisNode.java b/src/main/java/com/taozeyu/taolan/analysis/AnalysisNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/AnalysisNode.java rename to src/main/java/com/taozeyu/taolan/analysis/AnalysisNode.java index 7cb7447..0e31040 --- a/src/com/taozeyu/taolan/analysis/AnalysisNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/AnalysisNode.java @@ -1,48 +1,48 @@ -package com.taozeyu.taolan.analysis; - -import java.io.PrintStream; -import java.util.Iterator; - -import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; - -public abstract class AnalysisNode { - - private Exp exp = null; - - public abstract void match(AnalysisNode analysisNode) throws SyntacticAnalysisException; - - public abstract void match(TerminalSymbol token) throws SyntacticAnalysisException; - - public abstract void print(int retractNum, PrintStream out); - - public void finish() throws SyntacticAnalysisException {} - - public void printRetract(int retractNum, PrintStream out) { - for(int i=0; i container) { - Iterator it = container.iterator(); - while(it.hasNext()) { - Object target = it.next(); - if(target instanceof AnalysisNode) { - ((AnalysisNode) target).print(retractNum, out); - } else { - out.print(target); - } - if(it.hasNext()) { - out.print(", "); - } - } - } - - Exp getExp() { - return exp; - } - - void setExp(Exp exp) { - this.exp = exp; - } -} +package com.taozeyu.taolan.analysis; + +import java.io.PrintStream; +import java.util.Iterator; + +import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; + +public abstract class AnalysisNode { + + private Exp exp = null; + + public abstract void match(AnalysisNode analysisNode) throws SyntacticAnalysisException; + + public abstract void match(TerminalSymbol token) throws SyntacticAnalysisException; + + public abstract void print(int retractNum, PrintStream out); + + public void finish() throws SyntacticAnalysisException {} + + public void printRetract(int retractNum, PrintStream out) { + for(int i=0; i container) { + Iterator it = container.iterator(); + while(it.hasNext()) { + Object target = it.next(); + if(target instanceof AnalysisNode) { + ((AnalysisNode) target).print(retractNum, out); + } else { + out.print(target); + } + if(it.hasNext()) { + out.print(", "); + } + } + } + + Exp getExp() { + return exp; + } + + void setExp(Exp exp) { + this.exp = exp; + } +} diff --git a/src/com/taozeyu/taolan/analysis/FirstSetConstructor.java b/src/main/java/com/taozeyu/taolan/analysis/FirstSetConstructor.java old mode 100755 new mode 100644 similarity index 97% rename from src/com/taozeyu/taolan/analysis/FirstSetConstructor.java rename to src/main/java/com/taozeyu/taolan/analysis/FirstSetConstructor.java index 9849498..51cad77 --- a/src/com/taozeyu/taolan/analysis/FirstSetConstructor.java +++ b/src/main/java/com/taozeyu/taolan/analysis/FirstSetConstructor.java @@ -1,205 +1,205 @@ -package com.taozeyu.taolan.analysis; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; - -import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; - -class FirstSetConstructor { - - private final HashMap expContainer; - - private LinkedHashSet visitedExpSet = null; - private HashSet hasBuildExpSet = null; - - FirstSetConstructor(HashMap expContainer) { - this.expContainer = expContainer; - } - - void build() { - visitedExpSet = new LinkedHashSet<>(); - hasBuildExpSet = new HashSet<>(); - for(NonTerminalSymbol node:searchAllNonTerminalSymbols()) { - buildFirstSetIfNeed(node); - } - } - - private HashSet searchAllNonTerminalSymbols() { - HashSet container = new HashSet<>(); - for(NonTerminalSymbol node:expContainer.values()) { - searchNonTerminalSymbols(container, node); - } - return container; - } - - private void searchNonTerminalSymbols(HashSet container, NonTerminalSymbol node) { - boolean notAdded = container.add(node); - if(notAdded) { - for(Object[] expansion:node.expansionList) { - for(Object obj:expansion) { - if(obj instanceof NonTerminalSymbol) { - NonTerminalSymbol childNode = (NonTerminalSymbol) obj; - searchNonTerminalSymbols(container, childNode); - } - } - } - } - } - - private void buildFirstSetIfNeed(NonTerminalSymbol node) { - boolean success = visitedExpSet.add(node); - if(!success) { - printLeftRecursiveErrorMessage(node); - throw new RuntimeException("left recursive"); - } - boolean needHandle = hasBuildExpSet.add(node); - if(needHandle) { - buildFirstSetHandle(node); - } - visitedExpSet.remove(node); - } - - private void printLeftRecursiveErrorMessage(NonTerminalSymbol node) { - System.err.println("non-terminal symbol " + node.exp + " has left recursive."); - for(NonTerminalSymbol childNode:visitedExpSet) { - System.err.println(" --> " + childNode.exp); - } - } - - private void buildFirstSetHandle(NonTerminalSymbol node) { - collectAllFirstSetTokens(node); - removeBannedFirstSetTokens(node); - checkAmbiguity(node); - handleSigns(node); - } - - private void collectAllFirstSetTokens(NonTerminalSymbol node) { - for(Object[] expansion:node.expansionList) { - HashSet firstSet = getExpansionFirstSet(expansion); - node.firstSetList.add(firstSet); - node.firstSet.addAll(firstSet); - } - } - - private void removeBannedFirstSetTokens(NonTerminalSymbol node) { - for(TerminalSymbol banToken:node.banList) { - node.firstSet.remove(banToken); - } - } - - private HashSet getExpansionFirstSet(Object[] expansion) { - HashSet firstSet = new HashSet<>(); - boolean thisExpansionCanBeEmpty = true; - for(Object obj:expansion) { - NonTerminalSymbol node = tryGetNonTerminalSymbol(obj); - boolean willContinue = false; - if(node != null) { - buildFirstSetIfNeed(node); - // 非终结符的 first set 包含空,说明该非终结符可以展开为空。 - if(node.firstSet.contains(TerminalSymbol.Empty)) { - willContinue = true; - } else { - thisExpansionCanBeEmpty = false; - } - for(TerminalSymbol token:node.firstSet) { - if(!token.isEmpty()) { - firstSet.add(token); - } - } - } else { - TerminalSymbol token = (TerminalSymbol) obj; - firstSet.add(token); - thisExpansionCanBeEmpty = false; - } - if(!willContinue) { - break; - } - } - if(thisExpansionCanBeEmpty) { - // 说明该展开式不包含任何终结符,并且其每一个非终结符都可以展开为空。 - firstSet.add(TerminalSymbol.Empty); - } - return firstSet; - } - - private NonTerminalSymbol tryGetNonTerminalSymbol(Object obj) { - NonTerminalSymbol node = null; - if(obj instanceof NonTerminalSymbol) { - node = (NonTerminalSymbol) obj; - - } else if(obj instanceof Exp){ - Exp exp = (Exp) obj; - node = expContainer.get(exp); - } - return node; - } - - private void checkAmbiguity(NonTerminalSymbol node) { - HashSet union = new HashSet<>(); - boolean foundAnyConflicts = false; - for(HashSet firstSet:node.firstSetList) { - for(TerminalSymbol token:firstSet) { - if(!token.isEmpty() && !union.add(token)) { - foundAnyConflicts = true; - break; - } - } - } - if(foundAnyConflicts) { - printAmbiguityMessage(node); - throw new RuntimeException("ambiguity"); - } - } - - private void printAmbiguityMessage(NonTerminalSymbol node) { - Object info = node.exp; - if(info == null) { - Exp exp = getTopExpFromVisitedSet(); - info = "" + exp + "'s node"; - } - System.err.println("non-terminal symbol " + info + " has " + node.expansionList.size() + " expansions"); - for(int i=0; i firstSet:node.firstSetList) { - // Empty 终结符是一个临时符号,仅仅存在于 first set constructor 的 build 阶段。 - // 这行代码既检测了空符的存在,又删除了 expansionList 空符。 - canBeEmpty |= firstSet.remove(TerminalSymbol.Empty); - } - - if(canBeEmpty) { - if(node.sign == null) { - node.sign = '?'; - } else if(node.sign == '+') { - node.sign = '*'; - } - } - if(node.sign != null && (node.sign == '?' || node.sign == '*')) { - node.firstSet.add(TerminalSymbol.Empty); - } - } -} +package com.taozeyu.taolan.analysis; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; + +import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; + +class FirstSetConstructor { + + private final HashMap expContainer; + + private LinkedHashSet visitedExpSet = null; + private HashSet hasBuildExpSet = null; + + FirstSetConstructor(HashMap expContainer) { + this.expContainer = expContainer; + } + + void build() { + visitedExpSet = new LinkedHashSet<>(); + hasBuildExpSet = new HashSet<>(); + for(NonTerminalSymbol node:searchAllNonTerminalSymbols()) { + buildFirstSetIfNeed(node); + } + } + + private HashSet searchAllNonTerminalSymbols() { + HashSet container = new HashSet<>(); + for(NonTerminalSymbol node:expContainer.values()) { + searchNonTerminalSymbols(container, node); + } + return container; + } + + private void searchNonTerminalSymbols(HashSet container, NonTerminalSymbol node) { + boolean notAdded = container.add(node); + if(notAdded) { + for(Object[] expansion:node.expansionList) { + for(Object obj:expansion) { + if(obj instanceof NonTerminalSymbol) { + NonTerminalSymbol childNode = (NonTerminalSymbol) obj; + searchNonTerminalSymbols(container, childNode); + } + } + } + } + } + + private void buildFirstSetIfNeed(NonTerminalSymbol node) { + boolean success = visitedExpSet.add(node); + if(!success) { + printLeftRecursiveErrorMessage(node); + throw new RuntimeException("left recursive"); + } + boolean needHandle = hasBuildExpSet.add(node); + if(needHandle) { + buildFirstSetHandle(node); + } + visitedExpSet.remove(node); + } + + private void printLeftRecursiveErrorMessage(NonTerminalSymbol node) { + System.err.println("non-terminal symbol " + node.exp + " has left recursive."); + for(NonTerminalSymbol childNode:visitedExpSet) { + System.err.println(" --> " + childNode.exp); + } + } + + private void buildFirstSetHandle(NonTerminalSymbol node) { + collectAllFirstSetTokens(node); + removeBannedFirstSetTokens(node); + checkAmbiguity(node); + handleSigns(node); + } + + private void collectAllFirstSetTokens(NonTerminalSymbol node) { + for(Object[] expansion:node.expansionList) { + HashSet firstSet = getExpansionFirstSet(expansion); + node.firstSetList.add(firstSet); + node.firstSet.addAll(firstSet); + } + } + + private void removeBannedFirstSetTokens(NonTerminalSymbol node) { + for(TerminalSymbol banToken:node.banList) { + node.firstSet.remove(banToken); + } + } + + private HashSet getExpansionFirstSet(Object[] expansion) { + HashSet firstSet = new HashSet<>(); + boolean thisExpansionCanBeEmpty = true; + for(Object obj:expansion) { + NonTerminalSymbol node = tryGetNonTerminalSymbol(obj); + boolean willContinue = false; + if(node != null) { + buildFirstSetIfNeed(node); + // 非终结符的 first set 包含空,说明该非终结符可以展开为空。 + if(node.firstSet.contains(TerminalSymbol.Empty)) { + willContinue = true; + } else { + thisExpansionCanBeEmpty = false; + } + for(TerminalSymbol token:node.firstSet) { + if(!token.isEmpty()) { + firstSet.add(token); + } + } + } else { + TerminalSymbol token = (TerminalSymbol) obj; + firstSet.add(token); + thisExpansionCanBeEmpty = false; + } + if(!willContinue) { + break; + } + } + if(thisExpansionCanBeEmpty) { + // 说明该展开式不包含任何终结符,并且其每一个非终结符都可以展开为空。 + firstSet.add(TerminalSymbol.Empty); + } + return firstSet; + } + + private NonTerminalSymbol tryGetNonTerminalSymbol(Object obj) { + NonTerminalSymbol node = null; + if(obj instanceof NonTerminalSymbol) { + node = (NonTerminalSymbol) obj; + + } else if(obj instanceof Exp){ + Exp exp = (Exp) obj; + node = expContainer.get(exp); + } + return node; + } + + private void checkAmbiguity(NonTerminalSymbol node) { + HashSet union = new HashSet<>(); + boolean foundAnyConflicts = false; + for(HashSet firstSet:node.firstSetList) { + for(TerminalSymbol token:firstSet) { + if(!token.isEmpty() && !union.add(token)) { + foundAnyConflicts = true; + break; + } + } + } + if(foundAnyConflicts) { + printAmbiguityMessage(node); + throw new RuntimeException("ambiguity"); + } + } + + private void printAmbiguityMessage(NonTerminalSymbol node) { + Object info = node.exp; + if(info == null) { + Exp exp = getTopExpFromVisitedSet(); + info = "" + exp + "'s node"; + } + System.err.println("non-terminal symbol " + info + " has " + node.expansionList.size() + " expansions"); + for(int i=0; i firstSet:node.firstSetList) { + // Empty 终结符是一个临时符号,仅仅存在于 first set constructor 的 build 阶段。 + // 这行代码既检测了空符的存在,又删除了 expansionList 空符。 + canBeEmpty |= firstSet.remove(TerminalSymbol.Empty); + } + + if(canBeEmpty) { + if(node.sign == null) { + node.sign = '?'; + } else if(node.sign == '+') { + node.sign = '*'; + } + } + if(node.sign != null && (node.sign == '?' || node.sign == '*')) { + node.firstSet.add(TerminalSymbol.Empty); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/LexicalAnalysis.java b/src/main/java/com/taozeyu/taolan/analysis/LexicalAnalysis.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/LexicalAnalysis.java rename to src/main/java/com/taozeyu/taolan/analysis/LexicalAnalysis.java index 1678d2d..2f1c1f0 --- a/src/com/taozeyu/taolan/analysis/LexicalAnalysis.java +++ b/src/main/java/com/taozeyu/taolan/analysis/LexicalAnalysis.java @@ -1,253 +1,253 @@ -package com.taozeyu.taolan.analysis; - -import java.io.IOException; -import java.io.Reader; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - -import com.taozeyu.taolan.analysis.Token.Type; - -public class LexicalAnalysis { - - private static enum State { - Normal, Identifier, Sign, Annotation, String, RegEx, Space; - } - - private static final char[] FilterChar = new char[] { - '\b', '\f', '\r' - }; - private static final char[] IdentifierSign = new char[] {'_'}; - private static final char[] IdentifierRearSign = new char[] {'?', '!'}; - - private static final char[] Space = new char[] {' ', '\t'}; - - private static final HashMap StringTMMap = new HashMap<>(); - - static { - StringTMMap.put('\"', '\"'); - StringTMMap.put('\'', '\''); - StringTMMap.put('\\', '\\'); - StringTMMap.put('b', '\b'); - StringTMMap.put('f', '\f'); - StringTMMap.put('t', '\t'); - StringTMMap.put('r', '\r'); - StringTMMap.put('n', '\n'); - } - - private final Reader reader; - - private Token endToken = null; - private final LinkedList tokenBuffer = new LinkedList<>(); - - private State state; - private StringBuilder readBuffer = null; - private boolean transferredMeaningSign = false; - - public LexicalAnalysis(Reader reader) { - this.reader = reader; - this.state = State.Normal; - } - - Token read() throws IOException, LexicalAnalysisException { - - if(endToken != null) { - return endToken; - } - while(tokenBuffer.isEmpty()) { - int read = reader.read(); - char c = (read == -1 ? '\0' : (char) read); - while(!readChar(c)) {} - } - Token token = tokenBuffer.removeLast(); - if(token.type == Type.EndSymbol) { - endToken = token; - } - return token; - } - - private void refreshBuffer(char c) { - readBuffer = new StringBuilder(); - readBuffer.append(c); - } - - private void createToken(Type type) { - Token token = new Token(type, readBuffer.toString()); - tokenBuffer.addFirst(token); - readBuffer = null; - } - - private void createToken(Type type, String value) { - Token token = new Token(type, value); - tokenBuffer.addFirst(token); - readBuffer = null; - } - - private boolean readChar(char c) throws LexicalAnalysisException { - - boolean moveCursor = true; - Type createType = null; - - if(!include(FilterChar, c)) { - - if(state == State.Normal) { - - if(inIdentifierSetButNotRear(c)) { - state = State.Identifier; - } - else if(SignParser.inCharSet(c)) { - state = State.Sign; - } - else if(c == '#') { - state = State.Annotation; - } - else if(c == '\"' | c == '\'') { - state = State.String; - transferredMeaningSign = false; - } - else if(c == '`') { - state = State.RegEx; - transferredMeaningSign = false; - } - else if(include(Space, c)) { - state = State.Space; - } - else if(c == '\n') { - createType = Type.NewLine; - } - else if(c == '\0') { - createType = Type.EndSymbol; - } - else { - throw new LexicalAnalysisException(c); - } - refreshBuffer(c); - - } else if(state == State.Identifier) { - - if(inIdentifierSetButNotRear(c)) { - readBuffer.append(c); - - } else if(include(IdentifierRearSign, c)) { - createType = Type.Identifier; - readBuffer.append(c); - state = State.Normal; - - } else { - createType = Type.Identifier; - state = State.Normal; - moveCursor = false; - } - - } else if(state == State.Sign) { - - if(SignParser.inCharSet(c)) { - readBuffer.append(c); - - } else { - List list = SignParser.parse(readBuffer.toString()); - for(String signStr:list) { - createToken(Type.Sign, signStr); - } - createType = null; - state = State.Normal; - moveCursor = false; - } - - } else if(state == State.Annotation) { - - if(c != '\n' & c != '\0') { - readBuffer.append(c); - - } else { - createType = Type.Annotation; - state = State.Normal; - moveCursor = false; - - } - } else if(state == State.String) { - - if(c == '\n') { - throw new LexicalAnalysisException(c); - - } else if(c == '\0') { - throw new LexicalAnalysisException(c); - - } else if(transferredMeaningSign) { - - Character tms = StringTMMap.get(c); - if(tms == null) { - throw new LexicalAnalysisException(c); - } - readBuffer.append(tms); - transferredMeaningSign = false; - - } else if(c == '\\') { - transferredMeaningSign = true; - - } else { - readBuffer.append(c); - char firstChar = readBuffer.charAt(0); - if(firstChar == c) { - createType = Type.String; - state = State.Normal; - } - } - } else if(state == State.RegEx) { - - if(transferredMeaningSign) { - - if(c != '`') { - throw new LexicalAnalysisException(c); - } - readBuffer.append(c); - transferredMeaningSign = false; - - } else if(c =='\\') { - transferredMeaningSign = true; - - } else if(c == '\0') { - throw new LexicalAnalysisException(c); - - } else if(c == '`') { - readBuffer.append(c); - createType = Type.RegEx; - state = State.Normal; - - } else { - readBuffer.append(c); - } - - } else if(state == State.Space) { - - if(include(Space, c)) { - readBuffer.append(c); - - } else { - createType = Type.Space; - state = State.Normal; - moveCursor = false; - } - } - } - if(createType != null) { - createToken(createType); - } - return moveCursor; - } - - private boolean inIdentifierSetButNotRear(char c) { - return (c >= 'a' & c <= 'z' ) | (c >='A' & c <= 'Z') | (c >= '0' & c <= '9')|| include(IdentifierSign, c); - } - - private boolean include(char[] range, char c) { - boolean include = false; - for(int i=0; i StringTMMap = new HashMap<>(); + + static { + StringTMMap.put('\"', '\"'); + StringTMMap.put('\'', '\''); + StringTMMap.put('\\', '\\'); + StringTMMap.put('b', '\b'); + StringTMMap.put('f', '\f'); + StringTMMap.put('t', '\t'); + StringTMMap.put('r', '\r'); + StringTMMap.put('n', '\n'); + } + + private final Reader reader; + + private Token endToken = null; + private final LinkedList tokenBuffer = new LinkedList<>(); + + private State state; + private StringBuilder readBuffer = null; + private boolean transferredMeaningSign = false; + + public LexicalAnalysis(Reader reader) { + this.reader = reader; + this.state = State.Normal; + } + + Token read() throws IOException, LexicalAnalysisException { + + if(endToken != null) { + return endToken; + } + while(tokenBuffer.isEmpty()) { + int read = reader.read(); + char c = (read == -1 ? '\0' : (char) read); + while(!readChar(c)) {} + } + Token token = tokenBuffer.removeLast(); + if(token.type == Type.EndSymbol) { + endToken = token; + } + return token; + } + + private void refreshBuffer(char c) { + readBuffer = new StringBuilder(); + readBuffer.append(c); + } + + private void createToken(Type type) { + Token token = new Token(type, readBuffer.toString()); + tokenBuffer.addFirst(token); + readBuffer = null; + } + + private void createToken(Type type, String value) { + Token token = new Token(type, value); + tokenBuffer.addFirst(token); + readBuffer = null; + } + + private boolean readChar(char c) throws LexicalAnalysisException { + + boolean moveCursor = true; + Type createType = null; + + if(!include(FilterChar, c)) { + + if(state == State.Normal) { + + if(inIdentifierSetButNotRear(c)) { + state = State.Identifier; + } + else if(SignParser.inCharSet(c)) { + state = State.Sign; + } + else if(c == '#') { + state = State.Annotation; + } + else if(c == '\"' | c == '\'') { + state = State.String; + transferredMeaningSign = false; + } + else if(c == '`') { + state = State.RegEx; + transferredMeaningSign = false; + } + else if(include(Space, c)) { + state = State.Space; + } + else if(c == '\n') { + createType = Type.NewLine; + } + else if(c == '\0') { + createType = Type.EndSymbol; + } + else { + throw new LexicalAnalysisException(c); + } + refreshBuffer(c); + + } else if(state == State.Identifier) { + + if(inIdentifierSetButNotRear(c)) { + readBuffer.append(c); + + } else if(include(IdentifierRearSign, c)) { + createType = Type.Identifier; + readBuffer.append(c); + state = State.Normal; + + } else { + createType = Type.Identifier; + state = State.Normal; + moveCursor = false; + } + + } else if(state == State.Sign) { + + if(SignParser.inCharSet(c)) { + readBuffer.append(c); + + } else { + List list = SignParser.parse(readBuffer.toString()); + for(String signStr:list) { + createToken(Type.Sign, signStr); + } + createType = null; + state = State.Normal; + moveCursor = false; + } + + } else if(state == State.Annotation) { + + if(c != '\n' & c != '\0') { + readBuffer.append(c); + + } else { + createType = Type.Annotation; + state = State.Normal; + moveCursor = false; + + } + } else if(state == State.String) { + + if(c == '\n') { + throw new LexicalAnalysisException(c); + + } else if(c == '\0') { + throw new LexicalAnalysisException(c); + + } else if(transferredMeaningSign) { + + Character tms = StringTMMap.get(c); + if(tms == null) { + throw new LexicalAnalysisException(c); + } + readBuffer.append(tms); + transferredMeaningSign = false; + + } else if(c == '\\') { + transferredMeaningSign = true; + + } else { + readBuffer.append(c); + char firstChar = readBuffer.charAt(0); + if(firstChar == c) { + createType = Type.String; + state = State.Normal; + } + } + } else if(state == State.RegEx) { + + if(transferredMeaningSign) { + + if(c != '`') { + throw new LexicalAnalysisException(c); + } + readBuffer.append(c); + transferredMeaningSign = false; + + } else if(c =='\\') { + transferredMeaningSign = true; + + } else if(c == '\0') { + throw new LexicalAnalysisException(c); + + } else if(c == '`') { + readBuffer.append(c); + createType = Type.RegEx; + state = State.Normal; + + } else { + readBuffer.append(c); + } + + } else if(state == State.Space) { + + if(include(Space, c)) { + readBuffer.append(c); + + } else { + createType = Type.Space; + state = State.Normal; + moveCursor = false; + } + } + } + if(createType != null) { + createToken(createType); + } + return moveCursor; + } + + private boolean inIdentifierSetButNotRear(char c) { + return (c >= 'a' & c <= 'z' ) | (c >='A' & c <= 'Z') | (c >= '0' & c <= '9')|| include(IdentifierSign, c); + } + + private boolean include(char[] range, char c) { + boolean include = false; + for(int i=0; i expansionList = new ArrayList<>(); - final ArrayList banList = new ArrayList<>(); - - final ArrayList> firstSetList = new ArrayList<>(); - final HashSet firstSet = new HashSet<>(); - - NonTerminalSymbol(Exp exp) { - this.exp = exp; - } - - NonTerminalSymbol ban(TerminalSymbol...args) { - for(TerminalSymbol node:args) { - banList.add(node); - } - return this; - } - - NonTerminalSymbol or(Object...args) { - expansionList.add(args); - return this; - } - - NonTerminalSymbol sign(char sign) { - this.sign = sign; - return this; - } - - @Override - public String toString() { - String str; - if (exp != null) { - str = String.valueOf(exp); - } else { - LinkedList expansionStr = new LinkedList<>(); - for (Object[] expansion :expansionList) { - LinkedList signsStr = new LinkedList<>(); - for (Object obj:expansion) { - signsStr.add(obj.toString()); - } - expansionStr.add(String.join(" ", signsStr)); - } - str = "["+ String.join(" | ", expansionStr) +"]"; - } - if(sign != null) { - str += "(" + sign + ")"; - } - return str; - } -} +package com.taozeyu.taolan.analysis; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +class NonTerminalSymbol { + + static enum Exp { + + //空白 + SplitSpaceSign, SpaceOrEnter, Space, + + //基本单元 + Enter, This, Null, Boolean, + Number, Variable, String, RegEx, + Element, + + //表达式相关 + L0Expression, L0ParamExpression, L0Sign, + L1Expression, L1ParamExpression, + L2Expression, L2ParamExpression, L2Sign, + L3Expression, L3ParamExpression, L3Sign, + L4Expression, L4ParamExpression, L4Sign, + L5Expression, L5ParamExpression, L5Sign, + L6Expression, L6ParamExpression, L6Sign, + L7Expression, L7ParamExpression, L7Sign, + L8Expression, L8ParamExpression, L8Sign, + L9Expression, L9ParamExpression, L9Sign, + L10Expression, L10ParamExpression, L10Tail, L10TailOperation, + L11Expression, + + //控制流语法 + Chunk, StartChunk, Line, + Command, Operate, When, + + DefineVariable, DefineVariableElement, + DefineFunction, ParamsList, + IfElseChunk, TryCatch, + WhileChunk, DoUntilChunk, + ForEachChunk, ForEachCommand, ForEachCondition, + + //语法糖 + Lambda, + List, Map, MapEntry, + Invoker, InvokerBraceless, InvokerBanLambda, InvokerBracelessBanLambda, + ParamList, ParamListBanTokens , + Array, Container, + } + + final Exp exp; + Character sign = null; + + final ArrayList expansionList = new ArrayList<>(); + final ArrayList banList = new ArrayList<>(); + + final ArrayList> firstSetList = new ArrayList<>(); + final HashSet firstSet = new HashSet<>(); + + NonTerminalSymbol(Exp exp) { + this.exp = exp; + } + + NonTerminalSymbol ban(TerminalSymbol...args) { + for(TerminalSymbol node:args) { + banList.add(node); + } + return this; + } + + NonTerminalSymbol or(Object...args) { + expansionList.add(args); + return this; + } + + NonTerminalSymbol sign(char sign) { + this.sign = sign; + return this; + } + + @Override + public String toString() { + String str; + if (exp != null) { + str = String.valueOf(exp); + } else { + LinkedList expansionStr = new LinkedList<>(); + for (Object[] expansion :expansionList) { + LinkedList signsStr = new LinkedList<>(); + for (Object obj:expansion) { + signsStr.add(obj.toString()); + } + expansionStr.add(String.join(" ", signsStr)); + } + str = "["+ String.join(" | ", expansionStr) +"]"; + } + if(sign != null) { + str += "(" + sign + ")"; + } + return str; + } +} diff --git a/src/com/taozeyu/taolan/analysis/SignParser.java b/src/main/java/com/taozeyu/taolan/analysis/SignParser.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/SignParser.java rename to src/main/java/com/taozeyu/taolan/analysis/SignParser.java index 826fb85..ecb4308 --- a/src/com/taozeyu/taolan/analysis/SignParser.java +++ b/src/main/java/com/taozeyu/taolan/analysis/SignParser.java @@ -1,93 +1,93 @@ -package com.taozeyu.taolan.analysis; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -class SignParser { - - private final static List> signSetList; - private final static HashSet signCharSet; - private final static int MaxLength, MinLength; - - static { - String[] signArray = new String[] { - "+", "-", "*", "/", "%", - ">", "<", ">=", "<=", "=", "!=", "==", "=~", - "+=", "-=", "*=", "/=", "%=", - "&&", "||", "!", "^", - "&&=", "||=", "^=", - "<<", ">>", "->", "<-", - "?", ":", - ".", ",", ";", "..", - "(", ")", "[", "]", "{", "}", "|", - "@", "@@", "$", - }; - - int maxLength = Integer.MIN_VALUE, - minLength = Integer.MAX_VALUE; - - signCharSet = new HashSet<>(); - for(String sign:signArray) { - int length = sign.length(); - if(length > maxLength) { - maxLength = length; - } - if(length < minLength) { - minLength = length; - } - for(int i=0; i(maxLength - minLength); - for(int i=0; i< maxLength - minLength + 1; ++i) { - signSetList.add(new HashSet<>()); - } - for(String sign:signArray) { - int length = sign.length(); - HashSet signSet = signSetList.get(length - minLength); - signSet.add(sign); - } - MaxLength = maxLength; - MinLength = minLength; - } - - static boolean inCharSet(char c) { - return signCharSet.contains(c); - } - - static List parse(String str) throws LexicalAnalysisException { - LinkedList rsContainer = new LinkedList<>(); - int startIndex = 0; - while(startIndex < str.length()) { - String matchStr = match(startIndex, str); - if(matchStr == null) { - throw new LexicalAnalysisException(str.substring(startIndex)); - } else { - rsContainer.add(matchStr); - startIndex += matchStr.length(); - } - } - return rsContainer; - } - - private static String match(int startIndex, String str) { - String matchStr = null; - int length = str.length() - startIndex; - length = Math.min(length, MaxLength); - if(length >= MinLength) { - for(int i=length - MinLength; i>=0; i--) { - int matchLength = i + MinLength; - HashSet signSet = signSetList.get(i); - matchStr = str.substring(startIndex, startIndex + matchLength); - if(signSet.contains(matchStr)) { - break; - } - matchStr = null; - } - } - return matchStr; - } -} +package com.taozeyu.taolan.analysis; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +class SignParser { + + private final static List> signSetList; + private final static HashSet signCharSet; + private final static int MaxLength, MinLength; + + static { + String[] signArray = new String[] { + "+", "-", "*", "/", "%", + ">", "<", ">=", "<=", "=", "!=", "==", "=~", + "+=", "-=", "*=", "/=", "%=", + "&&", "||", "!", "^", + "&&=", "||=", "^=", + "<<", ">>", "->", "<-", + "?", ":", + ".", ",", ";", "..", + "(", ")", "[", "]", "{", "}", "|", + "@", "@@", "$", + }; + + int maxLength = Integer.MIN_VALUE, + minLength = Integer.MAX_VALUE; + + signCharSet = new HashSet<>(); + for(String sign:signArray) { + int length = sign.length(); + if(length > maxLength) { + maxLength = length; + } + if(length < minLength) { + minLength = length; + } + for(int i=0; i(maxLength - minLength); + for(int i=0; i< maxLength - minLength + 1; ++i) { + signSetList.add(new HashSet<>()); + } + for(String sign:signArray) { + int length = sign.length(); + HashSet signSet = signSetList.get(length - minLength); + signSet.add(sign); + } + MaxLength = maxLength; + MinLength = minLength; + } + + static boolean inCharSet(char c) { + return signCharSet.contains(c); + } + + static List parse(String str) throws LexicalAnalysisException { + LinkedList rsContainer = new LinkedList<>(); + int startIndex = 0; + while(startIndex < str.length()) { + String matchStr = match(startIndex, str); + if(matchStr == null) { + throw new LexicalAnalysisException(str.substring(startIndex)); + } else { + rsContainer.add(matchStr); + startIndex += matchStr.length(); + } + } + return rsContainer; + } + + private static String match(int startIndex, String str) { + String matchStr = null; + int length = str.length() - startIndex; + length = Math.min(length, MaxLength); + if(length >= MinLength) { + for(int i=length - MinLength; i>=0; i--) { + int matchLength = i + MinLength; + HashSet signSet = signSetList.get(i); + matchStr = str.substring(startIndex, startIndex + matchLength); + if(signSet.contains(matchStr)) { + break; + } + matchStr = null; + } + } + return matchStr; + } +} diff --git a/src/com/taozeyu/taolan/analysis/SyntacticAnalysis.java b/src/main/java/com/taozeyu/taolan/analysis/SyntacticAnalysis.java old mode 100755 new mode 100644 similarity index 97% rename from src/com/taozeyu/taolan/analysis/SyntacticAnalysis.java rename to src/main/java/com/taozeyu/taolan/analysis/SyntacticAnalysis.java index c80dc7a..d299f12 --- a/src/com/taozeyu/taolan/analysis/SyntacticAnalysis.java +++ b/src/main/java/com/taozeyu/taolan/analysis/SyntacticAnalysis.java @@ -1,188 +1,188 @@ -package com.taozeyu.taolan.analysis; - -import java.io.IOException; -import java.util.HashSet; - -import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; -import com.taozeyu.taolan.analysis.Token.Type; -import com.taozeyu.taolan.analysis.node.ChunkNode; -import com.taozeyu.taolan.analysis.node.StartChunkNode; - - -public class SyntacticAnalysis { - - private final LexicalAnalysis lexicalAnalysis; - - public SyntacticAnalysis(LexicalAnalysis lexicalAnalysis) { - this.lexicalAnalysis = lexicalAnalysis; - } - - TerminalSymbol readBuffered = null; - TerminalSymbol lastRead = null; - - private TerminalSymbol read() throws IOException, LexicalAnalysisException { - TerminalSymbol symbol; - if(readBuffered == null) { - Token token; - do { - token = lexicalAnalysis.read(); - } while(token.type == Type.Annotation); - - symbol = new TerminalSymbol(token.type, token.value); - } else{ - symbol = readBuffered; - readBuffered = null; - } - lastRead = symbol; - return symbol; - } - - private void back() { - if(readBuffered != null) { - throw new RuntimeException(); - } - readBuffered = lastRead; - } - - public ChunkNode analyze() throws IOException, LexicalAnalysisException, SyntacticAnalysisException { - NonTerminalSymbol node = SyntacticDefine.getNonTerminalSymbol(Exp.StartChunk); - AnalysisNode container = AnalysisDefine.createContainer(Exp.StartChunk); - TerminalSymbol token = read(); - boolean matches = analyzeConsiderSign(container, node, token); - if(!matches) { - throw new SyntacticAnalysisException(); - } - StartChunkNode startChunk = (StartChunkNode) container; - return startChunk.chunk; - } - - private boolean analyzeConsiderSign(AnalysisNode container, NonTerminalSymbol node, TerminalSymbol token) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { - boolean many, empty; - if(node.sign == null) { - many = false; - empty = false; - } else if(node.sign == '?') { - many = false; - empty = true; - } else if(node.sign == '+') { - many = true; - empty = false; - } else if(node.sign == '*'){ - many = true; - empty = true; - } else { - throw new RuntimeException("unknown sign '"+ node.sign + "'"); - } - boolean notGenerateEmpty = analyzeWith(container, node, token); - - if(!empty && !notGenerateEmpty) { - unexpect(token, node); - } - - if(many && notGenerateEmpty) { - while(notGenerateEmpty) { - token = read(); - notGenerateEmpty = analyzeWith(container, node, token); - } - back(); - notGenerateEmpty = true; - } - return notGenerateEmpty; - } - - //analyzeWith 假定非终结符 node 不能产生空,因此,产生空的情况将视为不匹配。 - private boolean analyzeWith(AnalysisNode container, NonTerminalSymbol node, TerminalSymbol token) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { - boolean notGenerateEmpty; - int index = selectExpansionIndex(node, token); - if(index != -1) { - Object[] expansion = node.expansionList.get(index); - matchesExpansion(container, node, expansion, token); - notGenerateEmpty = true; - } else { - // 倘若不与任何一个 first set 匹配,则是同与 follow set 匹配。此次展开结果为空。 - notGenerateEmpty = false; - } - return notGenerateEmpty; - } - - private int selectExpansionIndex(NonTerminalSymbol node, TerminalSymbol token) { - int length = node.firstSetList.size(); - int index = -1; - for(int i = 0; i firstSet = node.firstSetList.get(i); - if(firstSet.contains(token)) { - index = i; - break; - } - } - return index; - } - - private void matchesExpansion(AnalysisNode container, NonTerminalSymbol parentNode, Object[] expansion, TerminalSymbol firstToken) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { - TerminalSymbol token = firstToken; - boolean notGenerateAllEmpty = false; - for(Object obj:expansion) { - boolean notGenerateEmpty; - NonTerminalSymbol node = tryGetNonTerminalSymbol(obj); - if(node != null) { - // 这个方法只要返回了值,就表明匹配了(因为生成空也是匹配的一种) - notGenerateEmpty = analyzeConsiderContainer(container, node, token); - } else { - TerminalSymbol needToken = (TerminalSymbol) obj; - if(!needToken.equals(token)) { - unexpect(token, needToken); - } - container.match(token); - notGenerateEmpty = true; - } - if(notGenerateEmpty) { - token = read(); - } - notGenerateAllEmpty |= notGenerateEmpty; - } - back(); - if (!notGenerateAllEmpty) { - // 此方法在 first set 匹配的情况下调用,因此展开式不能变成空。 - // 倘若这个展开式变成了空,则一定是有问题的。此时不应该继续分析下去了。 - unexpect(token, parentNode); - } - } - - private boolean analyzeConsiderContainer(AnalysisNode container, NonTerminalSymbol node, TerminalSymbol token) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { - boolean notGenerateEmpty; - AnalysisNode childContainer = null; - if(container.getExp() != node.exp) { - childContainer = AnalysisDefine.createContainer(node.exp); - } - if(childContainer == null) { - notGenerateEmpty = analyzeConsiderSign(container, node, token); - } else { - notGenerateEmpty = analyzeConsiderSign(childContainer, node, token); - if(notGenerateEmpty) { - container.match(childContainer); - } - childContainer.finish(); - } - return notGenerateEmpty; - } - - private NonTerminalSymbol tryGetNonTerminalSymbol(Object obj) { - NonTerminalSymbol node = null; - if(obj instanceof NonTerminalSymbol) { - node = (NonTerminalSymbol) obj; - - } else if(obj instanceof Exp){ - Exp exp = (Exp) obj; - node = SyntacticDefine.getNonTerminalSymbol(exp); - } - return node; - } - - private void unexpect(TerminalSymbol token, Object wantobj) throws SyntacticAnalysisException { - if(token.type == Type.EndSymbol) { - throw new SyntacticAnalysisException("unexpect $END wanted " + wantobj); - } else { - throw new SyntacticAnalysisException("unexpect " + token.value + " wanted " + wantobj); - } - } -} +package com.taozeyu.taolan.analysis; + +import java.io.IOException; +import java.util.HashSet; + +import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; +import com.taozeyu.taolan.analysis.Token.Type; +import com.taozeyu.taolan.analysis.node.ChunkNode; +import com.taozeyu.taolan.analysis.node.StartChunkNode; + + +public class SyntacticAnalysis { + + private final LexicalAnalysis lexicalAnalysis; + + public SyntacticAnalysis(LexicalAnalysis lexicalAnalysis) { + this.lexicalAnalysis = lexicalAnalysis; + } + + TerminalSymbol readBuffered = null; + TerminalSymbol lastRead = null; + + private TerminalSymbol read() throws IOException, LexicalAnalysisException { + TerminalSymbol symbol; + if(readBuffered == null) { + Token token; + do { + token = lexicalAnalysis.read(); + } while(token.type == Type.Annotation); + + symbol = new TerminalSymbol(token.type, token.value); + } else{ + symbol = readBuffered; + readBuffered = null; + } + lastRead = symbol; + return symbol; + } + + private void back() { + if(readBuffered != null) { + throw new RuntimeException(); + } + readBuffered = lastRead; + } + + public ChunkNode analyze() throws IOException, LexicalAnalysisException, SyntacticAnalysisException { + NonTerminalSymbol node = SyntacticDefine.getNonTerminalSymbol(Exp.StartChunk); + AnalysisNode container = AnalysisDefine.createContainer(Exp.StartChunk); + TerminalSymbol token = read(); + boolean matches = analyzeConsiderSign(container, node, token); + if(!matches) { + throw new SyntacticAnalysisException(); + } + StartChunkNode startChunk = (StartChunkNode) container; + return startChunk.chunk; + } + + private boolean analyzeConsiderSign(AnalysisNode container, NonTerminalSymbol node, TerminalSymbol token) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { + boolean many, empty; + if(node.sign == null) { + many = false; + empty = false; + } else if(node.sign == '?') { + many = false; + empty = true; + } else if(node.sign == '+') { + many = true; + empty = false; + } else if(node.sign == '*'){ + many = true; + empty = true; + } else { + throw new RuntimeException("unknown sign '"+ node.sign + "'"); + } + boolean notGenerateEmpty = analyzeWith(container, node, token); + + if(!empty && !notGenerateEmpty) { + unexpect(token, node); + } + + if(many && notGenerateEmpty) { + while(notGenerateEmpty) { + token = read(); + notGenerateEmpty = analyzeWith(container, node, token); + } + back(); + notGenerateEmpty = true; + } + return notGenerateEmpty; + } + + //analyzeWith 假定非终结符 node 不能产生空,因此,产生空的情况将视为不匹配。 + private boolean analyzeWith(AnalysisNode container, NonTerminalSymbol node, TerminalSymbol token) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { + boolean notGenerateEmpty; + int index = selectExpansionIndex(node, token); + if(index != -1) { + Object[] expansion = node.expansionList.get(index); + matchesExpansion(container, node, expansion, token); + notGenerateEmpty = true; + } else { + // 倘若不与任何一个 first set 匹配,则是同与 follow set 匹配。此次展开结果为空。 + notGenerateEmpty = false; + } + return notGenerateEmpty; + } + + private int selectExpansionIndex(NonTerminalSymbol node, TerminalSymbol token) { + int length = node.firstSetList.size(); + int index = -1; + for(int i = 0; i firstSet = node.firstSetList.get(i); + if(firstSet.contains(token)) { + index = i; + break; + } + } + return index; + } + + private void matchesExpansion(AnalysisNode container, NonTerminalSymbol parentNode, Object[] expansion, TerminalSymbol firstToken) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { + TerminalSymbol token = firstToken; + boolean notGenerateAllEmpty = false; + for(Object obj:expansion) { + boolean notGenerateEmpty; + NonTerminalSymbol node = tryGetNonTerminalSymbol(obj); + if(node != null) { + // 这个方法只要返回了值,就表明匹配了(因为生成空也是匹配的一种) + notGenerateEmpty = analyzeConsiderContainer(container, node, token); + } else { + TerminalSymbol needToken = (TerminalSymbol) obj; + if(!needToken.equals(token)) { + unexpect(token, needToken); + } + container.match(token); + notGenerateEmpty = true; + } + if(notGenerateEmpty) { + token = read(); + } + notGenerateAllEmpty |= notGenerateEmpty; + } + back(); + if (!notGenerateAllEmpty) { + // 此方法在 first set 匹配的情况下调用,因此展开式不能变成空。 + // 倘若这个展开式变成了空,则一定是有问题的。此时不应该继续分析下去了。 + unexpect(token, parentNode); + } + } + + private boolean analyzeConsiderContainer(AnalysisNode container, NonTerminalSymbol node, TerminalSymbol token) throws IOException, LexicalAnalysisException, SyntacticAnalysisException { + boolean notGenerateEmpty; + AnalysisNode childContainer = null; + if(container.getExp() != node.exp) { + childContainer = AnalysisDefine.createContainer(node.exp); + } + if(childContainer == null) { + notGenerateEmpty = analyzeConsiderSign(container, node, token); + } else { + notGenerateEmpty = analyzeConsiderSign(childContainer, node, token); + if(notGenerateEmpty) { + container.match(childContainer); + } + childContainer.finish(); + } + return notGenerateEmpty; + } + + private NonTerminalSymbol tryGetNonTerminalSymbol(Object obj) { + NonTerminalSymbol node = null; + if(obj instanceof NonTerminalSymbol) { + node = (NonTerminalSymbol) obj; + + } else if(obj instanceof Exp){ + Exp exp = (Exp) obj; + node = SyntacticDefine.getNonTerminalSymbol(exp); + } + return node; + } + + private void unexpect(TerminalSymbol token, Object wantobj) throws SyntacticAnalysisException { + if(token.type == Type.EndSymbol) { + throw new SyntacticAnalysisException("unexpect $END wanted " + wantobj); + } else { + throw new SyntacticAnalysisException("unexpect " + token.value + " wanted " + wantobj); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java b/src/main/java/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java rename to src/main/java/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java index 908f6b6..08ff4c2 --- a/src/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java +++ b/src/main/java/com/taozeyu/taolan/analysis/SyntacticAnalysisException.java @@ -1,16 +1,16 @@ -package com.taozeyu.taolan.analysis; - -public class SyntacticAnalysisException extends Exception { - - private static final long serialVersionUID = 5986954890480206628L; - - public SyntacticAnalysisException() {}; - - public SyntacticAnalysisException(String msg) { - super(msg); - } - - public SyntacticAnalysisException(TerminalSymbol token) { - super(token.toString()); - } -} +package com.taozeyu.taolan.analysis; + +public class SyntacticAnalysisException extends Exception { + + private static final long serialVersionUID = 5986954890480206628L; + + public SyntacticAnalysisException() {}; + + public SyntacticAnalysisException(String msg) { + super(msg); + } + + public SyntacticAnalysisException(TerminalSymbol token) { + super(token.toString()); + } +} diff --git a/src/com/taozeyu/taolan/analysis/SyntacticDefine.java b/src/main/java/com/taozeyu/taolan/analysis/SyntacticDefine.java old mode 100755 new mode 100644 similarity index 98% rename from src/com/taozeyu/taolan/analysis/SyntacticDefine.java rename to src/main/java/com/taozeyu/taolan/analysis/SyntacticDefine.java index be2a584..7520477 --- a/src/com/taozeyu/taolan/analysis/SyntacticDefine.java +++ b/src/main/java/com/taozeyu/taolan/analysis/SyntacticDefine.java @@ -1,334 +1,334 @@ -package com.taozeyu.taolan.analysis; - -import java.util.HashMap; - -import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; -import com.taozeyu.taolan.analysis.Token.Type; - -class SyntacticDefine { - - private final static HashMap expContainer = new HashMap<>(); - - static { - NonTerminalSymbol[] defineNodes = new NonTerminalSymbol[] { - - //基本单元 - node(Exp.Number).or(token(Type.Number), node().or(token(Type.Sign, "."), token(Type.Number)).sign('?')), - node(Exp.Variable).or( - node().or(token(Type.Sign, "@")).or(token(Type.Sign, "@@")).sign('?'), - token(Type.Identifier)), - node(Exp.String).or(token(Type.String)) - .or(token(Type.Sign, "$"), token(Type.Identifier)), - node(Exp.RegEx).or(token(Type.RegEx)), - - node(Exp.SpaceOrEnter).or(token(Type.NewLine)) - .or(token(Type.Space)).sign('*'), - node(Exp.Space).or(token(Type.Space)).sign('*'), - node(Exp.SplitSpaceSign).or(token(Type.Space)).sign('+'), - - node(Exp.Enter).or(node().or(token(Type.Space)).sign('?'), token(Type.NewLine)), - - node(Exp.This).or(token(Type.Keyword, "this")), - node(Exp.Null).or(token(Type.Keyword, "null")), - - node(Exp.Boolean).or(token(Type.Keyword, "true")) - .or(token(Type.Keyword, "false")), - - node(Exp.Element).or(Exp.Number) - .or(Exp.Variable) - .or(Exp.String) - .or(Exp.RegEx) - .or(Exp.Array) - .or(Exp.Container) - .or(Exp.This) - .or(Exp.Null) - .or(Exp.Boolean), - - //表达式相关 - node(Exp.L0Expression).or(Exp.L1Expression, node().or(Exp.L0Sign, Exp.L1Expression).sign('*')), - node(Exp.L0ParamExpression).or(Exp.L1ParamExpression, node().or(Exp.L0Sign, Exp.L1ParamExpression).sign('*')), - - node(Exp.L0Sign).or(token(Type.Sign, "=")) - .or(token(Type.Sign, "+=")).or(token(Type.Sign, "-=")) - .or(token(Type.Sign, "*=")).or(token(Type.Sign, "/=")) - .or(token(Type.Sign, "&&=")).or(token(Type.Sign, "=~")) - .or(token(Type.Sign, "||=")).or(token(Type.Sign, "&=")) - .or(token(Type.Sign, "<<")), - - node(Exp.L1Expression).or(Exp.L2Expression, node().or( - token(Type.Sign, "?"), Exp.L2Expression, token(Type.Sign, ":"), Exp.L2Expression - ).sign('?')), - node(Exp.L1ParamExpression).or(Exp.L2ParamExpression, node().or( - token(Type.Sign, "?"), Exp.L2ParamExpression, token(Type.Sign, ":"), Exp.L2ParamExpression - ).sign('?')), - - node(Exp.L2Expression).or(Exp.L3Expression, node().or(Exp.L2Sign, Exp.L3Expression).sign('*')), - node(Exp.L2ParamExpression).or(Exp.L3ParamExpression, node().or(Exp.L2Sign, Exp.L3ParamExpression).sign('*')), - - node(Exp.L2Sign).or(token(Type.Sign, "||")), - - node(Exp.L3Expression).or(Exp.L4Expression, node().or(Exp.L3Sign, Exp.L4Expression).sign('*')), - node(Exp.L3ParamExpression).or(Exp.L4ParamExpression, node().or(Exp.L3Sign, Exp.L4ParamExpression).sign('*')), - - node(Exp.L3Sign).or(token(Type.Sign, "&&")), - - node(Exp.L4Expression).or(Exp.L5Expression, node().or(Exp.L4Sign, Exp.L5Expression).sign('*')), - node(Exp.L4ParamExpression).or(Exp.L5ParamExpression, node().or(Exp.L4Sign, Exp.L5ParamExpression).sign('*')), - - node(Exp.L4Sign).or(token(Type.Sign, "^")), - - node(Exp.L5Expression).or(Exp.L6Expression, node().or(Exp.L5Sign, Exp.L6Expression).sign('*')), - node(Exp.L5ParamExpression).or(Exp.L6ParamExpression, node().or(Exp.L5Sign, Exp.L6ParamExpression).sign('*')), - - node(Exp.L5Sign).or(token(Type.Sign, "==")) - .or(token(Type.Sign, "!=")), - - node(Exp.L6Expression).or(Exp.L7Expression, node().or(Exp.L6Sign, Exp.L7Expression).sign('*')), - node(Exp.L6ParamExpression).or(Exp.L7ParamExpression, node().or(Exp.L6Sign, Exp.L7ParamExpression).sign('*')), - - node(Exp.L6Sign).or(token(Type.Sign, ">")).or(token(Type.Sign, "<")) - .or(token(Type.Sign, ">=")).or(token(Type.Sign, "<=")) - .or(token(Type.Keyword, "instanceof")) - .or(token(Type.Keyword, "is")), - - node(Exp.L7Expression).or(Exp.L8Expression, node().or(Exp.L7Sign, Exp.L8Expression).sign('*')), - node(Exp.L7ParamExpression).or(Exp.L8ParamExpression, node().or(Exp.L7Sign, Exp.L8ParamExpression).sign('*')), - - node(Exp.L7Sign).or(token(Type.Sign, "+")) - .or(token(Type.Sign, "-")), - - node(Exp.L8Expression).or(Exp.L9Expression, node().or(Exp.L8Sign, Exp.L9Expression).sign('*')), - node(Exp.L8ParamExpression).or(Exp.L9ParamExpression, node().or(Exp.L8Sign, Exp.L9ParamExpression).sign('*')), - - node(Exp.L8Sign).or(token(Type.Sign, "*")) - .or(token(Type.Sign, "/")) - .or(token(Type.Sign, "%")), - - node(Exp.L9Expression).or(node().or(Exp.L9Sign).sign('?'), Exp.L10Expression), - node(Exp.L9ParamExpression).or(node().or(Exp.L9Sign).sign('?'), Exp.L10ParamExpression), - - node(Exp.L9Sign).or(token(Type.Sign, "+")).or(token(Type.Sign, "-")).or(token(Type.Sign, "!")), - - node(Exp.L10Expression).or( - Exp.Space, - Exp.L11Expression, - Exp.L10Tail, - node().or(Exp.Invoker, Exp.Space, Exp.L10Tail) - .or(Exp.SplitSpaceSign, node().or(Exp.InvokerBraceless).sign('?')) - .sign('?'), - Exp.Space), - - node(Exp.L10ParamExpression).or( - Exp.Space, - Exp.L11Expression, - Exp.L10Tail, - node().or(Exp.InvokerBanLambda, Exp.Space, Exp.L10Tail) - .or(Exp.SplitSpaceSign, node().or(Exp.InvokerBracelessBanLambda).sign('?')) - .sign('?'), - Exp.Space), - - node(Exp.L10Tail).or(Exp.L10TailOperation).sign('*'), - - node(Exp.L10TailOperation).or(token(Type.Sign, "."), Exp.SpaceOrEnter, token(Type.Identifier)) - .or(token(Type.Sign, "["), Exp.L0Expression, token(Type.Sign, "]")) - .or(token(Type.Sign, ".."), Exp.L10Expression) - .or(token(Type.Sign, "<<"), Exp.L10Expression), - - node(Exp.L11Expression).or( - node().or(token(Type.Sign, "("), Exp.L0Expression, token(Type.Sign, ")")) - .or(Exp.Element)), - - //控制流语法 - node(Exp.StartChunk).or(Exp.Chunk), - - node(Exp.Chunk).or( - Exp.SpaceOrEnter, - node().or(Exp.Line, Exp.Space, - node().or(token(Type.NewLine), Exp.SpaceOrEnter) - .or(token(Type.EndSymbol))).sign('?') - ).sign('*'), - - node(Exp.Line).or(Exp.Command) - .or(Exp.Operate) - .or(Exp.DefineVariable) - .or(Exp.DefineFunction) - .or(Exp.IfElseChunk) - .or(Exp.WhileChunk) - .or(Exp.DoUntilChunk) - .or(Exp.ForEachChunk) - .or(Exp.TryCatch), - - node(Exp.Command).or(node().or(token(Type.Keyword, "break")) - .or(token(Type.Keyword, "return"), - Exp.Space, - node().or(Exp.L0Expression).sign('?')) - .or(token(Type.Keyword, "continue")) - .or(token(Type.Keyword, "throw"), Exp.Space, Exp.L0Expression), - Exp.When), - - node(Exp.Operate).or(Exp.L0Expression, Exp.When), - - node(Exp.When).or(node().or(Exp.SplitSpaceSign).sign('?'), - node().or(token(Type.Keyword, "when"), Exp.SplitSpaceSign, Exp.L0Expression).sign('?')), - - node(Exp.DefineVariable).or(token(Type.Keyword, "var"), - Exp.Space, - Exp.DefineVariableElement, - node().or(Exp.Space, token(Type.Sign, ","), - Exp.SpaceOrEnter, Exp.DefineVariableElement).sign('*')), - - node(Exp.DefineVariableElement).or(token(Type.Identifier), - Exp.Space, - node().or(token(Type.Sign, "="), Exp.Space, Exp.L0Expression).sign('?')), - - node(Exp.DefineFunction).or(token(Type.Keyword, "def"), - Exp.Space, Exp.L11Expression, Exp.Space, - node().or(token(Type.Sign, "->"),Exp.Space, - token(Type.Identifier), Exp.Space).sign('?'), - node().or(token(Type.Keyword, "operator"), Exp.Space, node() - .or(token(Type.Sign, "=")) - .or(token(Type.Sign, "+=")).or(token(Type.Sign, "-=")) - .or(token(Type.Sign, "*=")).or(token(Type.Sign, "/=")) - .or(token(Type.Sign, "&&=")).or(token(Type.Sign, "=~")) - .or(token(Type.Sign, "||=")).or(token(Type.Sign, "&=")) - ).sign('?'), - Exp.Space, - node().or(token(Type.Sign, "("), Exp.SpaceOrEnter, - Exp.ParamsList, Exp.SpaceOrEnter, - token(Type.Sign, ")")) - .sign('?'), - Exp.SpaceOrEnter, - Exp.Chunk, token(Type.Keyword, "end")), - - node(Exp.ParamsList).or(token(Type.Identifier), Exp.Space, - node().or(token(Type.Sign, ","), Exp.SpaceOrEnter, token(Type.Identifier), Exp.Space) - .sign('*')) - .sign('?'), - - node(Exp.IfElseChunk).or( - token(Type.Keyword, "if"), Exp.Space, - Exp.L0Expression, Exp.SpaceOrEnter, - Exp.Chunk, - node().or(token(Type.Keyword, "elsif"), Exp.Space, - Exp.L0Expression, Exp.SpaceOrEnter, - Exp.Chunk).sign('*'), - node().or(token(Type.Keyword, "else"), Exp.SpaceOrEnter, - Exp.Chunk).sign('?'), - Exp.SpaceOrEnter, - token(Type.Keyword, "end")), - - node(Exp.TryCatch).or(token(Type.Keyword, "try"), Exp.Space, Exp.Chunk, - node().or(token(Type.Keyword, "catch"), - Exp.Space, - token(Type.Identifier), - Exp.Space, - node().or(token(Type.Sign, "<-"), Exp.Space, - Exp.L0Expression) - .sign('?'), Exp.Chunk) - .sign('*'), - node().or(token(Type.Keyword, "finally"), Exp.SpaceOrEnter, Exp.Chunk) - .sign('?'), token(Type.Keyword, "end")), - - node(Exp.WhileChunk).or(token(Type.Keyword, "while"), Exp.Space, - Exp.L0ParamExpression, - token(Type.Keyword, "do"), Exp.SpaceOrEnter, - Exp.Chunk, - token(Type.Keyword, "end")), - - node(Exp.DoUntilChunk).or(token(Type.Keyword, "begin"), Exp.SpaceOrEnter, - Exp.Chunk, - token(Type.Keyword, "until"), Exp.Space, - Exp.L0Expression), - - node(Exp.ForEachChunk).or(token(Type.Keyword, "for"), Exp.SpaceOrEnter, node() - .or(Exp.ForEachCondition), Exp.SpaceOrEnter, - token(Type.Keyword, "do"), - Exp.Chunk, token(Type.Keyword, "end")), - - node(Exp.ForEachCondition).or(Exp.ForEachCommand, Exp.SpaceOrEnter, - token(Type.Sign, ";"), Exp.SpaceOrEnter, - Exp.L0ParamExpression, Exp.SpaceOrEnter, - token(Type.Sign, ";"), Exp.SpaceOrEnter, - Exp.ForEachCommand), - - node(Exp.ForEachCommand).or( - node().or(Exp.DefineVariable).or(Exp.L0ParamExpression), - node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, - node().or(Exp.DefineVariable).or(Exp.L0ParamExpression)).sign('*')), - - //语法糖 - node(Exp.Lambda).or(token(Type.Keyword, "do"), Exp.Space, - node().or(token(Type.Sign, "|"), Exp.SpaceOrEnter, - Exp.ParamsList, Exp.SpaceOrEnter, - token(Type.Sign, "|")) - .sign('?'), - Exp.SpaceOrEnter, - Exp.Chunk, token(Type.Keyword, "end")), - - node(Exp.List).or(Exp.L0Expression, node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.L0Expression).sign('*')), - node(Exp.Map).or(Exp.MapEntry, node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.MapEntry).sign('*')), - node(Exp.MapEntry).or( - node().or(Exp.String).or(token(Type.Identifier)), - Exp.SpaceOrEnter, Exp.SpaceOrEnter, token(Type.Sign, ":"), Exp.SpaceOrEnter, Exp.SpaceOrEnter, - Exp.L0Expression), - - node(Exp.Invoker).or(node() - .or(token(Type.Sign, "("), - node().or(Exp.SpaceOrEnter, Exp.ParamList, Exp.SpaceOrEnter).sign('?'), - token(Type.Sign, ")")), - Exp.Space, - node().or(Exp.Lambda).sign('?')), - - node(Exp.InvokerBraceless).or( - node().or(Exp.ParamListBanTokens, Exp.Space).sign('?'), - node().or(Exp.Lambda).sign('?')), - - node(Exp.InvokerBanLambda).or(node() - .or(token(Type.Sign, "("), Exp.SpaceOrEnter, - Exp.ParamList, Exp.SpaceOrEnter, - token(Type.Sign, ")"))), - - node(Exp.InvokerBracelessBanLambda).or(Exp.ParamListBanTokens, Exp.Space).sign('?'), - - node(Exp.ParamListBanTokens).or( - node().or(Exp.L0ParamExpression).ban( - token(Type.Sign, "+"), token(Type.Sign, "-"), token(Type.Sign, "[") - ), - node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.L0ParamExpression).sign('*')), - - node(Exp.ParamList).or( - node().or(Exp.L0ParamExpression), - node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.L0ParamExpression).sign('*')), - - node(Exp.Array).or(token(Type.Sign, "["), Exp.SpaceOrEnter, Exp.List, Exp.SpaceOrEnter, token(Type.Sign, "]")), - node(Exp.Container).or(token(Type.Sign, "{"), Exp.SpaceOrEnter, Exp.Map, Exp.SpaceOrEnter, token(Type.Sign, "}")), - - }; - for(NonTerminalSymbol node:defineNodes) - { - expContainer.put(node.exp, node); - } - FirstSetConstructor firstSetConstructor = new FirstSetConstructor(expContainer); - firstSetConstructor.build(); - } - - static NonTerminalSymbol getNonTerminalSymbol(Exp exp) { - return expContainer.get(exp); - } - - private static NonTerminalSymbol node(Exp exp) { - return new NonTerminalSymbol(exp); - } - - private static NonTerminalSymbol node() { - return new NonTerminalSymbol(null); - } - - private static TerminalSymbol token(Type type, String value) { - return new TerminalSymbol(type, value); - } - - private static TerminalSymbol token(Type type) { - return new TerminalSymbol(type, null); - } -} +package com.taozeyu.taolan.analysis; + +import java.util.HashMap; + +import com.taozeyu.taolan.analysis.NonTerminalSymbol.Exp; +import com.taozeyu.taolan.analysis.Token.Type; + +class SyntacticDefine { + + private final static HashMap expContainer = new HashMap<>(); + + static { + NonTerminalSymbol[] defineNodes = new NonTerminalSymbol[] { + + //基本单元 + node(Exp.Number).or(token(Type.Number), node().or(token(Type.Sign, "."), token(Type.Number)).sign('?')), + node(Exp.Variable).or( + node().or(token(Type.Sign, "@")).or(token(Type.Sign, "@@")).sign('?'), + token(Type.Identifier)), + node(Exp.String).or(token(Type.String)) + .or(token(Type.Sign, "$"), token(Type.Identifier)), + node(Exp.RegEx).or(token(Type.RegEx)), + + node(Exp.SpaceOrEnter).or(token(Type.NewLine)) + .or(token(Type.Space)).sign('*'), + node(Exp.Space).or(token(Type.Space)).sign('*'), + node(Exp.SplitSpaceSign).or(token(Type.Space)).sign('+'), + + node(Exp.Enter).or(node().or(token(Type.Space)).sign('?'), token(Type.NewLine)), + + node(Exp.This).or(token(Type.Keyword, "this")), + node(Exp.Null).or(token(Type.Keyword, "null")), + + node(Exp.Boolean).or(token(Type.Keyword, "true")) + .or(token(Type.Keyword, "false")), + + node(Exp.Element).or(Exp.Number) + .or(Exp.Variable) + .or(Exp.String) + .or(Exp.RegEx) + .or(Exp.Array) + .or(Exp.Container) + .or(Exp.This) + .or(Exp.Null) + .or(Exp.Boolean), + + //表达式相关 + node(Exp.L0Expression).or(Exp.L1Expression, node().or(Exp.L0Sign, Exp.L1Expression).sign('*')), + node(Exp.L0ParamExpression).or(Exp.L1ParamExpression, node().or(Exp.L0Sign, Exp.L1ParamExpression).sign('*')), + + node(Exp.L0Sign).or(token(Type.Sign, "=")) + .or(token(Type.Sign, "+=")).or(token(Type.Sign, "-=")) + .or(token(Type.Sign, "*=")).or(token(Type.Sign, "/=")) + .or(token(Type.Sign, "&&=")).or(token(Type.Sign, "=~")) + .or(token(Type.Sign, "||=")).or(token(Type.Sign, "&=")) + .or(token(Type.Sign, "<<")), + + node(Exp.L1Expression).or(Exp.L2Expression, node().or( + token(Type.Sign, "?"), Exp.L2Expression, token(Type.Sign, ":"), Exp.L2Expression + ).sign('?')), + node(Exp.L1ParamExpression).or(Exp.L2ParamExpression, node().or( + token(Type.Sign, "?"), Exp.L2ParamExpression, token(Type.Sign, ":"), Exp.L2ParamExpression + ).sign('?')), + + node(Exp.L2Expression).or(Exp.L3Expression, node().or(Exp.L2Sign, Exp.L3Expression).sign('*')), + node(Exp.L2ParamExpression).or(Exp.L3ParamExpression, node().or(Exp.L2Sign, Exp.L3ParamExpression).sign('*')), + + node(Exp.L2Sign).or(token(Type.Sign, "||")), + + node(Exp.L3Expression).or(Exp.L4Expression, node().or(Exp.L3Sign, Exp.L4Expression).sign('*')), + node(Exp.L3ParamExpression).or(Exp.L4ParamExpression, node().or(Exp.L3Sign, Exp.L4ParamExpression).sign('*')), + + node(Exp.L3Sign).or(token(Type.Sign, "&&")), + + node(Exp.L4Expression).or(Exp.L5Expression, node().or(Exp.L4Sign, Exp.L5Expression).sign('*')), + node(Exp.L4ParamExpression).or(Exp.L5ParamExpression, node().or(Exp.L4Sign, Exp.L5ParamExpression).sign('*')), + + node(Exp.L4Sign).or(token(Type.Sign, "^")), + + node(Exp.L5Expression).or(Exp.L6Expression, node().or(Exp.L5Sign, Exp.L6Expression).sign('*')), + node(Exp.L5ParamExpression).or(Exp.L6ParamExpression, node().or(Exp.L5Sign, Exp.L6ParamExpression).sign('*')), + + node(Exp.L5Sign).or(token(Type.Sign, "==")) + .or(token(Type.Sign, "!=")), + + node(Exp.L6Expression).or(Exp.L7Expression, node().or(Exp.L6Sign, Exp.L7Expression).sign('*')), + node(Exp.L6ParamExpression).or(Exp.L7ParamExpression, node().or(Exp.L6Sign, Exp.L7ParamExpression).sign('*')), + + node(Exp.L6Sign).or(token(Type.Sign, ">")).or(token(Type.Sign, "<")) + .or(token(Type.Sign, ">=")).or(token(Type.Sign, "<=")) + .or(token(Type.Keyword, "instanceof")) + .or(token(Type.Keyword, "is")), + + node(Exp.L7Expression).or(Exp.L8Expression, node().or(Exp.L7Sign, Exp.L8Expression).sign('*')), + node(Exp.L7ParamExpression).or(Exp.L8ParamExpression, node().or(Exp.L7Sign, Exp.L8ParamExpression).sign('*')), + + node(Exp.L7Sign).or(token(Type.Sign, "+")) + .or(token(Type.Sign, "-")), + + node(Exp.L8Expression).or(Exp.L9Expression, node().or(Exp.L8Sign, Exp.L9Expression).sign('*')), + node(Exp.L8ParamExpression).or(Exp.L9ParamExpression, node().or(Exp.L8Sign, Exp.L9ParamExpression).sign('*')), + + node(Exp.L8Sign).or(token(Type.Sign, "*")) + .or(token(Type.Sign, "/")) + .or(token(Type.Sign, "%")), + + node(Exp.L9Expression).or(node().or(Exp.L9Sign).sign('?'), Exp.L10Expression), + node(Exp.L9ParamExpression).or(node().or(Exp.L9Sign).sign('?'), Exp.L10ParamExpression), + + node(Exp.L9Sign).or(token(Type.Sign, "+")).or(token(Type.Sign, "-")).or(token(Type.Sign, "!")), + + node(Exp.L10Expression).or( + Exp.Space, + Exp.L11Expression, + Exp.L10Tail, + node().or(Exp.Invoker, Exp.Space, Exp.L10Tail) + .or(Exp.SplitSpaceSign, node().or(Exp.InvokerBraceless).sign('?')) + .sign('?'), + Exp.Space), + + node(Exp.L10ParamExpression).or( + Exp.Space, + Exp.L11Expression, + Exp.L10Tail, + node().or(Exp.InvokerBanLambda, Exp.Space, Exp.L10Tail) + .or(Exp.SplitSpaceSign, node().or(Exp.InvokerBracelessBanLambda).sign('?')) + .sign('?'), + Exp.Space), + + node(Exp.L10Tail).or(Exp.L10TailOperation).sign('*'), + + node(Exp.L10TailOperation).or(token(Type.Sign, "."), Exp.SpaceOrEnter, token(Type.Identifier)) + .or(token(Type.Sign, "["), Exp.L0Expression, token(Type.Sign, "]")) + .or(token(Type.Sign, ".."), Exp.L10Expression) + .or(token(Type.Sign, "<<"), Exp.L10Expression), + + node(Exp.L11Expression).or( + node().or(token(Type.Sign, "("), Exp.L0Expression, token(Type.Sign, ")")) + .or(Exp.Element)), + + //控制流语法 + node(Exp.StartChunk).or(Exp.Chunk), + + node(Exp.Chunk).or( + Exp.SpaceOrEnter, + node().or(Exp.Line, Exp.Space, + node().or(token(Type.NewLine), Exp.SpaceOrEnter) + .or(token(Type.EndSymbol))).sign('?') + ).sign('*'), + + node(Exp.Line).or(Exp.Command) + .or(Exp.Operate) + .or(Exp.DefineVariable) + .or(Exp.DefineFunction) + .or(Exp.IfElseChunk) + .or(Exp.WhileChunk) + .or(Exp.DoUntilChunk) + .or(Exp.ForEachChunk) + .or(Exp.TryCatch), + + node(Exp.Command).or(node().or(token(Type.Keyword, "break")) + .or(token(Type.Keyword, "return"), + Exp.Space, + node().or(Exp.L0Expression).sign('?')) + .or(token(Type.Keyword, "continue")) + .or(token(Type.Keyword, "throw"), Exp.Space, Exp.L0Expression), + Exp.When), + + node(Exp.Operate).or(Exp.L0Expression, Exp.When), + + node(Exp.When).or(node().or(Exp.SplitSpaceSign).sign('?'), + node().or(token(Type.Keyword, "when"), Exp.SplitSpaceSign, Exp.L0Expression).sign('?')), + + node(Exp.DefineVariable).or(token(Type.Keyword, "var"), + Exp.Space, + Exp.DefineVariableElement, + node().or(Exp.Space, token(Type.Sign, ","), + Exp.SpaceOrEnter, Exp.DefineVariableElement).sign('*')), + + node(Exp.DefineVariableElement).or(token(Type.Identifier), + Exp.Space, + node().or(token(Type.Sign, "="), Exp.Space, Exp.L0Expression).sign('?')), + + node(Exp.DefineFunction).or(token(Type.Keyword, "def"), + Exp.Space, Exp.L11Expression, Exp.Space, + node().or(token(Type.Sign, "->"),Exp.Space, + token(Type.Identifier), Exp.Space).sign('?'), + node().or(token(Type.Keyword, "operator"), Exp.Space, node() + .or(token(Type.Sign, "=")) + .or(token(Type.Sign, "+=")).or(token(Type.Sign, "-=")) + .or(token(Type.Sign, "*=")).or(token(Type.Sign, "/=")) + .or(token(Type.Sign, "&&=")).or(token(Type.Sign, "=~")) + .or(token(Type.Sign, "||=")).or(token(Type.Sign, "&=")) + ).sign('?'), + Exp.Space, + node().or(token(Type.Sign, "("), Exp.SpaceOrEnter, + Exp.ParamsList, Exp.SpaceOrEnter, + token(Type.Sign, ")")) + .sign('?'), + Exp.SpaceOrEnter, + Exp.Chunk, token(Type.Keyword, "end")), + + node(Exp.ParamsList).or(token(Type.Identifier), Exp.Space, + node().or(token(Type.Sign, ","), Exp.SpaceOrEnter, token(Type.Identifier), Exp.Space) + .sign('*')) + .sign('?'), + + node(Exp.IfElseChunk).or( + token(Type.Keyword, "if"), Exp.Space, + Exp.L0Expression, Exp.SpaceOrEnter, + Exp.Chunk, + node().or(token(Type.Keyword, "elsif"), Exp.Space, + Exp.L0Expression, Exp.SpaceOrEnter, + Exp.Chunk).sign('*'), + node().or(token(Type.Keyword, "else"), Exp.SpaceOrEnter, + Exp.Chunk).sign('?'), + Exp.SpaceOrEnter, + token(Type.Keyword, "end")), + + node(Exp.TryCatch).or(token(Type.Keyword, "try"), Exp.Space, Exp.Chunk, + node().or(token(Type.Keyword, "catch"), + Exp.Space, + token(Type.Identifier), + Exp.Space, + node().or(token(Type.Sign, "<-"), Exp.Space, + Exp.L0Expression) + .sign('?'), Exp.Chunk) + .sign('*'), + node().or(token(Type.Keyword, "finally"), Exp.SpaceOrEnter, Exp.Chunk) + .sign('?'), token(Type.Keyword, "end")), + + node(Exp.WhileChunk).or(token(Type.Keyword, "while"), Exp.Space, + Exp.L0ParamExpression, + token(Type.Keyword, "do"), Exp.SpaceOrEnter, + Exp.Chunk, + token(Type.Keyword, "end")), + + node(Exp.DoUntilChunk).or(token(Type.Keyword, "begin"), Exp.SpaceOrEnter, + Exp.Chunk, + token(Type.Keyword, "until"), Exp.Space, + Exp.L0Expression), + + node(Exp.ForEachChunk).or(token(Type.Keyword, "for"), Exp.SpaceOrEnter, node() + .or(Exp.ForEachCondition), Exp.SpaceOrEnter, + token(Type.Keyword, "do"), + Exp.Chunk, token(Type.Keyword, "end")), + + node(Exp.ForEachCondition).or(Exp.ForEachCommand, Exp.SpaceOrEnter, + token(Type.Sign, ";"), Exp.SpaceOrEnter, + Exp.L0ParamExpression, Exp.SpaceOrEnter, + token(Type.Sign, ";"), Exp.SpaceOrEnter, + Exp.ForEachCommand), + + node(Exp.ForEachCommand).or( + node().or(Exp.DefineVariable).or(Exp.L0ParamExpression), + node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, + node().or(Exp.DefineVariable).or(Exp.L0ParamExpression)).sign('*')), + + //语法糖 + node(Exp.Lambda).or(token(Type.Keyword, "do"), Exp.Space, + node().or(token(Type.Sign, "|"), Exp.SpaceOrEnter, + Exp.ParamsList, Exp.SpaceOrEnter, + token(Type.Sign, "|")) + .sign('?'), + Exp.SpaceOrEnter, + Exp.Chunk, token(Type.Keyword, "end")), + + node(Exp.List).or(Exp.L0Expression, node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.L0Expression).sign('*')), + node(Exp.Map).or(Exp.MapEntry, node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.MapEntry).sign('*')), + node(Exp.MapEntry).or( + node().or(Exp.String).or(token(Type.Identifier)), + Exp.SpaceOrEnter, Exp.SpaceOrEnter, token(Type.Sign, ":"), Exp.SpaceOrEnter, Exp.SpaceOrEnter, + Exp.L0Expression), + + node(Exp.Invoker).or(node() + .or(token(Type.Sign, "("), + node().or(Exp.SpaceOrEnter, Exp.ParamList, Exp.SpaceOrEnter).sign('?'), + token(Type.Sign, ")")), + Exp.Space, + node().or(Exp.Lambda).sign('?')), + + node(Exp.InvokerBraceless).or( + node().or(Exp.ParamListBanTokens, Exp.Space).sign('?'), + node().or(Exp.Lambda).sign('?')), + + node(Exp.InvokerBanLambda).or(node() + .or(token(Type.Sign, "("), Exp.SpaceOrEnter, + Exp.ParamList, Exp.SpaceOrEnter, + token(Type.Sign, ")"))), + + node(Exp.InvokerBracelessBanLambda).or(Exp.ParamListBanTokens, Exp.Space).sign('?'), + + node(Exp.ParamListBanTokens).or( + node().or(Exp.L0ParamExpression).ban( + token(Type.Sign, "+"), token(Type.Sign, "-"), token(Type.Sign, "[") + ), + node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.L0ParamExpression).sign('*')), + + node(Exp.ParamList).or( + node().or(Exp.L0ParamExpression), + node().or(Exp.Space, token(Type.Sign, ","), Exp.SpaceOrEnter, Exp.L0ParamExpression).sign('*')), + + node(Exp.Array).or(token(Type.Sign, "["), Exp.SpaceOrEnter, Exp.List, Exp.SpaceOrEnter, token(Type.Sign, "]")), + node(Exp.Container).or(token(Type.Sign, "{"), Exp.SpaceOrEnter, Exp.Map, Exp.SpaceOrEnter, token(Type.Sign, "}")), + + }; + for(NonTerminalSymbol node:defineNodes) + { + expContainer.put(node.exp, node); + } + FirstSetConstructor firstSetConstructor = new FirstSetConstructor(expContainer); + firstSetConstructor.build(); + } + + static NonTerminalSymbol getNonTerminalSymbol(Exp exp) { + return expContainer.get(exp); + } + + private static NonTerminalSymbol node(Exp exp) { + return new NonTerminalSymbol(exp); + } + + private static NonTerminalSymbol node() { + return new NonTerminalSymbol(null); + } + + private static TerminalSymbol token(Type type, String value) { + return new TerminalSymbol(type, value); + } + + private static TerminalSymbol token(Type type) { + return new TerminalSymbol(type, null); + } +} diff --git a/src/com/taozeyu/taolan/analysis/TerminalSymbol.java b/src/main/java/com/taozeyu/taolan/analysis/TerminalSymbol.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/TerminalSymbol.java rename to src/main/java/com/taozeyu/taolan/analysis/TerminalSymbol.java index c83f624..fe6f302 --- a/src/com/taozeyu/taolan/analysis/TerminalSymbol.java +++ b/src/main/java/com/taozeyu/taolan/analysis/TerminalSymbol.java @@ -1,85 +1,85 @@ -package com.taozeyu.taolan.analysis; - -import java.util.HashSet; - -import com.taozeyu.taolan.analysis.Token.Type; - -public class TerminalSymbol { - - @SuppressWarnings("serial") - private final static HashSet careValueTypeSet = new HashSet() {{ - add(Type.Keyword); - add(Type.Sign); - }}; - - static final TerminalSymbol Empty = new TerminalSymbol(null, null); - - public final Type type; - public final String value; - final boolean careValue; - - TerminalSymbol(Type type, String value) { - this.type = type; - this.value = value; - this.careValue = careValueTypeSet.contains(type); - } - - boolean isEmpty() { - return this.type == null; - } - - @Override - public boolean equals(Object obj) { - boolean isEquals = false; - if(obj instanceof TerminalSymbol) { - TerminalSymbol other = (TerminalSymbol) obj; - isEquals = isEquals(this.type, other.type); - if(isEquals & careValue) { - isEquals = isEquals(this.value, other.value); - } - } - return isEquals; - } - - private boolean isEquals(Object o1, Object o2) { - boolean isEquals = false; - if(o1 == null & o2 == null) { - isEquals = true; - } else if(o1 != null & o2 != null) { - isEquals = o1.equals(o2); - } - return isEquals; - } - - @Override - public int hashCode() { - int hashCode = getHashCode(this.type); - if(careValue) { - hashCode ^= getHashCode(this.value); - } - return hashCode; - } - - private int getHashCode(Object obj) { - int hashCode = 0; - if(obj != null) { - hashCode = obj.hashCode(); - } - return hashCode; - } - - @Override - public String toString() { - String str; - if(this.value != null) { - str = " “" + this.value + "”"; - } else { - if(this.type != null) { - str = this.type.toString(); - } else { - str = "ε"; - } - } - return str; - } -} +package com.taozeyu.taolan.analysis; + +import java.util.HashSet; + +import com.taozeyu.taolan.analysis.Token.Type; + +public class TerminalSymbol { + + @SuppressWarnings("serial") + private final static HashSet careValueTypeSet = new HashSet() {{ + add(Type.Keyword); + add(Type.Sign); + }}; + + static final TerminalSymbol Empty = new TerminalSymbol(null, null); + + public final Type type; + public final String value; + final boolean careValue; + + TerminalSymbol(Type type, String value) { + this.type = type; + this.value = value; + this.careValue = careValueTypeSet.contains(type); + } + + boolean isEmpty() { + return this.type == null; + } + + @Override + public boolean equals(Object obj) { + boolean isEquals = false; + if(obj instanceof TerminalSymbol) { + TerminalSymbol other = (TerminalSymbol) obj; + isEquals = isEquals(this.type, other.type); + if(isEquals & careValue) { + isEquals = isEquals(this.value, other.value); + } + } + return isEquals; + } + + private boolean isEquals(Object o1, Object o2) { + boolean isEquals = false; + if(o1 == null & o2 == null) { + isEquals = true; + } else if(o1 != null & o2 != null) { + isEquals = o1.equals(o2); + } + return isEquals; + } + + @Override + public int hashCode() { + int hashCode = getHashCode(this.type); + if(careValue) { + hashCode ^= getHashCode(this.value); + } + return hashCode; + } + + private int getHashCode(Object obj) { + int hashCode = 0; + if(obj != null) { + hashCode = obj.hashCode(); + } + return hashCode; + } + + @Override + public String toString() { + String str; + if(this.value != null) { + str = " “" + this.value + "”"; + } else { + if(this.type != null) { + str = this.type.toString(); + } else { + str = "ε"; + } + } + return str; + } +} diff --git a/src/com/taozeyu/taolan/analysis/Token.java b/src/main/java/com/taozeyu/taolan/analysis/Token.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/Token.java rename to src/main/java/com/taozeyu/taolan/analysis/Token.java index f47a7ea..135deb0 --- a/src/com/taozeyu/taolan/analysis/Token.java +++ b/src/main/java/com/taozeyu/taolan/analysis/Token.java @@ -1,76 +1,76 @@ -package com.taozeyu.taolan.analysis; - -import java.util.HashSet; - -public class Token { - - private static final HashSet keywordsSet = new HashSet<>(); - - static { - keywordsSet.add("true"); - keywordsSet.add("false"); - keywordsSet.add("if"); - keywordsSet.add("when"); - keywordsSet.add("elsif"); - keywordsSet.add("else"); - keywordsSet.add("while"); - keywordsSet.add("begin"); - keywordsSet.add("until"); - keywordsSet.add("for"); - keywordsSet.add("do"); - keywordsSet.add("try"); - keywordsSet.add("catch"); - keywordsSet.add("finally"); - keywordsSet.add("end"); - keywordsSet.add("def"); - keywordsSet.add("var"); - keywordsSet.add("this"); - keywordsSet.add("null"); - keywordsSet.add("throw"); - keywordsSet.add("break"); - keywordsSet.add("continue"); - keywordsSet.add("return"); - keywordsSet.add("operator"); - keywordsSet.add("instanceof"); - keywordsSet.add("is"); - } - - public static enum Type { - Keyword, Number, Identifier, Sign, Annotation, String, RegEx, Space, NewLine, EndSymbol; - } - - final Type type; - final String value; - - Token(Type type, String value) { - - if(type == Type.Identifier) { - char firstChar = value.charAt(0); - if(firstChar >= '0' & firstChar < '9') { - type = Type.Number; - - } else if(keywordsSet.contains(value)){ - type = Type.Keyword; - } - } - else if(type == Type.Annotation) { - value = value.substring(1); - } - else if(type == Type.String) { - value = value.substring(1, value.length() - 1); - } - else if(type == Type.RegEx) { - value = value.substring(1, value.length() - 1); - } - else if(type == Type.EndSymbol) { - value = null; - } - this.type = type; - this.value = value; - } - - @Override - public String toString() { - return String.format("%s(%s) ", type, value); - } -} +package com.taozeyu.taolan.analysis; + +import java.util.HashSet; + +public class Token { + + private static final HashSet keywordsSet = new HashSet<>(); + + static { + keywordsSet.add("true"); + keywordsSet.add("false"); + keywordsSet.add("if"); + keywordsSet.add("when"); + keywordsSet.add("elsif"); + keywordsSet.add("else"); + keywordsSet.add("while"); + keywordsSet.add("begin"); + keywordsSet.add("until"); + keywordsSet.add("for"); + keywordsSet.add("do"); + keywordsSet.add("try"); + keywordsSet.add("catch"); + keywordsSet.add("finally"); + keywordsSet.add("end"); + keywordsSet.add("def"); + keywordsSet.add("var"); + keywordsSet.add("this"); + keywordsSet.add("null"); + keywordsSet.add("throw"); + keywordsSet.add("break"); + keywordsSet.add("continue"); + keywordsSet.add("return"); + keywordsSet.add("operator"); + keywordsSet.add("instanceof"); + keywordsSet.add("is"); + } + + public static enum Type { + Keyword, Number, Identifier, Sign, Annotation, String, RegEx, Space, NewLine, EndSymbol; + } + + final Type type; + final String value; + + Token(Type type, String value) { + + if(type == Type.Identifier) { + char firstChar = value.charAt(0); + if(firstChar >= '0' & firstChar < '9') { + type = Type.Number; + + } else if(keywordsSet.contains(value)){ + type = Type.Keyword; + } + } + else if(type == Type.Annotation) { + value = value.substring(1); + } + else if(type == Type.String) { + value = value.substring(1, value.length() - 1); + } + else if(type == Type.RegEx) { + value = value.substring(1, value.length() - 1); + } + else if(type == Type.EndSymbol) { + value = null; + } + this.type = type; + this.value = value; + } + + @Override + public String toString() { + return String.format("%s(%s) ", type, value); + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/ArrayNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/ArrayNode.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/analysis/node/ArrayNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/ArrayNode.java index 303cd30..348577a --- a/src/com/taozeyu/taolan/analysis/node/ArrayNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/ArrayNode.java @@ -1,27 +1,27 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; - -import com.taozeyu.taolan.analysis.AnalysisNode; -import com.taozeyu.taolan.analysis.TerminalSymbol; - - -public class ArrayNode extends AnalysisNode { - - public List content = new ArrayList<>(); - - @Override - public void print(int retractNum, PrintStream out) { - out.print("["); - printParams(retractNum, out, content); - out.print("]"); - } - - @Override - public void match(AnalysisNode analysisNode) { } - - @Override - public void match(TerminalSymbol token) { } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +import com.taozeyu.taolan.analysis.AnalysisNode; +import com.taozeyu.taolan.analysis.TerminalSymbol; + + +public class ArrayNode extends AnalysisNode { + + public List content = new ArrayList<>(); + + @Override + public void print(int retractNum, PrintStream out) { + out.print("["); + printParams(retractNum, out, content); + out.print("]"); + } + + @Override + public void match(AnalysisNode analysisNode) { } + + @Override + public void match(TerminalSymbol token) { } +} diff --git a/src/com/taozeyu/taolan/analysis/node/ChunkNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/ChunkNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/ChunkNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/ChunkNode.java index 8e0aeb2..d43a622 --- a/src/com/taozeyu/taolan/analysis/node/ChunkNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/ChunkNode.java @@ -1,21 +1,21 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.*; - -import com.taozeyu.taolan.analysis.AnalysisNode; - - -public abstract class ChunkNode extends AnalysisNode { - - public List lineList = new LinkedList<>(); - - @Override - public void print(int retractNum, PrintStream out) { - for(AnalysisNode line: lineList) { - printRetract(retractNum, out); - line.print(retractNum, out); - out.println(); - } - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.*; + +import com.taozeyu.taolan.analysis.AnalysisNode; + + +public abstract class ChunkNode extends AnalysisNode { + + public List lineList = new LinkedList<>(); + + @Override + public void print(int retractNum, PrintStream out) { + for(AnalysisNode line: lineList) { + printRetract(retractNum, out); + line.print(retractNum, out); + out.println(); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/CommandNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/CommandNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/CommandNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/CommandNode.java index 2cf4c99..c2ac669 --- a/src/com/taozeyu/taolan/analysis/node/CommandNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/CommandNode.java @@ -1,25 +1,25 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; - - -public abstract class CommandNode extends AnalysisNode { - - public String command = null; - public ExpressionNode expression = null; - public WhenNode condition = null; - - @Override - public void print(int retractNum, PrintStream out) { - out.print(command); - if(expression != null) { - out.print(" "); - expression.print(retractNum, out); - } - if(condition != null) { - condition.print(retractNum, out); - } - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; + + +public abstract class CommandNode extends AnalysisNode { + + public String command = null; + public ExpressionNode expression = null; + public WhenNode condition = null; + + @Override + public void print(int retractNum, PrintStream out) { + out.print(command); + if(expression != null) { + out.print(" "); + expression.print(retractNum, out); + } + if(condition != null) { + condition.print(retractNum, out); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/ContainerNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/ContainerNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/ContainerNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/ContainerNode.java index fa4e5e4..b25a597 --- a/src/com/taozeyu/taolan/analysis/node/ContainerNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/ContainerNode.java @@ -1,37 +1,37 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; - -import com.taozeyu.taolan.analysis.AnalysisNode; -import com.taozeyu.taolan.analysis.TerminalSymbol; - -public class ContainerNode extends AnalysisNode { - - public Map content = new LinkedHashMap<>(); - - @Override - public void print(int retractNum, PrintStream out) { - Iterator> it = content.entrySet().iterator(); - out.print("{"); - while(it.hasNext()) { - Entry e = it.next(); - out.print(e.getKey()); - out.print(" : "); - e.getValue().print(retractNum, out); - if(it.hasNext()) { - out.print(", "); - } - } - out.print("}"); - } - - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) {} -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.taozeyu.taolan.analysis.AnalysisNode; +import com.taozeyu.taolan.analysis.TerminalSymbol; + +public class ContainerNode extends AnalysisNode { + + public Map content = new LinkedHashMap<>(); + + @Override + public void print(int retractNum, PrintStream out) { + Iterator> it = content.entrySet().iterator(); + out.print("{"); + while(it.hasNext()) { + Entry e = it.next(); + out.print(e.getKey()); + out.print(" : "); + e.getValue().print(retractNum, out); + if(it.hasNext()) { + out.print(", "); + } + } + out.print("}"); + } + + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) {} +} diff --git a/src/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java index 07a30fd..380cdf6 --- a/src/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/DefineFunctionNode.java @@ -1,45 +1,45 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class DefineFunctionNode extends AnalysisNode { - - public String functionName; - public ExpressionNode parentExpression = null; - public String operator = null; - public ChunkNode body; - - public List paramNames = new LinkedList<>(); - - public Set requireSet; - public int id; - - @Override - public void print(int retractNum, PrintStream out) { - out.print("def "); - if(parentExpression != null) { - parentExpression.print(retractNum, out); - out.print("->"); - } - out.print(functionName); - if(operator != null) { - out.print(" operator"); - out.print(operator); - out.print(" "); - } - out.print("{"); - printParams(retractNum, out, paramNames); - out.print("}\n"); - if(body != null) { - body.print(retractNum + 1, out); - } - printRetract(retractNum, out); - out.print("end\n"); - } - -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import com.taozeyu.taolan.analysis.AnalysisNode; + +public abstract class DefineFunctionNode extends AnalysisNode { + + public String functionName; + public ExpressionNode parentExpression = null; + public String operator = null; + public ChunkNode body; + + public List paramNames = new LinkedList<>(); + + public Set requireSet; + public int id; + + @Override + public void print(int retractNum, PrintStream out) { + out.print("def "); + if(parentExpression != null) { + parentExpression.print(retractNum, out); + out.print("->"); + } + out.print(functionName); + if(operator != null) { + out.print(" operator"); + out.print(operator); + out.print(" "); + } + out.print("{"); + printParams(retractNum, out, paramNames); + out.print("}\n"); + if(body != null) { + body.print(retractNum + 1, out); + } + printRetract(retractNum, out); + out.print("end\n"); + } + +} diff --git a/src/com/taozeyu/taolan/analysis/node/DefineVariableNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/DefineVariableNode.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/analysis/node/DefineVariableNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/DefineVariableNode.java index 2c7a242..789d305 --- a/src/com/taozeyu/taolan/analysis/node/DefineVariableNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/DefineVariableNode.java @@ -1,23 +1,23 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; - - -public abstract class DefineVariableNode extends AnalysisNode { - - public String variableName; - public ExpressionNode initValue = null; - - @Override - public void print(int retractNum, PrintStream out) { - out.print("var "); - out.print(variableName); - if(initValue != null) { - out.print(" = "); - initValue.print(retractNum, out); - } - } - -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; + + +public abstract class DefineVariableNode extends AnalysisNode { + + public String variableName; + public ExpressionNode initValue = null; + + @Override + public void print(int retractNum, PrintStream out) { + out.print("var "); + out.print(variableName); + if(initValue != null) { + out.print(" = "); + initValue.print(retractNum, out); + } + } + +} diff --git a/src/com/taozeyu/taolan/analysis/node/ElementNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/ElementNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/ElementNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/ElementNode.java index 7303397..62858bb --- a/src/com/taozeyu/taolan/analysis/node/ElementNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/ElementNode.java @@ -1,72 +1,72 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; - - -public abstract class ElementNode extends AnalysisNode { - - public enum ElementType { - Integer, Number, Variable, String, RegEx, Array, Container, This, Null, Boolean, - } - - public ElementType type; - public String value; - - public boolean fromThis = false; - public boolean fromConstructor = false; - - public ArrayNode array = null; - public ContainerNode container = null; - - public boolean isLocalVariable() { - return type == ElementType.Variable && !fromConstructor && !fromThis; - } - - public boolean isAttributeVariable() { - return type == ElementType.Variable && (fromConstructor || fromThis); - } - - @Override - public void print(int retractNum, PrintStream out) { - if(type == ElementType.Integer) { - out.print(value); - - } else if(type == ElementType.Number) { - out.print(value); - - } else if(type == ElementType.Variable) { - if(fromConstructor) { - out.print("@@"); - } else if(fromThis) { - out.print("@"); - } - out.print(value); - - } else if(type == ElementType.String) { - out.print("\""); - out.print(value); - out.print("\""); - - } else if(type == ElementType.RegEx) { - out.print("`"); - out.print(value); - out.print("`"); - - } else if(type == ElementType.Array) { - array.print(retractNum, out); - - } else if(type == ElementType.Container) { - container.print(retractNum, out); - - } else if(type == ElementType.This) { - out.print("this"); - - } else if(type == ElementType.Null) { - out.print("null"); - } else { - out.print(value); - } - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; + + +public abstract class ElementNode extends AnalysisNode { + + public enum ElementType { + Integer, Number, Variable, String, RegEx, Array, Container, This, Null, Boolean, + } + + public ElementType type; + public String value; + + public boolean fromThis = false; + public boolean fromConstructor = false; + + public ArrayNode array = null; + public ContainerNode container = null; + + public boolean isLocalVariable() { + return type == ElementType.Variable && !fromConstructor && !fromThis; + } + + public boolean isAttributeVariable() { + return type == ElementType.Variable && (fromConstructor || fromThis); + } + + @Override + public void print(int retractNum, PrintStream out) { + if(type == ElementType.Integer) { + out.print(value); + + } else if(type == ElementType.Number) { + out.print(value); + + } else if(type == ElementType.Variable) { + if(fromConstructor) { + out.print("@@"); + } else if(fromThis) { + out.print("@"); + } + out.print(value); + + } else if(type == ElementType.String) { + out.print("\""); + out.print(value); + out.print("\""); + + } else if(type == ElementType.RegEx) { + out.print("`"); + out.print(value); + out.print("`"); + + } else if(type == ElementType.Array) { + array.print(retractNum, out); + + } else if(type == ElementType.Container) { + container.print(retractNum, out); + + } else if(type == ElementType.This) { + out.print("this"); + + } else if(type == ElementType.Null) { + out.print("null"); + } else { + out.print(value); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/ExpressionNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/ExpressionNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/ExpressionNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/ExpressionNode.java index 281bc18..e69159b --- a/src/com/taozeyu/taolan/analysis/node/ExpressionNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/ExpressionNode.java @@ -1,118 +1,118 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; -import com.taozeyu.taolan.analysis.TerminalSymbol; - -public abstract class ExpressionNode extends AnalysisNode { - - public String sign = null; - - public InvokerNode invoker = null; - - final public ExpressionNode[] expressionOperands = new ExpressionNode[3]; - final public ElementNode[] elementOperands = new ElementNode[3]; - - protected ExpressionNode fork() { - ExpressionNode forked = new ExpressionNode() { - @Override - public void match(AnalysisNode analysisNode) {} - - @Override - public void match(TerminalSymbol token) {} - }; - forked.copy(this); - return forked; - } - - public void copy(ExpressionNode other) { - for(int i=0; i<3; ++i) { - this.expressionOperands[i] = other.expressionOperands[i]; - this.elementOperands[i] = other.elementOperands[i]; - } - this.sign = other.sign; - this.invoker = other.invoker; - } - - public void clear() { - for(int i=0; i<3; ++i) { - expressionOperands[i] = null; - elementOperands[i] = null; - } - sign = null; - invoker = null; - } - - protected boolean isSecondPositionFilled() { - return invoker != null || (sign != null && any(1)); - } - - public ExpressionNode getExpressionAt(int index) { - return expressionOperands[index]; - } - - public ElementNode getElementAt(int index) { - return elementOperands[index]; - } - - public boolean isExpression(int index) { - return expressionOperands[index] != null; - } - - public boolean isElement(int index) { - return elementOperands[index] != null; - } - - public boolean any(int index) { - return expressionOperands[index] != null || elementOperands[index] != null; - } - - @Override - public void print(int retractNum, PrintStream out) { - if(invoker != null) { - printAt(0, retractNum, out); - invoker.print(retractNum, out); - - } else if(sign == null) { - printAt(0, retractNum, out); - - } else { - int num = 0; - for(int i=0; i<3; ++i) { - if(any(i)) { - num ++; - } - } - if(num == 3) { - printAt(0, retractNum, out); - out.print(" ? "); - printAt(1, retractNum, out); - out.print(" : "); - printAt(2, retractNum, out); - } - else if(num == 2) { - printAt(0, retractNum, out); - out.print(" "); - out.print(sign); - out.print(" "); - printAt(1, retractNum, out); - } - else { - out.print(sign); - out.print(" "); - printAt(0, retractNum, out); - } - } - } - - private void printAt(int index, int retractNum, PrintStream out) { - if(isElement(index)) { - elementOperands[index].print(retractNum, out); - } else { - out.print("("); - expressionOperands[index].print(retractNum, out); - out.print(")"); - } - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; +import com.taozeyu.taolan.analysis.TerminalSymbol; + +public abstract class ExpressionNode extends AnalysisNode { + + public String sign = null; + + public InvokerNode invoker = null; + + final public ExpressionNode[] expressionOperands = new ExpressionNode[3]; + final public ElementNode[] elementOperands = new ElementNode[3]; + + protected ExpressionNode fork() { + ExpressionNode forked = new ExpressionNode() { + @Override + public void match(AnalysisNode analysisNode) {} + + @Override + public void match(TerminalSymbol token) {} + }; + forked.copy(this); + return forked; + } + + public void copy(ExpressionNode other) { + for(int i=0; i<3; ++i) { + this.expressionOperands[i] = other.expressionOperands[i]; + this.elementOperands[i] = other.elementOperands[i]; + } + this.sign = other.sign; + this.invoker = other.invoker; + } + + public void clear() { + for(int i=0; i<3; ++i) { + expressionOperands[i] = null; + elementOperands[i] = null; + } + sign = null; + invoker = null; + } + + protected boolean isSecondPositionFilled() { + return invoker != null || (sign != null && any(1)); + } + + public ExpressionNode getExpressionAt(int index) { + return expressionOperands[index]; + } + + public ElementNode getElementAt(int index) { + return elementOperands[index]; + } + + public boolean isExpression(int index) { + return expressionOperands[index] != null; + } + + public boolean isElement(int index) { + return elementOperands[index] != null; + } + + public boolean any(int index) { + return expressionOperands[index] != null || elementOperands[index] != null; + } + + @Override + public void print(int retractNum, PrintStream out) { + if(invoker != null) { + printAt(0, retractNum, out); + invoker.print(retractNum, out); + + } else if(sign == null) { + printAt(0, retractNum, out); + + } else { + int num = 0; + for(int i=0; i<3; ++i) { + if(any(i)) { + num ++; + } + } + if(num == 3) { + printAt(0, retractNum, out); + out.print(" ? "); + printAt(1, retractNum, out); + out.print(" : "); + printAt(2, retractNum, out); + } + else if(num == 2) { + printAt(0, retractNum, out); + out.print(" "); + out.print(sign); + out.print(" "); + printAt(1, retractNum, out); + } + else { + out.print(sign); + out.print(" "); + printAt(0, retractNum, out); + } + } + } + + private void printAt(int index, int retractNum, PrintStream out) { + if(isElement(index)) { + elementOperands[index].print(retractNum, out); + } else { + out.print("("); + expressionOperands[index].print(retractNum, out); + out.print(")"); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java index 58042b5..d8adba2 --- a/src/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/ForEachLoopNode.java @@ -1,28 +1,28 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.List; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class ForEachLoopNode extends AnalysisNode { - - public List beforeCommandList = null; - public List afterCommandList = null; - public ExpressionNode loopCondition; - public ChunkNode chunk; - - @Override - public void print(int retractNum, PrintStream out) { - out.print("for ("); - printParams(retractNum, out, beforeCommandList); - out.print("; "); - loopCondition.print(retractNum, out); - out.print("; "); - printParams(retractNum, out, afterCommandList); - out.print(") do\n"); - chunk.print(retractNum + 1, out); - printRetract(retractNum, out); - out.print("end"); - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.List; + +import com.taozeyu.taolan.analysis.AnalysisNode; + +public abstract class ForEachLoopNode extends AnalysisNode { + + public List beforeCommandList = null; + public List afterCommandList = null; + public ExpressionNode loopCondition; + public ChunkNode chunk; + + @Override + public void print(int retractNum, PrintStream out) { + out.print("for ("); + printParams(retractNum, out, beforeCommandList); + out.print("; "); + loopCondition.print(retractNum, out); + out.print("; "); + printParams(retractNum, out, afterCommandList); + out.print(") do\n"); + chunk.print(retractNum + 1, out); + printRetract(retractNum, out); + out.print("end"); + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/IfElseNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/IfElseNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/IfElseNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/IfElseNode.java index 665b3e3..36abbee --- a/src/com/taozeyu/taolan/analysis/node/IfElseNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/IfElseNode.java @@ -1,47 +1,47 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.LinkedList; -import java.util.List; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class IfElseNode extends AnalysisNode { - - public List conditionExpressionList = new LinkedList<>(); - public List conditionChuckList = new LinkedList<>(); - public ChunkNode elseChuck = null; - - protected void addExpression(ExpressionNode node) { - conditionExpressionList.add(node); - conditionChuckList.add(null); - } - - protected void addChunk(ChunkNode node) { - conditionChuckList.set(conditionChuckList.size() - 1, node); - } - - @Override - public void print(int retractNum, PrintStream out) { - for(int i=0; i conditionExpressionList = new LinkedList<>(); + public List conditionChuckList = new LinkedList<>(); + public ChunkNode elseChuck = null; + + protected void addExpression(ExpressionNode node) { + conditionExpressionList.add(node); + conditionChuckList.add(null); + } + + protected void addChunk(ChunkNode node) { + conditionChuckList.set(conditionChuckList.size() - 1, node); + } + + @Override + public void print(int retractNum, PrintStream out) { + for(int i=0; i paramList = new LinkedList<>(); - public LambdaNode lambda = null; - - @Override - public void print(int retractNum, PrintStream out) { - out.print("{"); - printParams(retractNum, out, paramList); - out.print("}"); - if(lambda != null) { - lambda.print(retractNum, out); - } - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; + +import com.taozeyu.taolan.analysis.AnalysisNode; + +public abstract class InvokerNode extends AnalysisNode { + + public List paramList = new LinkedList<>(); + public LambdaNode lambda = null; + + @Override + public void print(int retractNum, PrintStream out) { + out.print("{"); + printParams(retractNum, out, paramList); + out.print("}"); + if(lambda != null) { + lambda.print(retractNum, out); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/LambdaNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/LambdaNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/LambdaNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/LambdaNode.java index ee8c6c9..41b7bfa --- a/src/com/taozeyu/taolan/analysis/node/LambdaNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/LambdaNode.java @@ -1,27 +1,27 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class LambdaNode extends AnalysisNode { - - public List paramNameList = new LinkedList<>(); - public ChunkNode chunk; - - @Override - public void print(int retractNum, PrintStream out) { - out.print(" do("); - printParams(retractNum, out, paramNameList); - out.print(")\n"); - if(chunk != null) { - chunk.print(retractNum + 1, out); - } - printRetract(retractNum, out); - out.print("end"); - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import com.taozeyu.taolan.analysis.AnalysisNode; + +public abstract class LambdaNode extends AnalysisNode { + + public List paramNameList = new LinkedList<>(); + public ChunkNode chunk; + + @Override + public void print(int retractNum, PrintStream out) { + out.print(" do("); + printParams(retractNum, out, paramNameList); + out.print(")\n"); + if(chunk != null) { + chunk.print(retractNum + 1, out); + } + printRetract(retractNum, out); + out.print("end"); + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/LoopChunkNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/LoopChunkNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/LoopChunkNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/LoopChunkNode.java index df82b15..e90b286 --- a/src/com/taozeyu/taolan/analysis/node/LoopChunkNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/LoopChunkNode.java @@ -1,37 +1,37 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; - - -public abstract class LoopChunkNode extends AnalysisNode { - - public ExpressionNode condition; - public boolean isWhile; - public ChunkNode chunk; - - @Override - public void print(int retractNum, PrintStream out) { - if(isWhile) { - out.print("while "); - condition.print(retractNum, out); - out.print(" do\n"); - if(chunk != null) { - chunk.print(retractNum + 1, out); - } - printRetract(retractNum, out); - out.print("end"); - } - else { - out.print("begin"); - out.print("\n"); - if(chunk != null) { - chunk.print(retractNum + 1, out); - } - printRetract(retractNum, out); - out.print("until "); - condition.print(retractNum, out); - } - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; + + +public abstract class LoopChunkNode extends AnalysisNode { + + public ExpressionNode condition; + public boolean isWhile; + public ChunkNode chunk; + + @Override + public void print(int retractNum, PrintStream out) { + if(isWhile) { + out.print("while "); + condition.print(retractNum, out); + out.print(" do\n"); + if(chunk != null) { + chunk.print(retractNum + 1, out); + } + printRetract(retractNum, out); + out.print("end"); + } + else { + out.print("begin"); + out.print("\n"); + if(chunk != null) { + chunk.print(retractNum + 1, out); + } + printRetract(retractNum, out); + out.print("until "); + condition.print(retractNum, out); + } + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/OperateNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/OperateNode.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/analysis/node/OperateNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/OperateNode.java index 6d0ed9e..347e318 --- a/src/com/taozeyu/taolan/analysis/node/OperateNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/OperateNode.java @@ -1,20 +1,20 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class OperateNode extends AnalysisNode { - - public ExpressionNode expression; - public WhenNode condition; - - @Override - public void print(int retractNum, PrintStream out) { - expression.print(retractNum, out); - if(condition != null) { - condition.print(retractNum, out); - } - } - -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; + +public abstract class OperateNode extends AnalysisNode { + + public ExpressionNode expression; + public WhenNode condition; + + @Override + public void print(int retractNum, PrintStream out) { + expression.print(retractNum, out); + if(condition != null) { + condition.print(retractNum, out); + } + } + +} diff --git a/src/com/taozeyu/taolan/analysis/node/StartChunkNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/StartChunkNode.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/analysis/node/StartChunkNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/StartChunkNode.java index 77c7188..9f00f5c --- a/src/com/taozeyu/taolan/analysis/node/StartChunkNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/StartChunkNode.java @@ -1,15 +1,15 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class StartChunkNode extends AnalysisNode { - - public ChunkNode chunk; - - @Override - public void print(int retractNum, PrintStream out) { - chunk.print(retractNum, out); - } -} +package com.taozeyu.taolan.analysis.node; + +import java.io.PrintStream; + +import com.taozeyu.taolan.analysis.AnalysisNode; + +public abstract class StartChunkNode extends AnalysisNode { + + public ChunkNode chunk; + + @Override + public void print(int retractNum, PrintStream out) { + chunk.print(retractNum, out); + } +} diff --git a/src/com/taozeyu/taolan/analysis/node/TryCatchNode.java b/src/main/java/com/taozeyu/taolan/analysis/node/TryCatchNode.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/analysis/node/TryCatchNode.java rename to src/main/java/com/taozeyu/taolan/analysis/node/TryCatchNode.java index f5e7f0e..c1e19db --- a/src/com/taozeyu/taolan/analysis/node/TryCatchNode.java +++ b/src/main/java/com/taozeyu/taolan/analysis/node/TryCatchNode.java @@ -1,59 +1,59 @@ -package com.taozeyu.taolan.analysis.node; - -import java.io.PrintStream; -import java.util.LinkedList; -import java.util.List; - -import com.taozeyu.taolan.analysis.AnalysisNode; - -public abstract class TryCatchNode extends AnalysisNode { - - public ChunkNode tryChunk; - public ChunkNode finallyChunk = null; - public List errorNameList = new LinkedList<>(); - public List typeList = new LinkedList<>(); - public List catchChunkList = new LinkedList<>(); - - protected void addErrorName(String errorName) { - errorNameList.add(errorName); - typeList.add(null); - catchChunkList.add(null); - } - - protected void addErrorType(ExpressionNode type) { - typeList.set(typeList.size() - 1, type); - } - - protected void addChunk(ChunkNode chunk) { - catchChunkList.set(catchChunkList.size() - 1, chunk); - } - - @Override - public void print(int retractNum, PrintStream out) { - if(tryChunk != null) { - out.print("try\n"); - tryChunk.print(retractNum + 1, out); - } - for(int i=0; i errorNameList = new LinkedList<>(); + public List typeList = new LinkedList<>(); + public List catchChunkList = new LinkedList<>(); + + protected void addErrorName(String errorName) { + errorNameList.add(errorName); + typeList.add(null); + catchChunkList.add(null); + } + + protected void addErrorType(ExpressionNode type) { + typeList.set(typeList.size() - 1, type); + } + + protected void addChunk(ChunkNode chunk) { + catchChunkList.set(catchChunkList.size() - 1, chunk); + } + + @Override + public void print(int retractNum, PrintStream out) { + if(tryChunk != null) { + out.print("try\n"); + tryChunk.print(retractNum + 1, out); + } + for(int i=0; i placeholderRegisterList; - Map functionIDMapper; - - VariableRecorder variableRecorder; - FunctionRecorder functionRecorder; - - CodeChunk codeChunk; - JumpStack jumpStack; - - LocalVariablePool variablePool; - PositionPlaceholder positionPlaceholder; - - private ChunkContext(ChunkContext parent) { - functionStartIndex = parent.functionStartIndex; - placeholderRegisterList = parent.placeholderRegisterList; - functionRecorder = parent.functionRecorder; - functionIDMapper = parent.functionIDMapper; - } - - ChunkContext(int _functionStartIndex) { - functionStartIndex = _functionStartIndex; - placeholderRegisterList = new LinkedList<>(); - functionIDMapper = new HashMap<>(); - variableRecorder = new VariableRecorder(); - functionRecorder = new FunctionRecorder(); - codeChunk = new CodeChunk(); - jumpStack = new JumpStack(); - variablePool = new LocalVariablePool(); - positionPlaceholder = new PositionPlaceholder(); - } - - ChunkContext link() { - ChunkContext context = new ChunkContext(this); - context.codeChunk = this.codeChunk; - context.variablePool = this.variablePool; - context.positionPlaceholder = this.positionPlaceholder; - context.jumpStack = this.jumpStack; - context.variableRecorder = this.variableRecorder.link(); - return context; - } - - ChunkContext extend() { - ChunkContext context = new ChunkContext(this); - context.codeChunk = new CodeChunk(); - context.variablePool = new LocalVariablePool(); - context.positionPlaceholder = new PositionPlaceholder(); - context.jumpStack = new JumpStack(); - context.variableRecorder = new VariableRecorder(); - return context; - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +class ChunkContext { + + int functionStartIndex; + + List placeholderRegisterList; + Map functionIDMapper; + + VariableRecorder variableRecorder; + FunctionRecorder functionRecorder; + + CodeChunk codeChunk; + JumpStack jumpStack; + + LocalVariablePool variablePool; + PositionPlaceholder positionPlaceholder; + + private ChunkContext(ChunkContext parent) { + functionStartIndex = parent.functionStartIndex; + placeholderRegisterList = parent.placeholderRegisterList; + functionRecorder = parent.functionRecorder; + functionIDMapper = parent.functionIDMapper; + } + + ChunkContext(int _functionStartIndex) { + functionStartIndex = _functionStartIndex; + placeholderRegisterList = new LinkedList<>(); + functionIDMapper = new HashMap<>(); + variableRecorder = new VariableRecorder(); + functionRecorder = new FunctionRecorder(); + codeChunk = new CodeChunk(); + jumpStack = new JumpStack(); + variablePool = new LocalVariablePool(); + positionPlaceholder = new PositionPlaceholder(); + } + + ChunkContext link() { + ChunkContext context = new ChunkContext(this); + context.codeChunk = this.codeChunk; + context.variablePool = this.variablePool; + context.positionPlaceholder = this.positionPlaceholder; + context.jumpStack = this.jumpStack; + context.variableRecorder = this.variableRecorder.link(); + return context; + } + + ChunkContext extend() { + ChunkContext context = new ChunkContext(this); + context.codeChunk = new CodeChunk(); + context.variablePool = new LocalVariablePool(); + context.positionPlaceholder = new PositionPlaceholder(); + context.jumpStack = new JumpStack(); + context.variableRecorder = new VariableRecorder(); + return context; + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/CodeChunk.java b/src/main/java/com/taozeyu/taolan/intermediatecode/CodeChunk.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/intermediatecode/CodeChunk.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/CodeChunk.java index 494e632..8a6aff6 --- a/src/com/taozeyu/taolan/intermediatecode/CodeChunk.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/CodeChunk.java @@ -1,184 +1,184 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -public class CodeChunk implements Iterable{ - - private final List container = new ArrayList<>(); - - public Code getCodeByLine(int line) { - return container.get(line); - } - - @Override - public Iterator iterator() { - return container.iterator(); - } - - public enum Command { - Set, //私有变量->私有变量 - SetImmediate, //立即数->私有变量 - GetThis, //this->私有变量 - GetError, //error -> 私有变量 - Rel, //this变量->私有变量 - RelStatic, //constructor变量->私有变量 - Move, //私有变量->this变量 - MoveStatic, //私有变量->constructor变量 - - Add, Sub, Mul, Div, Mod, Insert, Range, - Gt, Gte, Lt, Lte, Equal, NotEqual, Match, - And, Or, Not, Xor, Opposite, - InstanceOf, Is, - - Jump, JumpWhen, JumpUnless, - PushTryBlock, PopTryBlock, JumpFinally, - Throw, Return, - - Push, Pop, Take, Clear, - Invoke, InvokeVirtual, InvokeLambda, - - DefFunction, - - NewArray, NewContainer, NewRegEx, - } - - public enum ImmediateType { - Integer, Number, Boolean, String, Null, - } - - public static class ImmediateNumber { - ImmediateType type; - int integerValue; - float numberValue; - boolean booleanValue; - String stringValue; - - @Override - public String toString() { - if(type == ImmediateType.Boolean) { - return String.valueOf(booleanValue); - } else if(type == ImmediateType.Integer) { - return String.valueOf(integerValue); - } else if(type == ImmediateType.Number) { - return String.valueOf(numberValue); - } else if(type == ImmediateType.String) { - return String.valueOf(stringValue); - } else { - return "NULL"; - } - } - - public ImmediateType getType() { - return type; - } - - public int getIntegerValue() { - return integerValue; - } - - public float getNumberValue() { - return numberValue; - } - - public boolean isBooleanValue() { - return booleanValue; - } - - public String getStringValue() { - return stringValue; - } - } - - public static class Code { - Command command; - int number1; - int number2; - int number3; - ImmediateNumber immediateNumber; - - @Override - public String toString() { - String str = String.format("%s %s, %s, %s", command, number1, number2, number3); - if(immediateNumber != null) { - if (immediateNumber.type == ImmediateType.String) { - str += " >> \"" + immediateNumber+"\""; - } else { - str += " >> " + immediateNumber; - } - } - return str; - } - - public Command getCommand() { - return command; - } - - public int getNumber1() { - return number1; - } - - public int getNumber2() { - return number2; - } - - public int getNumber3() { - return number3; - } - - public ImmediateNumber getImmediateNumber() { - return immediateNumber; - } - } - - int getCurrentPostion() { - return container.size(); - } - - void push(Command command, int number1, int number2, int number3, ImmediateNumber immediateNumber) { - Code code = new Code(); - code.command = command; - code.number1 = number1; - code.number2 = number2; - code.number3 = number3; - code.immediateNumber = immediateNumber; - container.add(code); - } - - void push(Command command, int number1, int number2, int number3) { - push(command, number1, number2, number3, null); - } - - void push(Command command, int number1, int number2) { - push(command, number1, number2, 0, null); - } - - void push(Command command, int number1) { - push(command, number1, 0, 0, null); - } - - void push(Command command) { - push(command, 0, 0, 0, null); - } - - void push(Command command, int number1, ImmediateNumber immediateNumber) { - push(command, number1, 0, 0, immediateNumber); - } - - void push(Code code) { - container.add(code); - } - - @Override - public String toString() { - String str = ""; - int lineNumber = 0; - for(Code code:container) { - str += lineNumber + "\t"; - str += code + "\n"; - lineNumber++; - } - return str; - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class CodeChunk implements Iterable{ + + private final List container = new ArrayList<>(); + + public Code getCodeByLine(int line) { + return container.get(line); + } + + @Override + public Iterator iterator() { + return container.iterator(); + } + + public enum Command { + Set, //私有变量->私有变量 + SetImmediate, //立即数->私有变量 + GetThis, //this->私有变量 + GetError, //error -> 私有变量 + Rel, //this变量->私有变量 + RelStatic, //constructor变量->私有变量 + Move, //私有变量->this变量 + MoveStatic, //私有变量->constructor变量 + + Add, Sub, Mul, Div, Mod, Insert, Range, + Gt, Gte, Lt, Lte, Equal, NotEqual, Match, + And, Or, Not, Xor, Opposite, + InstanceOf, Is, + + Jump, JumpWhen, JumpUnless, + PushTryBlock, PopTryBlock, JumpFinally, + Throw, Return, + + Push, Pop, Take, Clear, + Invoke, InvokeVirtual, InvokeLambda, + + DefFunction, + + NewArray, NewContainer, NewRegEx, + } + + public enum ImmediateType { + Integer, Number, Boolean, String, Null, + } + + public static class ImmediateNumber { + ImmediateType type; + int integerValue; + float numberValue; + boolean booleanValue; + String stringValue; + + @Override + public String toString() { + if(type == ImmediateType.Boolean) { + return String.valueOf(booleanValue); + } else if(type == ImmediateType.Integer) { + return String.valueOf(integerValue); + } else if(type == ImmediateType.Number) { + return String.valueOf(numberValue); + } else if(type == ImmediateType.String) { + return String.valueOf(stringValue); + } else { + return "NULL"; + } + } + + public ImmediateType getType() { + return type; + } + + public int getIntegerValue() { + return integerValue; + } + + public float getNumberValue() { + return numberValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public String getStringValue() { + return stringValue; + } + } + + public static class Code { + Command command; + int number1; + int number2; + int number3; + ImmediateNumber immediateNumber; + + @Override + public String toString() { + String str = String.format("%s %s, %s, %s", command, number1, number2, number3); + if(immediateNumber != null) { + if (immediateNumber.type == ImmediateType.String) { + str += " >> \"" + immediateNumber+"\""; + } else { + str += " >> " + immediateNumber; + } + } + return str; + } + + public Command getCommand() { + return command; + } + + public int getNumber1() { + return number1; + } + + public int getNumber2() { + return number2; + } + + public int getNumber3() { + return number3; + } + + public ImmediateNumber getImmediateNumber() { + return immediateNumber; + } + } + + int getCurrentPostion() { + return container.size(); + } + + void push(Command command, int number1, int number2, int number3, ImmediateNumber immediateNumber) { + Code code = new Code(); + code.command = command; + code.number1 = number1; + code.number2 = number2; + code.number3 = number3; + code.immediateNumber = immediateNumber; + container.add(code); + } + + void push(Command command, int number1, int number2, int number3) { + push(command, number1, number2, number3, null); + } + + void push(Command command, int number1, int number2) { + push(command, number1, number2, 0, null); + } + + void push(Command command, int number1) { + push(command, number1, 0, 0, null); + } + + void push(Command command) { + push(command, 0, 0, 0, null); + } + + void push(Command command, int number1, ImmediateNumber immediateNumber) { + push(command, number1, 0, 0, immediateNumber); + } + + void push(Code code) { + container.add(code); + } + + @Override + public String toString() { + String str = ""; + int lineNumber = 0; + for(Code code:container) { + str += lineNumber + "\t"; + str += code + "\n"; + lineNumber++; + } + return str; + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/CodeCreator.java b/src/main/java/com/taozeyu/taolan/intermediatecode/CodeCreator.java old mode 100755 new mode 100644 similarity index 98% rename from src/com/taozeyu/taolan/intermediatecode/CodeCreator.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/CodeCreator.java index d132ce5..8a01b83 --- a/src/com/taozeyu/taolan/intermediatecode/CodeCreator.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/CodeCreator.java @@ -1,255 +1,255 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.List; - -import com.taozeyu.taolan.analysis.AnalysisNode; -import com.taozeyu.taolan.analysis.node.ChunkNode; -import com.taozeyu.taolan.analysis.node.CommandNode; -import com.taozeyu.taolan.analysis.node.DefineFunctionNode; -import com.taozeyu.taolan.analysis.node.DefineVariableNode; -import com.taozeyu.taolan.analysis.node.ExpressionNode; -import com.taozeyu.taolan.analysis.node.ForEachLoopNode; -import com.taozeyu.taolan.analysis.node.IfElseNode; -import com.taozeyu.taolan.analysis.node.LoopChunkNode; -import com.taozeyu.taolan.analysis.node.OperateNode; -import com.taozeyu.taolan.analysis.node.TryCatchNode; -import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; -import com.taozeyu.taolan.intermediatecode.PlaceholderReplacement.RegisterNode; - -class CodeCreator { - - final static CodeCreator instance = new CodeCreator(); - - void handleChunk(ChunkNode chunk, ChunkContext context) throws IntermediateCodeExpression { - if(chunk != null) { - handleAnalysisNodeList(chunk.lineList, chunk, context); - RegisterNode node = PlaceholderReplacement.instance.register(context.codeChunk, context.positionPlaceholder); - context.placeholderRegisterList.add(node); - } - } - - private void handleAnalysisNodeList(List list, ChunkNode chunk, ChunkContext context) throws IntermediateCodeExpression { - for(AnalysisNode node:list) { - if(node instanceof CommandNode) { - handleCommand((CommandNode) node, context); - - } else if(node instanceof OperateNode) { - handleOperate((OperateNode) node, context); - - } else if(node instanceof ExpressionNode) { - handleExpression((ExpressionNode) node, context); - - } else if(node instanceof DefineVariableNode) { - handleDefineVariable((DefineVariableNode) node, context); - - } else if(node instanceof DefineFunctionNode) { - handleDefineFunction((DefineFunctionNode) node, context); - - } else if(node instanceof IfElseNode) { - handleIfElse((IfElseNode) node, context); - - } else if(node instanceof LoopChunkNode) { - handleLoop((LoopChunkNode) node, context); - - } else if(node instanceof ForEachLoopNode) { - handleForLoop((ForEachLoopNode) node, chunk, context); - - } else if(node instanceof TryCatchNode) { - handleTryCatch((TryCatchNode) node, context); - - } else { - throw new RuntimeException("unknown node type " + node.getClass().getSimpleName()); - } - } - } - - private void handleCommand(CommandNode command, ChunkContext context) throws IntermediateCodeExpression { - if(command.condition != null) { - int endHolder = context.positionPlaceholder.createPosition(); - int conditionVar = ExpressionGenerator.instance.createExpression(command.condition.condition, context); - context.codeChunk.push(Command.JumpUnless, endHolder, conditionVar); - generateCommandCodes(command, context); - context.positionPlaceholder.setPosition(endHolder, context.codeChunk.getCurrentPostion()); - context.variablePool.freeIndex(conditionVar); - } else { - generateCommandCodes(command, context); - } - } - - private void generateCommandCodes(CommandNode commandNode, ChunkContext context) throws IntermediateCodeExpression { - Command command = null; - if("return".equals(commandNode.command)) { - command = Command.Return; - } else if("throw".equals(commandNode.command)) { - command = Command.Throw; - } - if(command != null) { - int expression = -1; - if(commandNode.expression != null) { - expression = ExpressionGenerator.instance.createExpression(commandNode.expression, context); - } - context.codeChunk.push(command, expression); - context.variablePool.freeIndex(expression); - - } else { - if(context.jumpStack.isNotInLoop()) { - throw new IntermediateCodeExpression("not in loop."); - } - if("break".equals(commandNode.command)) { - context.codeChunk.push(Command.Jump, context.jumpStack.getCurrentBreakLocation()); - } else if("continue".equals(commandNode.command)) { - context.codeChunk.push(Command.Jump, context.jumpStack.getCurrentContinueLocation()); - } else { - throw new IntermediateCodeExpression("unknown command "+ commandNode.command); - } - } - } - - private void handleOperate(OperateNode operate, ChunkContext context) throws IntermediateCodeExpression { - int expressionVar; - if(operate.condition != null) { - int conditionVar = ExpressionGenerator.instance.createExpression(operate.condition.condition, context); - int nextHolder = context.positionPlaceholder.createPosition(); - context.codeChunk.push(Command.JumpUnless, nextHolder, conditionVar); - context.variablePool.freeIndex(conditionVar); - expressionVar = ExpressionGenerator.instance.createExpression(operate.expression, context); - context.positionPlaceholder.setPosition(nextHolder, context.codeChunk.getCurrentPostion()); - } else { - expressionVar = ExpressionGenerator.instance.createExpression(operate.expression, context); - } - context.variablePool.freeIndex(expressionVar); - } - - private void handleExpression(ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { - int expressionVar = ExpressionGenerator.instance.createExpression(expression, context); - context.variablePool.freeIndex(expressionVar); - } - - private void handleDefineVariable(DefineVariableNode defVar, ChunkContext context) throws IntermediateCodeExpression { - String name = defVar.variableName; - int varIndex = VariableGenerator.instance.defVariable(name, context); - if(defVar.initValue != null) { - ExpressionGenerator.instance.createExpression(varIndex, defVar.initValue, context); - } - } - - private void handleDefineFunction(DefineFunctionNode defFun, ChunkContext context) throws IntermediateCodeExpression { - FunctionGenerator.instance.createFunction(defFun, context); - } - - private void handleIfElse(IfElseNode ifelse, ChunkContext context) throws IntermediateCodeExpression { - int endHolder = context.positionPlaceholder.createPosition(); - for(int i=0; i list, ChunkNode chunk, ChunkContext context) throws IntermediateCodeExpression { + for(AnalysisNode node:list) { + if(node instanceof CommandNode) { + handleCommand((CommandNode) node, context); + + } else if(node instanceof OperateNode) { + handleOperate((OperateNode) node, context); + + } else if(node instanceof ExpressionNode) { + handleExpression((ExpressionNode) node, context); + + } else if(node instanceof DefineVariableNode) { + handleDefineVariable((DefineVariableNode) node, context); + + } else if(node instanceof DefineFunctionNode) { + handleDefineFunction((DefineFunctionNode) node, context); + + } else if(node instanceof IfElseNode) { + handleIfElse((IfElseNode) node, context); + + } else if(node instanceof LoopChunkNode) { + handleLoop((LoopChunkNode) node, context); + + } else if(node instanceof ForEachLoopNode) { + handleForLoop((ForEachLoopNode) node, chunk, context); + + } else if(node instanceof TryCatchNode) { + handleTryCatch((TryCatchNode) node, context); + + } else { + throw new RuntimeException("unknown node type " + node.getClass().getSimpleName()); + } + } + } + + private void handleCommand(CommandNode command, ChunkContext context) throws IntermediateCodeExpression { + if(command.condition != null) { + int endHolder = context.positionPlaceholder.createPosition(); + int conditionVar = ExpressionGenerator.instance.createExpression(command.condition.condition, context); + context.codeChunk.push(Command.JumpUnless, endHolder, conditionVar); + generateCommandCodes(command, context); + context.positionPlaceholder.setPosition(endHolder, context.codeChunk.getCurrentPostion()); + context.variablePool.freeIndex(conditionVar); + } else { + generateCommandCodes(command, context); + } + } + + private void generateCommandCodes(CommandNode commandNode, ChunkContext context) throws IntermediateCodeExpression { + Command command = null; + if("return".equals(commandNode.command)) { + command = Command.Return; + } else if("throw".equals(commandNode.command)) { + command = Command.Throw; + } + if(command != null) { + int expression = -1; + if(commandNode.expression != null) { + expression = ExpressionGenerator.instance.createExpression(commandNode.expression, context); + } + context.codeChunk.push(command, expression); + context.variablePool.freeIndex(expression); + + } else { + if(context.jumpStack.isNotInLoop()) { + throw new IntermediateCodeExpression("not in loop."); + } + if("break".equals(commandNode.command)) { + context.codeChunk.push(Command.Jump, context.jumpStack.getCurrentBreakLocation()); + } else if("continue".equals(commandNode.command)) { + context.codeChunk.push(Command.Jump, context.jumpStack.getCurrentContinueLocation()); + } else { + throw new IntermediateCodeExpression("unknown command "+ commandNode.command); + } + } + } + + private void handleOperate(OperateNode operate, ChunkContext context) throws IntermediateCodeExpression { + int expressionVar; + if(operate.condition != null) { + int conditionVar = ExpressionGenerator.instance.createExpression(operate.condition.condition, context); + int nextHolder = context.positionPlaceholder.createPosition(); + context.codeChunk.push(Command.JumpUnless, nextHolder, conditionVar); + context.variablePool.freeIndex(conditionVar); + expressionVar = ExpressionGenerator.instance.createExpression(operate.expression, context); + context.positionPlaceholder.setPosition(nextHolder, context.codeChunk.getCurrentPostion()); + } else { + expressionVar = ExpressionGenerator.instance.createExpression(operate.expression, context); + } + context.variablePool.freeIndex(expressionVar); + } + + private void handleExpression(ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + int expressionVar = ExpressionGenerator.instance.createExpression(expression, context); + context.variablePool.freeIndex(expressionVar); + } + + private void handleDefineVariable(DefineVariableNode defVar, ChunkContext context) throws IntermediateCodeExpression { + String name = defVar.variableName; + int varIndex = VariableGenerator.instance.defVariable(name, context); + if(defVar.initValue != null) { + ExpressionGenerator.instance.createExpression(varIndex, defVar.initValue, context); + } + } + + private void handleDefineFunction(DefineFunctionNode defFun, ChunkContext context) throws IntermediateCodeExpression { + FunctionGenerator.instance.createFunction(defFun, context); + } + + private void handleIfElse(IfElseNode ifelse, ChunkContext context) throws IntermediateCodeExpression { + int endHolder = context.positionPlaceholder.createPosition(); + for(int i=0; i".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Gt, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("<".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Lt, num1, num2); - context.variablePool.freeIndex(num2); - - } else if(">=".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Gte, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("<=".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Lte, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("==".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Equal, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("!=".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.NotEqual, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("=~".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Match, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("<<".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Insert, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("..".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Range, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("!".equals(expression.sign)) { - createChildExpressionAt(var, expression, 0, context); - context.codeChunk.push(Command.Not, var); - - } else if("&&".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.And, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("||".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Or, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("^".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Xor, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("instanceof".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.InstanceOf, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("is".equals(expression.sign)) { - num1 = var; - num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(Command.Is, num1, num2); - context.variablePool.freeIndex(num2); - - } else if("=".equals(expression.sign)) { - createSetter(var, expression, context); - - } else if("+=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Add, context); - - } else if("-=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Sub, context); - - } else if("*=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Mul, context); - - } else if("/=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Div, context); - - } else if("%=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Mod, context); - - } else if("&&=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.And, context); - - } else if("||=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Or, context); - - } else if("^=".equals(expression.sign)) { - createOperatorAndSetter(var, expression, Command.Xor, context); - - } else if(".".equals(expression.sign)) { - int target = context.variablePool.createIndex(); - createChildExpressionAt(target, expression, 0, context); - String funName = expression.getElementAt(1).value; - FunctionGenerator.instance.createInvoker(target, var, funName, null, null, context); - - } else if("[".equals(expression.sign)) { - int indexVar = context.variablePool.createIndex(); - int targetVar = context.variablePool.createIndex(); - createChildExpressionAt(targetVar, expression, 0, context); - createChildExpressionAt(indexVar, expression, 1, context); - - ImmediateNumber immediateNumber = new ImmediateNumber(); - immediateNumber.type = ImmediateType.String; - immediateNumber.stringValue = "get"; - context.codeChunk.push(Command.Push, indexVar); - context.codeChunk.push(Command.InvokeVirtual, targetVar, 1, -1, immediateNumber); - context.codeChunk.push(Command.Pop, var); - - context.variablePool.freeIndex(targetVar); - context.variablePool.freeIndex(indexVar); - - } else if(expression.isElement(0)){ - createElement(var, expression.getElementAt(0), context); - } - } - - private void createOperatorAndSetter(int var, ExpressionNode expression, Command command, ChunkContext context) throws IntermediateCodeExpression { - int num1 = var; - int num2 = context.variablePool.createIndex(); - createChildExpressionAt(num1, expression, 0, context); - createChildExpressionAt(num2, expression, 1, context); - context.codeChunk.push(command, num1, num2); - context.variablePool.freeIndex(num2); - createSetterWithInitSet(var, num1, expression, context); - } - - private void createSetter(int resultVar, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { - if(expression.isElement(0)) { - int setVar = context.variablePool.createIndex(); - createChildExpressionAt(setVar, expression, 1, context); - createSetterWithInitSet(resultVar, setVar, expression, context); - context.variablePool.freeIndex(setVar); - } else { - ExpressionNode target = expression.getExpressionAt(0); - if("[".equals(target.sign)) { - int indexVar = context.variablePool.createIndex(); - int targetVar = context.variablePool.createIndex(); - createChildExpressionAt(targetVar, target, 0, context); - createChildExpressionAt(indexVar, target, 1, context); - createChildExpressionAt(resultVar, expression, 1, context); - - ImmediateNumber immediateNumber = new ImmediateNumber(); - immediateNumber.type = ImmediateType.String; - immediateNumber.stringValue = "set"; - context.codeChunk.push(Command.Push, indexVar); - context.codeChunk.push(Command.Push, resultVar); - context.codeChunk.push(Command.InvokeVirtual, targetVar, 2, -1, immediateNumber); - context.codeChunk.push(Command.Pop, resultVar); - - context.variablePool.freeIndex(targetVar); - context.variablePool.freeIndex(indexVar); - } else { - throw new IntermediateCodeExpression("unknown sign "+ target.sign); - } - } - } - - private void createSetterWithInitSet(int resultVar, int setVar, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { - if(expression.isElement(0)) { - - ElementNode element = expression.getElementAt(0); - String variableName = element.value; - if (element.isLocalVariable()) { - if (context.variableRecorder.contains(variableName)) { - int localVariableIndex = context.variableRecorder.getVarIndex(variableName); - context.codeChunk.push(Command.Set, localVariableIndex, setVar); - context.codeChunk.push(Command.Set, resultVar, localVariableIndex); - } else { - context.codeChunk.push(Command.GetThis, resultVar); - context.codeChunk.push(Command.Push, setVar); - FunctionGenerator.instance.invokeByName(resultVar, 1, resultVar, -1, variableName+"=", context); - } - } else if (element.isAttributeVariable()) { - VariableGenerator.instance.setAttributeVariableValue(resultVar, setVar, element, context); - } - } else { - if (true) throw new RuntimeException("not implements"); - } - } - - private void createChildExpressionAt(int var, ExpressionNode parent, int index, ChunkContext context) throws IntermediateCodeExpression { - if(parent.isElement(index)) { - createElement(var, parent.getElementAt(index), context); - } else { - createExpression(var, parent.getExpressionAt(index), context); - } - } - - private void createElement(int var, ElementNode element, ChunkContext context) throws IntermediateCodeExpression { - if(element.type == ElementType.Variable) { - String variableName = element.value; - if (element.isLocalVariable()) { - if (context.variableRecorder.contains(variableName)) { - int localVariableIndex = context.variableRecorder.getVarIndex(variableName); - context.codeChunk.push(Command.Set, var, localVariableIndex); - } else { - context.codeChunk.push(Command.GetThis, var); - FunctionGenerator.instance.invokeByName(var, 0, var, -1, variableName, context); - } - } else if (element.isAttributeVariable()) { - VariableGenerator.instance.getAttributesValue(var, element, context); - } - } else if(element.type == ElementType.RegEx) { - int paramVar = context.variablePool.createIndex(); - ImmediateNumber immediateNumber = new ImmediateNumber(); - immediateNumber.type = ImmediateType.String; - immediateNumber.stringValue = element.value; - context.codeChunk.push(Command.SetImmediate, paramVar, immediateNumber); - context.codeChunk.push(Command.Push, paramVar); - context.codeChunk.push(Command.NewRegEx); - context.variablePool.freeIndex(paramVar); - - } else if(element.type == ElementType.This) { - context.codeChunk.push(Command.GetThis, var); - - } else if(element.type == ElementType.Array) { - ArrayNode array = element.array; - for(ExpressionNode expression:array.content) { - int paramVar = createExpression(expression, context); - context.codeChunk.push(Command.Push, paramVar); - context.variablePool.freeIndex(paramVar); - } - context.codeChunk.push(Command.NewArray, var, array.content.size()); - - } else if(element.type == ElementType.Container) { - ContainerNode container = element.container; - for(Entry e:container.content.entrySet()) { - String key = e.getKey(); - ExpressionNode value = e.getValue(); - ImmediateNumber immediateNumber = new ImmediateNumber(); - - int keyVar = context.variablePool.createIndex(); - immediateNumber.type = ImmediateType.String; - immediateNumber.stringValue = key; - context.codeChunk.push(Command.SetImmediate, keyVar, immediateNumber); - context.codeChunk.push(Command.Push, keyVar); - context.variablePool.freeIndex(keyVar); - - int valueVar = createExpression(value, context); - context.codeChunk.push(Command.Push, valueVar); - context.variablePool.freeIndex(valueVar); - } - context.codeChunk.push(Command.NewContainer, var, container.content.size()); - - } else { - ImmediateNumber immediateNumber = new ImmediateNumber(); - if(element.type == ElementType.Null) { - immediateNumber.type = ImmediateType.Null; - - } else if(element.type == ElementType.Integer) { - immediateNumber.type = ImmediateType.Integer; - immediateNumber.integerValue = Integer.valueOf(element.value); - - } else if(element.type == ElementType.Number) { - immediateNumber.type = ImmediateType.Number; - immediateNumber.numberValue = Float.valueOf(element.value); - - } else if(element.type == ElementType.String) { - immediateNumber.type = ImmediateType.String; - immediateNumber.stringValue = element.value; - - } else if (element.type == ElementType.Boolean) { - immediateNumber.type = ImmediateType.Boolean; - immediateNumber.booleanValue = element.value.equals("true"); - } - context.codeChunk.push(Command.SetImmediate, var, immediateNumber); - } - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.ArrayList; +import java.util.Map.Entry; + +import com.taozeyu.taolan.analysis.node.ArrayNode; +import com.taozeyu.taolan.analysis.node.ContainerNode; +import com.taozeyu.taolan.analysis.node.ElementNode; +import com.taozeyu.taolan.analysis.node.ElementNode.ElementType; +import com.taozeyu.taolan.analysis.node.ExpressionNode; +import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; +import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateNumber; +import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateType; + +class ExpressionGenerator { + + final static ExpressionGenerator instance = new ExpressionGenerator(); + + int createExpression(ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + int var = context.variablePool.createIndex(); + createExpression(var, expression, context); + return var; + } + + int createChildExpressionAt(ExpressionNode parent, int index, ChunkContext context) throws IntermediateCodeExpression { + int var = context.variablePool.createIndex(); + createChildExpressionAt(var, parent, index, context); + return var; + } + + void createExpression(int var, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + if(expression.invoker != null) { + FunctionGenerator.instance.createInvoker(var, expression, context); + } else if("?:".equals(expression.sign)) { + createConditionExpression(var, expression, context); + } else { + createSingleOrDoubleOperator(var, expression, context); + } + } + + private void createConditionExpression(int var, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + createChildExpressionAt(var, expression, 0, context); + int leftExpressionHolder = context.positionPlaceholder.createPosition(); + int endHolder = context.positionPlaceholder.createPosition(); + context.codeChunk.push(Command.JumpWhen, leftExpressionHolder, var); + createChildExpressionAt(var, expression, 2, context); + context.codeChunk.push(Command.Jump, endHolder); + context.positionPlaceholder.setPosition(leftExpressionHolder, context.codeChunk.getCurrentPostion()); + createChildExpressionAt(var, expression, 1, context); + context.positionPlaceholder.setPosition(endHolder, context.codeChunk.getCurrentPostion()); + } + + private void createSingleOrDoubleOperator(int var, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + int num1, num2; + if("+".equals(expression.sign)) { + if(expression.any(1)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Add, num1, num2); + context.variablePool.freeIndex(num2); + } else { + createChildExpressionAt(var, expression, 0, context); + } + } else if("-".equals(expression.sign)) { + if(expression.any(1)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Sub, num1, num2); + context.variablePool.freeIndex(num2); + } else { + createChildExpressionAt(var, expression, 0, context); + context.codeChunk.push(Command.Opposite, var); + } + } else if("*".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Mul, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("/".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Div, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("%".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Mod, num1, num2); + context.variablePool.freeIndex(num2); + + } else if(">".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Gt, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("<".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Lt, num1, num2); + context.variablePool.freeIndex(num2); + + } else if(">=".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Gte, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("<=".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Lte, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("==".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Equal, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("!=".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.NotEqual, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("=~".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Match, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("<<".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Insert, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("..".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Range, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("!".equals(expression.sign)) { + createChildExpressionAt(var, expression, 0, context); + context.codeChunk.push(Command.Not, var); + + } else if("&&".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.And, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("||".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Or, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("^".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Xor, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("instanceof".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.InstanceOf, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("is".equals(expression.sign)) { + num1 = var; + num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(Command.Is, num1, num2); + context.variablePool.freeIndex(num2); + + } else if("=".equals(expression.sign)) { + createSetter(var, expression, context); + + } else if("+=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Add, context); + + } else if("-=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Sub, context); + + } else if("*=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Mul, context); + + } else if("/=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Div, context); + + } else if("%=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Mod, context); + + } else if("&&=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.And, context); + + } else if("||=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Or, context); + + } else if("^=".equals(expression.sign)) { + createOperatorAndSetter(var, expression, Command.Xor, context); + + } else if(".".equals(expression.sign)) { + int target = context.variablePool.createIndex(); + createChildExpressionAt(target, expression, 0, context); + String funName = expression.getElementAt(1).value; + FunctionGenerator.instance.createInvoker(target, var, funName, null, null, context); + + } else if("[".equals(expression.sign)) { + int indexVar = context.variablePool.createIndex(); + int targetVar = context.variablePool.createIndex(); + createChildExpressionAt(targetVar, expression, 0, context); + createChildExpressionAt(indexVar, expression, 1, context); + + ImmediateNumber immediateNumber = new ImmediateNumber(); + immediateNumber.type = ImmediateType.String; + immediateNumber.stringValue = "get"; + context.codeChunk.push(Command.Push, indexVar); + context.codeChunk.push(Command.InvokeVirtual, targetVar, 1, -1, immediateNumber); + context.codeChunk.push(Command.Pop, var); + + context.variablePool.freeIndex(targetVar); + context.variablePool.freeIndex(indexVar); + + } else if(expression.isElement(0)){ + createElement(var, expression.getElementAt(0), context); + } + } + + private void createOperatorAndSetter(int var, ExpressionNode expression, Command command, ChunkContext context) throws IntermediateCodeExpression { + int num1 = var; + int num2 = context.variablePool.createIndex(); + createChildExpressionAt(num1, expression, 0, context); + createChildExpressionAt(num2, expression, 1, context); + context.codeChunk.push(command, num1, num2); + context.variablePool.freeIndex(num2); + createSetterWithInitSet(var, num1, expression, context); + } + + private void createSetter(int resultVar, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + if(expression.isElement(0)) { + int setVar = context.variablePool.createIndex(); + createChildExpressionAt(setVar, expression, 1, context); + createSetterWithInitSet(resultVar, setVar, expression, context); + context.variablePool.freeIndex(setVar); + } else { + ExpressionNode target = expression.getExpressionAt(0); + if("[".equals(target.sign)) { + int indexVar = context.variablePool.createIndex(); + int targetVar = context.variablePool.createIndex(); + createChildExpressionAt(targetVar, target, 0, context); + createChildExpressionAt(indexVar, target, 1, context); + createChildExpressionAt(resultVar, expression, 1, context); + + ImmediateNumber immediateNumber = new ImmediateNumber(); + immediateNumber.type = ImmediateType.String; + immediateNumber.stringValue = "set"; + context.codeChunk.push(Command.Push, indexVar); + context.codeChunk.push(Command.Push, resultVar); + context.codeChunk.push(Command.InvokeVirtual, targetVar, 2, -1, immediateNumber); + context.codeChunk.push(Command.Pop, resultVar); + + context.variablePool.freeIndex(targetVar); + context.variablePool.freeIndex(indexVar); + } else { + throw new IntermediateCodeExpression("unknown sign "+ target.sign); + } + } + } + + private void createSetterWithInitSet(int resultVar, int setVar, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + if(expression.isElement(0)) { + + ElementNode element = expression.getElementAt(0); + String variableName = element.value; + if (element.isLocalVariable()) { + if (context.variableRecorder.contains(variableName)) { + int localVariableIndex = context.variableRecorder.getVarIndex(variableName); + context.codeChunk.push(Command.Set, localVariableIndex, setVar); + context.codeChunk.push(Command.Set, resultVar, localVariableIndex); + } else { + context.codeChunk.push(Command.GetThis, resultVar); + context.codeChunk.push(Command.Push, setVar); + FunctionGenerator.instance.invokeByName(resultVar, 1, resultVar, -1, variableName+"=", context); + } + } else if (element.isAttributeVariable()) { + VariableGenerator.instance.setAttributeVariableValue(resultVar, setVar, element, context); + } + } else { + if (true) throw new RuntimeException("not implements"); + } + } + + private void createChildExpressionAt(int var, ExpressionNode parent, int index, ChunkContext context) throws IntermediateCodeExpression { + if(parent.isElement(index)) { + createElement(var, parent.getElementAt(index), context); + } else { + createExpression(var, parent.getExpressionAt(index), context); + } + } + + private void createElement(int var, ElementNode element, ChunkContext context) throws IntermediateCodeExpression { + if(element.type == ElementType.Variable) { + String variableName = element.value; + if (element.isLocalVariable()) { + if (context.variableRecorder.contains(variableName)) { + int localVariableIndex = context.variableRecorder.getVarIndex(variableName); + context.codeChunk.push(Command.Set, var, localVariableIndex); + } else { + context.codeChunk.push(Command.GetThis, var); + FunctionGenerator.instance.invokeByName(var, 0, var, -1, variableName, context); + } + } else if (element.isAttributeVariable()) { + VariableGenerator.instance.getAttributesValue(var, element, context); + } + } else if(element.type == ElementType.RegEx) { + int paramVar = context.variablePool.createIndex(); + ImmediateNumber immediateNumber = new ImmediateNumber(); + immediateNumber.type = ImmediateType.String; + immediateNumber.stringValue = element.value; + context.codeChunk.push(Command.SetImmediate, paramVar, immediateNumber); + context.codeChunk.push(Command.Push, paramVar); + context.codeChunk.push(Command.NewRegEx); + context.variablePool.freeIndex(paramVar); + + } else if(element.type == ElementType.This) { + context.codeChunk.push(Command.GetThis, var); + + } else if(element.type == ElementType.Array) { + ArrayNode array = element.array; + for(ExpressionNode expression:array.content) { + int paramVar = createExpression(expression, context); + context.codeChunk.push(Command.Push, paramVar); + context.variablePool.freeIndex(paramVar); + } + context.codeChunk.push(Command.NewArray, var, array.content.size()); + + } else if(element.type == ElementType.Container) { + ContainerNode container = element.container; + for(Entry e:container.content.entrySet()) { + String key = e.getKey(); + ExpressionNode value = e.getValue(); + ImmediateNumber immediateNumber = new ImmediateNumber(); + + int keyVar = context.variablePool.createIndex(); + immediateNumber.type = ImmediateType.String; + immediateNumber.stringValue = key; + context.codeChunk.push(Command.SetImmediate, keyVar, immediateNumber); + context.codeChunk.push(Command.Push, keyVar); + context.variablePool.freeIndex(keyVar); + + int valueVar = createExpression(value, context); + context.codeChunk.push(Command.Push, valueVar); + context.variablePool.freeIndex(valueVar); + } + context.codeChunk.push(Command.NewContainer, var, container.content.size()); + + } else { + ImmediateNumber immediateNumber = new ImmediateNumber(); + if(element.type == ElementType.Null) { + immediateNumber.type = ImmediateType.Null; + + } else if(element.type == ElementType.Integer) { + immediateNumber.type = ImmediateType.Integer; + immediateNumber.integerValue = Integer.valueOf(element.value); + + } else if(element.type == ElementType.Number) { + immediateNumber.type = ImmediateType.Number; + immediateNumber.numberValue = Float.valueOf(element.value); + + } else if(element.type == ElementType.String) { + immediateNumber.type = ImmediateType.String; + immediateNumber.stringValue = element.value; + + } else if (element.type == ElementType.Boolean) { + immediateNumber.type = ImmediateType.Boolean; + immediateNumber.booleanValue = element.value.equals("true"); + } + context.codeChunk.push(Command.SetImmediate, var, immediateNumber); + } + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java b/src/main/java/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java old mode 100755 new mode 100644 similarity index 97% rename from src/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java index abdbf93..d730a2a --- a/src/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/FunctionGenerator.java @@ -1,162 +1,162 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.*; - -import com.taozeyu.taolan.analysis.node.ChunkNode; -import com.taozeyu.taolan.analysis.node.DefineFunctionNode; -import com.taozeyu.taolan.analysis.node.ElementNode; -import com.taozeyu.taolan.analysis.node.ElementNode.ElementType; -import com.taozeyu.taolan.analysis.node.ExpressionNode; -import com.taozeyu.taolan.analysis.node.InvokerNode; -import com.taozeyu.taolan.analysis.node.LambdaNode; -import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; -import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateNumber; -import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateType; - -class FunctionGenerator { - - final static FunctionGenerator instance = new FunctionGenerator(); - - void createInvoker(int var, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { - InvokerNode invoker = expression.invoker; - Integer target; - String funName; - if(expression.isExpression(0)) { - ExpressionNode parentNode = expression.getExpressionAt(0); - if(".".equals(parentNode.sign)) { - target = ExpressionGenerator.instance.createChildExpressionAt(parentNode, 0, context); - funName = getFunctionNameFrom(1, parentNode); - } else { - throw new IntermediateCodeExpression(); - } - } else { - target = null; - funName = getFunctionNameFrom(0, expression); - } - createInvoker(target, var, funName, invoker.paramList, invoker.lambda, context); - if(target != null) { - context.variablePool.freeIndex(target); - } - } - - private String getFunctionNameFrom(int index, ExpressionNode parent) throws IntermediateCodeExpression { - String funName; - if(parent.isElement(index)) { - ElementNode element = parent.getElementAt(index); - if(element.type == ElementType.Variable && !element.fromConstructor && !element.fromThis) { - funName = element.value; - } else { - throw new IntermediateCodeExpression(); - } - } else { - throw new IntermediateCodeExpression(); - } - return funName; - } - - void createInvoker(Integer target, int res, String funName, List paramList, LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { - if(target != null) { - invokerVirtual(target, res, funName, paramList, lambda, context); - } else { - invoker(res, funName, paramList, lambda, context); - } - } - - private void invokerVirtual(int target, int res, String funName, List paramList, LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { - pushParamsBeforeInvoke(paramList, context); - int lambdaID = -1; - if(lambda != null) { - lambdaID = createLambda(lambda, context); - } - int paramsCount = paramList == null? 0: paramList.size(); - invokeByName(target, paramsCount, res, lambdaID, funName, context); - } - - private void invoker(int res, String funName, List paramList, LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { - pushParamsBeforeInvoke(paramList, context); - int paramsCount = paramList == null? 0: paramList.size(); - - int lambdaFunctionId = -1; - if(lambda != null) { - lambdaFunctionId = createLambda(lambda, context); - } - Integer funID = context.functionIDMapper.get(funName); - - if(funID != null) { - context.codeChunk.push(Command.Invoke, funID, paramsCount, lambdaFunctionId); - context.codeChunk.push(Command.Pop, res); - - } else if (funName.equals("lambda")) { - context.codeChunk.push(Command.InvokeLambda, paramsCount, lambdaFunctionId); - context.codeChunk.push(Command.Pop, res); - - } else { - int target = context.variablePool.createIndex(); - context.codeChunk.push(Command.GetThis, target); - invokeByName(target, paramsCount, res, lambdaFunctionId, funName, context); - context.variablePool.freeIndex(target); - } - } - - private void pushParamsBeforeInvoke(List paramList, ChunkContext context) throws IntermediateCodeExpression { - if(paramList != null) { - for(ExpressionNode param:paramList) { - int paramVar = ExpressionGenerator.instance.createExpression(param, context); - context.codeChunk.push(Command.Push, paramVar); - context.variablePool.freeIndex(paramVar); - } - } - } - - void invokeByName(int target, int paramsSize, int res, int lambdaID, String funName, ChunkContext context) { - ImmediateNumber immediateNumber = new ImmediateNumber(); - immediateNumber.type = ImmediateType.String; - immediateNumber.stringValue = funName; - context.codeChunk.push(Command.InvokeVirtual, target, paramsSize, lambdaID, immediateNumber); - context.codeChunk.push(Command.Pop, res); - } - - private int createLambda(LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { - return generateFunction(context, lambda.chunk, lambda.paramNameList); - } - - int createFunction(DefineFunctionNode funNode, ChunkContext context) throws IntermediateCodeExpression { - String funName = funNode.functionName; - if(funNode.operator != null) { - funName += funNode.operator; - } - int funID = generateFunction(context, funNode.body, funNode.paramNames); - if(funNode.parentExpression != null) { - int parentVar = ExpressionGenerator.instance.createExpression(funNode.parentExpression, context); - ImmediateNumber functionName = new ImmediateNumber(); - functionName.type = ImmediateType.String; - functionName.stringValue = funName; - context.codeChunk.push(Command.DefFunction, parentVar, funID, -1, functionName); - context.variablePool.freeIndex(parentVar); - } else { - if(context.functionIDMapper.containsKey(funName)) { - throw new IntermediateCodeExpression("function has defined " + funName); - } - context.functionIDMapper.put(funName, funID); - } - return funID; - } - - private int generateFunction(ChunkContext context, ChunkNode body, List paramNames) throws IntermediateCodeExpression { - ChunkContext childContext = context.extend(); - if(paramNames != null) { - int index = 0; - for(String paramName:paramNames) { - int paramVariableIndex = VariableGenerator.instance.defVariable(paramName, childContext); - childContext.codeChunk.push(Command.Take, paramVariableIndex, index); - index++; - } - } - childContext.codeChunk.push(Command.Clear); - CodeCreator.instance.handleChunk(body, childContext); - childContext.codeChunk.push(Command.Return, -1); - int functionId = context.functionRecorder.createFunctionBody(childContext.codeChunk); - functionId += context.functionStartIndex; - return functionId; - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.*; + +import com.taozeyu.taolan.analysis.node.ChunkNode; +import com.taozeyu.taolan.analysis.node.DefineFunctionNode; +import com.taozeyu.taolan.analysis.node.ElementNode; +import com.taozeyu.taolan.analysis.node.ElementNode.ElementType; +import com.taozeyu.taolan.analysis.node.ExpressionNode; +import com.taozeyu.taolan.analysis.node.InvokerNode; +import com.taozeyu.taolan.analysis.node.LambdaNode; +import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; +import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateNumber; +import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateType; + +class FunctionGenerator { + + final static FunctionGenerator instance = new FunctionGenerator(); + + void createInvoker(int var, ExpressionNode expression, ChunkContext context) throws IntermediateCodeExpression { + InvokerNode invoker = expression.invoker; + Integer target; + String funName; + if(expression.isExpression(0)) { + ExpressionNode parentNode = expression.getExpressionAt(0); + if(".".equals(parentNode.sign)) { + target = ExpressionGenerator.instance.createChildExpressionAt(parentNode, 0, context); + funName = getFunctionNameFrom(1, parentNode); + } else { + throw new IntermediateCodeExpression(); + } + } else { + target = null; + funName = getFunctionNameFrom(0, expression); + } + createInvoker(target, var, funName, invoker.paramList, invoker.lambda, context); + if(target != null) { + context.variablePool.freeIndex(target); + } + } + + private String getFunctionNameFrom(int index, ExpressionNode parent) throws IntermediateCodeExpression { + String funName; + if(parent.isElement(index)) { + ElementNode element = parent.getElementAt(index); + if(element.type == ElementType.Variable && !element.fromConstructor && !element.fromThis) { + funName = element.value; + } else { + throw new IntermediateCodeExpression(); + } + } else { + throw new IntermediateCodeExpression(); + } + return funName; + } + + void createInvoker(Integer target, int res, String funName, List paramList, LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { + if(target != null) { + invokerVirtual(target, res, funName, paramList, lambda, context); + } else { + invoker(res, funName, paramList, lambda, context); + } + } + + private void invokerVirtual(int target, int res, String funName, List paramList, LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { + pushParamsBeforeInvoke(paramList, context); + int lambdaID = -1; + if(lambda != null) { + lambdaID = createLambda(lambda, context); + } + int paramsCount = paramList == null? 0: paramList.size(); + invokeByName(target, paramsCount, res, lambdaID, funName, context); + } + + private void invoker(int res, String funName, List paramList, LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { + pushParamsBeforeInvoke(paramList, context); + int paramsCount = paramList == null? 0: paramList.size(); + + int lambdaFunctionId = -1; + if(lambda != null) { + lambdaFunctionId = createLambda(lambda, context); + } + Integer funID = context.functionIDMapper.get(funName); + + if(funID != null) { + context.codeChunk.push(Command.Invoke, funID, paramsCount, lambdaFunctionId); + context.codeChunk.push(Command.Pop, res); + + } else if (funName.equals("lambda")) { + context.codeChunk.push(Command.InvokeLambda, paramsCount, lambdaFunctionId); + context.codeChunk.push(Command.Pop, res); + + } else { + int target = context.variablePool.createIndex(); + context.codeChunk.push(Command.GetThis, target); + invokeByName(target, paramsCount, res, lambdaFunctionId, funName, context); + context.variablePool.freeIndex(target); + } + } + + private void pushParamsBeforeInvoke(List paramList, ChunkContext context) throws IntermediateCodeExpression { + if(paramList != null) { + for(ExpressionNode param:paramList) { + int paramVar = ExpressionGenerator.instance.createExpression(param, context); + context.codeChunk.push(Command.Push, paramVar); + context.variablePool.freeIndex(paramVar); + } + } + } + + void invokeByName(int target, int paramsSize, int res, int lambdaID, String funName, ChunkContext context) { + ImmediateNumber immediateNumber = new ImmediateNumber(); + immediateNumber.type = ImmediateType.String; + immediateNumber.stringValue = funName; + context.codeChunk.push(Command.InvokeVirtual, target, paramsSize, lambdaID, immediateNumber); + context.codeChunk.push(Command.Pop, res); + } + + private int createLambda(LambdaNode lambda, ChunkContext context) throws IntermediateCodeExpression { + return generateFunction(context, lambda.chunk, lambda.paramNameList); + } + + int createFunction(DefineFunctionNode funNode, ChunkContext context) throws IntermediateCodeExpression { + String funName = funNode.functionName; + if(funNode.operator != null) { + funName += funNode.operator; + } + int funID = generateFunction(context, funNode.body, funNode.paramNames); + if(funNode.parentExpression != null) { + int parentVar = ExpressionGenerator.instance.createExpression(funNode.parentExpression, context); + ImmediateNumber functionName = new ImmediateNumber(); + functionName.type = ImmediateType.String; + functionName.stringValue = funName; + context.codeChunk.push(Command.DefFunction, parentVar, funID, -1, functionName); + context.variablePool.freeIndex(parentVar); + } else { + if(context.functionIDMapper.containsKey(funName)) { + throw new IntermediateCodeExpression("function has defined " + funName); + } + context.functionIDMapper.put(funName, funID); + } + return funID; + } + + private int generateFunction(ChunkContext context, ChunkNode body, List paramNames) throws IntermediateCodeExpression { + ChunkContext childContext = context.extend(); + if(paramNames != null) { + int index = 0; + for(String paramName:paramNames) { + int paramVariableIndex = VariableGenerator.instance.defVariable(paramName, childContext); + childContext.codeChunk.push(Command.Take, paramVariableIndex, index); + index++; + } + } + childContext.codeChunk.push(Command.Clear); + CodeCreator.instance.handleChunk(body, childContext); + childContext.codeChunk.push(Command.Return, -1); + int functionId = context.functionRecorder.createFunctionBody(childContext.codeChunk); + functionId += context.functionStartIndex; + return functionId; + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java b/src/main/java/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java index e40a800..7d2985c --- a/src/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/FunctionRecorder.java @@ -1,22 +1,22 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.ArrayList; -import java.util.List; - -class FunctionRecorder { - - private final List container = new ArrayList<>(); - - int createFunctionBody(CodeChunk body) { - container.add(body); - return container.size() - 1; - } - - CodeChunk getFunctionBody(int id) { - return container.get(id); - } - - List getContainer() { - return container; - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.ArrayList; +import java.util.List; + +class FunctionRecorder { + + private final List container = new ArrayList<>(); + + int createFunctionBody(CodeChunk body) { + container.add(body); + return container.size() - 1; + } + + CodeChunk getFunctionBody(int id) { + return container.get(id); + } + + List getContainer() { + return container; + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java b/src/main/java/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java old mode 100755 new mode 100644 similarity index 97% rename from src/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java index 7dcd42b..6f592e0 --- a/src/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/IntermediateCodeCreator.java @@ -1,33 +1,33 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.List; - -import com.taozeyu.taolan.analysis.node.ChunkNode; -import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; - -public class IntermediateCodeCreator { - - private final int functionStartIndex; - - public IntermediateCodeCreator(int functionStartIndex) { - this.functionStartIndex = functionStartIndex; - } - - public Result create(ChunkNode chunk) throws IntermediateCodeExpression { - ChunkContext context = new ChunkContext(functionStartIndex); - CodeCreator.instance.handleChunk(chunk, context); - context.codeChunk.push(Command.Return, -1); - PlaceholderReplacement.instance.handle(context.placeholderRegisterList); - return new Result(context.codeChunk, context.functionRecorder.getContainer()); - } - - public static class Result { - public final CodeChunk targetCode; - public final List functionBodyTable; - - private Result(CodeChunk targetCode, List functionBodyTable) { - this.targetCode = targetCode; - this.functionBodyTable = functionBodyTable; - } - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.List; + +import com.taozeyu.taolan.analysis.node.ChunkNode; +import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; + +public class IntermediateCodeCreator { + + private final int functionStartIndex; + + public IntermediateCodeCreator(int functionStartIndex) { + this.functionStartIndex = functionStartIndex; + } + + public Result create(ChunkNode chunk) throws IntermediateCodeExpression { + ChunkContext context = new ChunkContext(functionStartIndex); + CodeCreator.instance.handleChunk(chunk, context); + context.codeChunk.push(Command.Return, -1); + PlaceholderReplacement.instance.handle(context.placeholderRegisterList); + return new Result(context.codeChunk, context.functionRecorder.getContainer()); + } + + public static class Result { + public final CodeChunk targetCode; + public final List functionBodyTable; + + private Result(CodeChunk targetCode, List functionBodyTable) { + this.targetCode = targetCode; + this.functionBodyTable = functionBodyTable; + } + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java b/src/main/java/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java index 062cdff..cd34cd2 --- a/src/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/IntermediateCodeExpression.java @@ -1,12 +1,12 @@ -package com.taozeyu.taolan.intermediatecode; - -public class IntermediateCodeExpression extends Exception { - - private static final long serialVersionUID = -5303146379867837864L; - - public IntermediateCodeExpression() {}; - - public IntermediateCodeExpression(String msg) { - super(msg); - }; -} +package com.taozeyu.taolan.intermediatecode; + +public class IntermediateCodeExpression extends Exception { + + private static final long serialVersionUID = -5303146379867837864L; + + public IntermediateCodeExpression() {}; + + public IntermediateCodeExpression(String msg) { + super(msg); + }; +} diff --git a/src/com/taozeyu/taolan/intermediatecode/JumpStack.java b/src/main/java/com/taozeyu/taolan/intermediatecode/JumpStack.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/intermediatecode/JumpStack.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/JumpStack.java index 42e6550..53f427c --- a/src/com/taozeyu/taolan/intermediatecode/JumpStack.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/JumpStack.java @@ -1,43 +1,43 @@ -package com.taozeyu.taolan.intermediatecode; - -class JumpStack { - - private Node topNode = null; - - void push(int breakLocation, int continueLocation) { - Node node = new Node(); - node.breakLocation = breakLocation; - node.continueLocation = continueLocation; - node.next = topNode; - topNode = node; - } - - void pop() { - topNode = topNode.next; - } - - boolean isNotInLoop() { - return topNode == null; - } - - int getCurrentBreakLocation() { - return topNode.breakLocation; - } - - int getCurrentContinueLocation() { - return topNode.continueLocation; - } - - void setCurrentBreakLocation(int currentBreakLocation) { - this.topNode.breakLocation = currentBreakLocation; - } - - void setCurrentContinueLocation(int currentContinueLocation) { - this.topNode.continueLocation = currentContinueLocation; - } - - private static class Node { - private int breakLocation = -1, continueLocation = -1; - private Node next; - } -} +package com.taozeyu.taolan.intermediatecode; + +class JumpStack { + + private Node topNode = null; + + void push(int breakLocation, int continueLocation) { + Node node = new Node(); + node.breakLocation = breakLocation; + node.continueLocation = continueLocation; + node.next = topNode; + topNode = node; + } + + void pop() { + topNode = topNode.next; + } + + boolean isNotInLoop() { + return topNode == null; + } + + int getCurrentBreakLocation() { + return topNode.breakLocation; + } + + int getCurrentContinueLocation() { + return topNode.continueLocation; + } + + void setCurrentBreakLocation(int currentBreakLocation) { + this.topNode.breakLocation = currentBreakLocation; + } + + void setCurrentContinueLocation(int currentContinueLocation) { + this.topNode.continueLocation = currentContinueLocation; + } + + private static class Node { + private int breakLocation = -1, continueLocation = -1; + private Node next; + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java b/src/main/java/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java index 7983b78..f79b18f --- a/src/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/LocalVariablePool.java @@ -1,26 +1,26 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.LinkedList; - -class LocalVariablePool { - - private int nextIndex = 0; - private LinkedList indexPool = new LinkedList<>(); - - int createIndex() { - int index; - if(indexPool.isEmpty()) { - index = nextIndex; - nextIndex++; - } else { - index = indexPool.removeFirst(); - } - return index; - } - - void freeIndex(int index) { - if (index != -1) { - indexPool.addLast(index); - } - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.LinkedList; + +class LocalVariablePool { + + private int nextIndex = 0; + private LinkedList indexPool = new LinkedList<>(); + + int createIndex() { + int index; + if(indexPool.isEmpty()) { + index = nextIndex; + nextIndex++; + } else { + index = indexPool.removeFirst(); + } + return index; + } + + void freeIndex(int index) { + if (index != -1) { + indexPool.addLast(index); + } + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java b/src/main/java/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java index 347fefb..28d1698 --- a/src/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/PlaceholderReplacement.java @@ -1,78 +1,78 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; - -class PlaceholderReplacement { - - final static PlaceholderReplacement instance = new PlaceholderReplacement(); - - private static final Map commandReplaceIndexMap = new HashMap<>(); - - static { - define(Command.Jump, 1); - define(Command.JumpWhen, 1); - define(Command.JumpUnless, 1); - define(Command.PushTryBlock, 1, 2); - } - - static class RegisterNode { - CodeChunk codeChunk; - PositionPlaceholder holder; - } - - private static void define(Command command, int...replaceIndexes) { - commandReplaceIndexMap.put(command, replaceIndexes); - } - - RegisterNode register(CodeChunk codeChunk, PositionPlaceholder holder) { - RegisterNode node = new RegisterNode(); - node.codeChunk = codeChunk; - node.holder = holder; - return node; - } - - void handle(List list) { - for(RegisterNode node:list) { - handle(node.codeChunk, node.holder); - } - } - - private void handle(CodeChunk codeChunk, PositionPlaceholder holder) { - for(CodeChunk.Code code:codeChunk) { - int[] replaceIndexes = commandReplaceIndexMap.get(code.command); - if (replaceIndexes != null) { - for (int replaceIndex : replaceIndexes) { - replace(code, replaceIndex, holder); - } - } - } - } - - private void replace(CodeChunk.Code code, int replaceIndex, PositionPlaceholder holder) { - switch(replaceIndex) { - case 1: - code.number1 = checkAndReplace(code.number1, holder); - break; - case 2: - code.number2 = checkAndReplace(code.number2, holder); - break; - case 3: - code.number3 = checkAndReplace(code.number3, holder); - break; - default: - throw new RuntimeException("unknow replaceIndex " + replaceIndex); - } - } - - private int checkAndReplace(int position, PositionPlaceholder holder) { - if(position >= 0) { - return position; - } else { - return holder.getPosition(position); - } - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; + +class PlaceholderReplacement { + + final static PlaceholderReplacement instance = new PlaceholderReplacement(); + + private static final Map commandReplaceIndexMap = new HashMap<>(); + + static { + define(Command.Jump, 1); + define(Command.JumpWhen, 1); + define(Command.JumpUnless, 1); + define(Command.PushTryBlock, 1, 2); + } + + static class RegisterNode { + CodeChunk codeChunk; + PositionPlaceholder holder; + } + + private static void define(Command command, int...replaceIndexes) { + commandReplaceIndexMap.put(command, replaceIndexes); + } + + RegisterNode register(CodeChunk codeChunk, PositionPlaceholder holder) { + RegisterNode node = new RegisterNode(); + node.codeChunk = codeChunk; + node.holder = holder; + return node; + } + + void handle(List list) { + for(RegisterNode node:list) { + handle(node.codeChunk, node.holder); + } + } + + private void handle(CodeChunk codeChunk, PositionPlaceholder holder) { + for(CodeChunk.Code code:codeChunk) { + int[] replaceIndexes = commandReplaceIndexMap.get(code.command); + if (replaceIndexes != null) { + for (int replaceIndex : replaceIndexes) { + replace(code, replaceIndex, holder); + } + } + } + } + + private void replace(CodeChunk.Code code, int replaceIndex, PositionPlaceholder holder) { + switch(replaceIndex) { + case 1: + code.number1 = checkAndReplace(code.number1, holder); + break; + case 2: + code.number2 = checkAndReplace(code.number2, holder); + break; + case 3: + code.number3 = checkAndReplace(code.number3, holder); + break; + default: + throw new RuntimeException("unknow replaceIndex " + replaceIndex); + } + } + + private int checkAndReplace(int position, PositionPlaceholder holder) { + if(position >= 0) { + return position; + } else { + return holder.getPosition(position); + } + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java b/src/main/java/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java old mode 100755 new mode 100644 similarity index 95% rename from src/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java index d144d99..1a49a52 --- a/src/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/PositionPlaceholder.java @@ -1,24 +1,24 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.HashMap; -import java.util.Map; - -class PositionPlaceholder { - - private int nextPosition = -1; - private Map placeholderMapper = new HashMap<>(); - - int createPosition() { - int position = nextPosition; - nextPosition--; - return position; - } - - void setPosition(int placeholder, int position) { - placeholderMapper.put(placeholder, position); - } - - int getPosition(int placeholder) { - return placeholderMapper.get(placeholder); - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.HashMap; +import java.util.Map; + +class PositionPlaceholder { + + private int nextPosition = -1; + private Map placeholderMapper = new HashMap<>(); + + int createPosition() { + int position = nextPosition; + nextPosition--; + return position; + } + + void setPosition(int placeholder, int position) { + placeholderMapper.put(placeholder, position); + } + + int getPosition(int placeholder) { + return placeholderMapper.get(placeholder); + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/VariableGenerator.java b/src/main/java/com/taozeyu/taolan/intermediatecode/VariableGenerator.java old mode 100755 new mode 100644 similarity index 97% rename from src/com/taozeyu/taolan/intermediatecode/VariableGenerator.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/VariableGenerator.java index 1289737..6c30a00 --- a/src/com/taozeyu/taolan/intermediatecode/VariableGenerator.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/VariableGenerator.java @@ -1,43 +1,43 @@ -package com.taozeyu.taolan.intermediatecode; - -import com.taozeyu.taolan.analysis.node.ElementNode; -import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; -import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateNumber; -import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateType; - -class VariableGenerator { - - final static VariableGenerator instance = new VariableGenerator(); - - int defVariable(String varName, ChunkContext context) throws IntermediateCodeExpression { - if(context.variableRecorder.contains(varName)) { - throw new IntermediateCodeExpression("variable has defined " + varName); - } - int varIndex = context.variablePool.createIndex(); - context.variableRecorder.define(varName, varIndex); - return varIndex; - } - - void getAttributesValue(int var, ElementNode element, ChunkContext context) throws IntermediateCodeExpression { - if(element.fromThis) { - context.codeChunk.push(Command.Rel, var, getStringImmediateNumber(element.value)); - } else if(element.fromConstructor) { - context.codeChunk.push(Command.RelStatic, var, getStringImmediateNumber(element.value)); - } - } - - void setAttributeVariableValue(int resultVar, int setVar, ElementNode element, ChunkContext context) throws IntermediateCodeExpression { - if(element.fromThis) { - context.codeChunk.push(Command.Move, resultVar, setVar, -1, getStringImmediateNumber(element.value)); - } else if(element.fromConstructor) { - context.codeChunk.push(Command.MoveStatic, resultVar, setVar, -1, getStringImmediateNumber(element.value)); - } - } - - private ImmediateNumber getStringImmediateNumber(String variableName) { - ImmediateNumber in = new ImmediateNumber(); - in.type = ImmediateType.String; - in.stringValue = variableName; - return in; - } -} +package com.taozeyu.taolan.intermediatecode; + +import com.taozeyu.taolan.analysis.node.ElementNode; +import com.taozeyu.taolan.intermediatecode.CodeChunk.Command; +import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateNumber; +import com.taozeyu.taolan.intermediatecode.CodeChunk.ImmediateType; + +class VariableGenerator { + + final static VariableGenerator instance = new VariableGenerator(); + + int defVariable(String varName, ChunkContext context) throws IntermediateCodeExpression { + if(context.variableRecorder.contains(varName)) { + throw new IntermediateCodeExpression("variable has defined " + varName); + } + int varIndex = context.variablePool.createIndex(); + context.variableRecorder.define(varName, varIndex); + return varIndex; + } + + void getAttributesValue(int var, ElementNode element, ChunkContext context) throws IntermediateCodeExpression { + if(element.fromThis) { + context.codeChunk.push(Command.Rel, var, getStringImmediateNumber(element.value)); + } else if(element.fromConstructor) { + context.codeChunk.push(Command.RelStatic, var, getStringImmediateNumber(element.value)); + } + } + + void setAttributeVariableValue(int resultVar, int setVar, ElementNode element, ChunkContext context) throws IntermediateCodeExpression { + if(element.fromThis) { + context.codeChunk.push(Command.Move, resultVar, setVar, -1, getStringImmediateNumber(element.value)); + } else if(element.fromConstructor) { + context.codeChunk.push(Command.MoveStatic, resultVar, setVar, -1, getStringImmediateNumber(element.value)); + } + } + + private ImmediateNumber getStringImmediateNumber(String variableName) { + ImmediateNumber in = new ImmediateNumber(); + in.type = ImmediateType.String; + in.stringValue = variableName; + return in; + } +} diff --git a/src/com/taozeyu/taolan/intermediatecode/VariableRecorder.java b/src/main/java/com/taozeyu/taolan/intermediatecode/VariableRecorder.java old mode 100755 new mode 100644 similarity index 96% rename from src/com/taozeyu/taolan/intermediatecode/VariableRecorder.java rename to src/main/java/com/taozeyu/taolan/intermediatecode/VariableRecorder.java index 9cb063c..3c990fc --- a/src/com/taozeyu/taolan/intermediatecode/VariableRecorder.java +++ b/src/main/java/com/taozeyu/taolan/intermediatecode/VariableRecorder.java @@ -1,39 +1,39 @@ -package com.taozeyu.taolan.intermediatecode; - -import java.util.LinkedHashMap; -import java.util.Map; - -class VariableRecorder { - - private final Map variableMap = new LinkedHashMap<>(); - - private final VariableRecorder parent; - - VariableRecorder() { - this(null); - } - - private VariableRecorder(VariableRecorder parent) { - this.parent = parent; - } - - VariableRecorder link() { - return new VariableRecorder(this); - } - - boolean contains(String variableName) { - return getVarIndex(variableName) != null; - } - - void define(String variableName, int varIndex) { - variableMap.put(variableName, varIndex); - } - - Integer getVarIndex(String variableName) { - Integer varIndex = variableMap.get(variableName); - if(varIndex == null && parent != null) { - varIndex = parent.getVarIndex(variableName); - } - return varIndex; - } -} +package com.taozeyu.taolan.intermediatecode; + +import java.util.LinkedHashMap; +import java.util.Map; + +class VariableRecorder { + + private final Map variableMap = new LinkedHashMap<>(); + + private final VariableRecorder parent; + + VariableRecorder() { + this(null); + } + + private VariableRecorder(VariableRecorder parent) { + this.parent = parent; + } + + VariableRecorder link() { + return new VariableRecorder(this); + } + + boolean contains(String variableName) { + return getVarIndex(variableName) != null; + } + + void define(String variableName, int varIndex) { + variableMap.put(variableName, varIndex); + } + + Integer getVarIndex(String variableName) { + Integer varIndex = variableMap.get(variableName); + if(varIndex == null && parent != null) { + varIndex = parent.getVarIndex(variableName); + } + return varIndex; + } +} diff --git a/src/com/taozeyu/taolan/virtualMachine/DataChunk.java b/src/main/java/com/taozeyu/taolan/virtualMachine/DataChunk.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/DataChunk.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/DataChunk.java diff --git a/src/com/taozeyu/taolan/virtualMachine/Interpreter.java b/src/main/java/com/taozeyu/taolan/virtualMachine/Interpreter.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/Interpreter.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/Interpreter.java diff --git a/src/com/taozeyu/taolan/virtualMachine/NativeFunction.java b/src/main/java/com/taozeyu/taolan/virtualMachine/NativeFunction.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/NativeFunction.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/NativeFunction.java diff --git a/src/com/taozeyu/taolan/virtualMachine/Runtime.java b/src/main/java/com/taozeyu/taolan/virtualMachine/Runtime.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/Runtime.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/Runtime.java diff --git a/src/com/taozeyu/taolan/virtualMachine/TaolanNativeObject.java b/src/main/java/com/taozeyu/taolan/virtualMachine/TaolanNativeObject.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/TaolanNativeObject.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/TaolanNativeObject.java diff --git a/src/com/taozeyu/taolan/virtualMachine/TaolanObject.java b/src/main/java/com/taozeyu/taolan/virtualMachine/TaolanObject.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/TaolanObject.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/TaolanObject.java diff --git a/src/com/taozeyu/taolan/virtualMachine/Value.java b/src/main/java/com/taozeyu/taolan/virtualMachine/Value.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/Value.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/Value.java diff --git a/src/com/taozeyu/taolan/virtualMachine/VirtualMachine.java b/src/main/java/com/taozeyu/taolan/virtualMachine/VirtualMachine.java similarity index 99% rename from src/com/taozeyu/taolan/virtualMachine/VirtualMachine.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/VirtualMachine.java index e0c67c7..bf25fac 100644 --- a/src/com/taozeyu/taolan/virtualMachine/VirtualMachine.java +++ b/src/main/java/com/taozeyu/taolan/virtualMachine/VirtualMachine.java @@ -75,7 +75,7 @@ private int hasRegisteredFunctionCount() { private void loadAllSystemLib() throws IOException, SyntacticAnalysisException, IntermediateCodeExpression, LexicalAnalysisException { Charset systemLibCharset = Charset.forName("UTF-8"); - File libDirectory = new File(System.getProperty("user.dir"), "src/system_lib"); + File libDirectory = new File(System.getProperty("user.dir"), "target/classes/system_lib"); for (File systemLibFile : libDirectory.listFiles()) { if (systemLibFile.getName().matches("(\\w|\\-|_)+\\.t$")) {//扩展名是 .t 的文件 BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(systemLibFile), systemLibCharset)); diff --git a/src/com/taozeyu/taolan/virtualMachine/nativeobject/ArrayNativeObject.java b/src/main/java/com/taozeyu/taolan/virtualMachine/nativeobject/ArrayNativeObject.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/nativeobject/ArrayNativeObject.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/nativeobject/ArrayNativeObject.java diff --git a/src/com/taozeyu/taolan/virtualMachine/nativeobject/ContainerNativeObject.java b/src/main/java/com/taozeyu/taolan/virtualMachine/nativeobject/ContainerNativeObject.java similarity index 100% rename from src/com/taozeyu/taolan/virtualMachine/nativeobject/ContainerNativeObject.java rename to src/main/java/com/taozeyu/taolan/virtualMachine/nativeobject/ContainerNativeObject.java diff --git a/src/main/java/script/test.t b/src/main/java/script/test.t new file mode 100644 index 0000000..d1e4b92 --- /dev/null +++ b/src/main/java/script/test.t @@ -0,0 +1,11 @@ +def say_hello_world(who) + print "hello world " + who +end +def plus(a, b) + return a + b +end +var name = "tao" +say_hello_world name +var sum = plus 1, 2 +print sum +#我是注释,注释是这样写的。 \ No newline at end of file diff --git a/src/system_lib/Array.t b/src/main/java/system_lib/Array.t similarity index 100% rename from src/system_lib/Array.t rename to src/main/java/system_lib/Array.t diff --git a/src/system_lib/Container.t b/src/main/java/system_lib/Container.t similarity index 100% rename from src/system_lib/Container.t rename to src/main/java/system_lib/Container.t diff --git a/src/system_lib/Error.t b/src/main/java/system_lib/Error.t similarity index 100% rename from src/system_lib/Error.t rename to src/main/java/system_lib/Error.t diff --git a/src/system_lib/Object.t b/src/main/java/system_lib/Object.t similarity index 100% rename from src/system_lib/Object.t rename to src/main/java/system_lib/Object.t