diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/Function.java b/src/be/jeffcheasey88/peeratcode/parser/java/Function.java index 041c1f7..e895cfa 100644 --- a/src/be/jeffcheasey88/peeratcode/parser/java/Function.java +++ b/src/be/jeffcheasey88/peeratcode/parser/java/Function.java @@ -4,9 +4,10 @@ import java.util.List; import be.jeffcheasey88.peeratcode.parser.Token; import be.jeffcheasey88.peeratcode.parser.java.Annotation.Annotable; +import be.jeffcheasey88.peeratcode.parser.java.Operation.OperationContainer; import be.jeffcheasey88.peeratcode.parser.java.Variable.VariableContainer; -public class Function extends JavaElement implements Annotable, VariableContainer{ +public class Function extends JavaElement implements Annotable, VariableContainer, OperationContainer{ public static interface FunctionContainer{ @@ -56,4 +57,9 @@ public class Function extends JavaElement implements Annotable, VariableContaine this.elements.add(variable); } + @Override + public void addOperation(Operation operation) { + this.elements.add(operation); + } + } diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/JavaParser.java b/src/be/jeffcheasey88/peeratcode/parser/java/JavaParser.java index 059f0ac..3661d14 100644 --- a/src/be/jeffcheasey88/peeratcode/parser/java/JavaParser.java +++ b/src/be/jeffcheasey88/peeratcode/parser/java/JavaParser.java @@ -11,6 +11,7 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -23,6 +24,7 @@ import be.jeffcheasey88.peeratcode.parser.Tokenizer; import be.jeffcheasey88.peeratcode.parser.java.Annotation.Annotable; import be.jeffcheasey88.peeratcode.parser.java.Function.FunctionContainer; import be.jeffcheasey88.peeratcode.parser.java.Value.BiValue; +import be.jeffcheasey88.peeratcode.parser.java.Variable.VariableContainer; import be.jeffcheasey88.peeratcode.parser.state.BuilderStateTree; import be.jeffcheasey88.peeratcode.parser.state.InitialStateTree; import be.jeffcheasey88.peeratcode.parser.state.RedirectStateTree; @@ -461,24 +463,46 @@ public class JavaParser extends Parser { })).then(annotation_end); //VARIABLE + BiFunction variable_builder = (parent, bag) -> { + Integer mod = bag.get("mod"); + Token vtype = bag.get("type"); + Map map = bag.get("vars"); + for(Entry vars : map.entrySet()){ + Variable result = new Variable(mod == null ? 0 : mod, vtype, vars.getKey(), false, vars.getValue()); + bag.set(result); + if(parent instanceof VariableContainer) ((VariableContainer)parent).addVariable(result); + } + return null; + }; + InitialStateTree variable = new InitialStateTree<>(); variable.multiple(annotation); - StateTree variable_mod = variable.then(new RedirectStateTree<>(modifier, (global, local) -> global.set("modifier", local))); - StateTree variable_type = variable.then(new RedirectStateTree<>(type, (global, local) -> global.set("type", local))); + StateTree variable_mod = variable.then(new RedirectStateTree<>(modifier, (global, local) -> global.set("mod", local.get()))); + StateTree variable_type = variable.then(new RedirectStateTree<>(type, (global, local) -> global.set("type", local.get()))); variable_mod.then(variable_type); StateTree variable_name = variable_type.then((validator) -> validator.validate( (token) -> token.getType().equals(TokenType.NAME), - (bag, token) -> bag.set(token))); + (bag, token) -> { + Map map = bag.get("vars"); + if(map == null){ + map = new LinkedHashMap<>(); + bag.set("vars", map); + } + bag.set("last", token); + map.put(token, null); + })); variable_name.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) - .end((a,b) -> null); + .end(variable_builder); StateTree variable_split = variable_name.then((validator) -> validator.validate((token) -> token.getValue().equals(","))); variable_split.then(variable_name); StateTree variable_value = variable_name.then((validator) -> validator.validate((token) -> token.getValue().equals("="))) - .then(new RedirectStateTree<>(value_container, (global, local) -> global.set("value", local))); + .then(new RedirectStateTree<>(value_container, (global, local) -> { + global.>get("vars").put(global.get("last"), local.get()); + })); variable_value.then(variable_split); variable_value.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) - .end((a,b) -> a); - variable_value.end((a,b) -> a); + .end(variable_builder); + variable_value.end(variable_builder); //OPERATION StateTree operation = new StateTree<>(); diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/Operation.java b/src/be/jeffcheasey88/peeratcode/parser/java/Operation.java index 0ca2696..4c3c35e 100644 --- a/src/be/jeffcheasey88/peeratcode/parser/java/Operation.java +++ b/src/be/jeffcheasey88/peeratcode/parser/java/Operation.java @@ -2,6 +2,12 @@ package be.jeffcheasey88.peeratcode.parser.java; public class Operation extends JavaElement{ +public static interface OperationContainer{ + + void addOperation(Operation operation); + + } + public Operation(){} } diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/AssignOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/AssignOperation.java new file mode 100644 index 0000000..aabc3fb --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/AssignOperation.java @@ -0,0 +1,24 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Operation; +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class AssignOperation extends Operation{ + + private Value left; + private Value right; + + public AssignOperation(Value left, Value right){ + this.left = left; + this.right = right; + } + + public Value left(){ + return left; + } + + public Value right(){ + return right; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/BreakOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/BreakOperation.java new file mode 100644 index 0000000..62d4005 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/BreakOperation.java @@ -0,0 +1,9 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Operation; + +public class BreakOperation extends Operation{ + + public BreakOperation(){} + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/CatchOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/CatchOperation.java new file mode 100644 index 0000000..95d8632 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/CatchOperation.java @@ -0,0 +1,26 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import java.util.List; + +import be.jeffcheasey88.peeratcode.parser.Token; + +public class CatchOperation extends OperationBag{ + + private List types; + private Token name; + + public CatchOperation(List types, Token name){ + super(); + this.types = types; + this.name = name; + } + + public List getTypes(){ + return this.types; + } + + public Token getName(){ + return this.name; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/ContinueOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ContinueOperation.java new file mode 100644 index 0000000..8d6a89b --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ContinueOperation.java @@ -0,0 +1,7 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Operation; + +public class ContinueOperation extends Operation{ + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/DoOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/DoOperation.java new file mode 100644 index 0000000..33ade37 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/DoOperation.java @@ -0,0 +1,5 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +public class DoOperation extends OperationBag{ + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/ElseOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ElseOperation.java new file mode 100644 index 0000000..05814a5 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ElseOperation.java @@ -0,0 +1,5 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +public class ElseOperation extends OperationBag{ + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/FinallyOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/FinallyOperation.java new file mode 100644 index 0000000..850bb6f --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/FinallyOperation.java @@ -0,0 +1,5 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +public class FinallyOperation extends OperationBag{ + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/ForOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ForOperation.java new file mode 100644 index 0000000..bc57d21 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ForOperation.java @@ -0,0 +1,43 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import java.util.List; + +import be.jeffcheasey88.peeratcode.parser.java.Value; +import be.jeffcheasey88.peeratcode.parser.java.Variable; + +public class ForOperation extends OperationBag{ + + private List init_vars; + private List init_values; + + private Value condition; + + private List updates; + + public ForOperation(List init_vars, List init_values, Value condition, List updates){ + super(); + + this.init_vars = init_vars; + this.init_values = init_values; + + this.condition = condition; + this.updates = updates; + } + + public List initVars(){ + return this.init_vars; + } + + public List initValues(){ + return this.init_values; + } + + public Value getCondition(){ + return this.condition; + } + + public List getUpdates(){ + return this.updates; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/ForeachOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ForeachOperation.java new file mode 100644 index 0000000..26a42c9 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ForeachOperation.java @@ -0,0 +1,32 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.Token; +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class ForeachOperation extends OperationBag{ + + private Token type; + private Token name; + private Value iterator; + + public ForeachOperation(Token type, Token name, Value iterator){ + super(); + + this.type = type; + this.name = name; + this.iterator = iterator; + } + + public Token getType(){ + return this.type; + } + + public Token getName(){ + return this.name; + } + + public Value getIterator(){ + return this.iterator; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/IfOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/IfOperation.java new file mode 100644 index 0000000..7c0ffd1 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/IfOperation.java @@ -0,0 +1,17 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class IfOperation extends OperationBag{ + + private Value condition; + + public IfOperation(Value condition){ + super(); + } + + public Value getCondition(){ + return this.condition; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/MethodCallOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/MethodCallOperation.java new file mode 100644 index 0000000..126a2d2 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/MethodCallOperation.java @@ -0,0 +1,39 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import java.util.List; + +import be.jeffcheasey88.peeratcode.parser.Token; +import be.jeffcheasey88.peeratcode.parser.java.Operation; +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class MethodCallOperation extends Operation{ + + private Value start; + private MethodCallOperation previous; + private Token path; + private List parameters; + + public MethodCallOperation(Value start, Token path, List parameters){ + this.start = start; + this.path = path; + this.parameters = parameters; + } + + public MethodCallOperation(MethodCallOperation previous, Token path, List parameters){ + this((Value)null, path, parameters); + this.previous = previous; + } + + public MethodCallOperation getPrevious(){ + return this.previous; + } + + public Token getPath(){ + return path; + } + + public List getParameters(){ + return this.parameters; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/OperationBag.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/OperationBag.java new file mode 100644 index 0000000..b9e5c15 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/OperationBag.java @@ -0,0 +1,30 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import java.util.ArrayList; +import java.util.List; + +import be.jeffcheasey88.peeratcode.parser.java.JavaElement; +import be.jeffcheasey88.peeratcode.parser.java.Operation; +import be.jeffcheasey88.peeratcode.parser.java.Variable; +import be.jeffcheasey88.peeratcode.parser.java.Operation.OperationContainer; +import be.jeffcheasey88.peeratcode.parser.java.Variable.VariableContainer; + +public class OperationBag extends Operation implements VariableContainer, OperationContainer{ + + private List elements; + + public OperationBag(){ + this.elements = new ArrayList<>(); + } + + @Override + public void addVariable(Variable variable){ + this.elements.add(variable); + } + + @Override + public void addOperation(Operation operation){ + this.elements.add(operation); + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/ReturnOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ReturnOperation.java new file mode 100644 index 0000000..be59091 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ReturnOperation.java @@ -0,0 +1,18 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Operation; +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class ReturnOperation extends Operation{ + + private Value value; + + public ReturnOperation(Value value){ + this.value = value; + } + + public Value getValue(){ + return this.value; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/SwitchOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/SwitchOperation.java new file mode 100644 index 0000000..54ae16a --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/SwitchOperation.java @@ -0,0 +1,7 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Operation; + +public class SwitchOperation extends Operation{ + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/SynchronizedOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/SynchronizedOperation.java new file mode 100644 index 0000000..678790d --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/SynchronizedOperation.java @@ -0,0 +1,18 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class SynchronizedOperation extends OperationBag{ + + private Value value; + + public SynchronizedOperation(Value value){ + super(); + this.value = value; + } + + public Value getValue(){ + return this.value; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/ThrowOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ThrowOperation.java new file mode 100644 index 0000000..6c1479d --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/ThrowOperation.java @@ -0,0 +1,18 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Operation; +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class ThrowOperation extends Operation{ + + private Value value; + + public ThrowOperation(Value value){ + this.value = value; + } + + public Value getValue(){ + return this.value; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/TryOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/TryOperation.java new file mode 100644 index 0000000..fdc047e --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/TryOperation.java @@ -0,0 +1,22 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Variable; + +public class TryOperation extends OperationBag{ + + private Variable resource; + + public TryOperation(){ + super(); + } + + public TryOperation(Variable resource){ + this(); + this.resource = resource; + } + + public Variable getResource(){ + return this.resource; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/parser/java/operation/WhileOperation.java b/src/be/jeffcheasey88/peeratcode/parser/java/operation/WhileOperation.java new file mode 100644 index 0000000..876bffc --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/parser/java/operation/WhileOperation.java @@ -0,0 +1,17 @@ +package be.jeffcheasey88.peeratcode.parser.java.operation; + +import be.jeffcheasey88.peeratcode.parser.java.Value; + +public class WhileOperation extends OperationBag{ + + private Value condition; + + public WhileOperation(Value condition){ + this.condition = condition; + } + + public Value getCondition(){ + return this.condition; + } + +} diff --git a/test/be/jeffcheasey88/peeratcode/parser/java/OperationTests.java b/test/be/jeffcheasey88/peeratcode/parser/java/OperationTests.java new file mode 100644 index 0000000..42a2c42 --- /dev/null +++ b/test/be/jeffcheasey88/peeratcode/parser/java/OperationTests.java @@ -0,0 +1,423 @@ +package be.jeffcheasey88.peeratcode.parser.java; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + +import org.junit.jupiter.api.Test; + +import be.jeffcheasey88.peeratcode.parser.Bag; +import be.jeffcheasey88.peeratcode.parser.Parser; +import be.jeffcheasey88.peeratcode.parser.Token; +import be.jeffcheasey88.peeratcode.parser.TokenType; +import be.jeffcheasey88.peeratcode.parser.TokenValidator; +import be.jeffcheasey88.peeratcode.parser.java.Operation.OperationContainer; +import be.jeffcheasey88.peeratcode.parser.java.operation.AssignOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.BreakOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.CatchOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.ContinueOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.DoOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.ElseOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.FinallyOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.IfOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.ReturnOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.SynchronizedOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.ThrowOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.TryOperation; +import be.jeffcheasey88.peeratcode.parser.java.operation.WhileOperation; +import be.jeffcheasey88.peeratcode.parser.state.RedirectStateTree; +import be.jeffcheasey88.peeratcode.parser.state.StateTree; + +public class OperationTests { + + public static StateTree get(){ + BiConsumer methodCallConcat = (bag, token) -> { + Token value = bag.get(); + if(value == null) bag.set(token); + else bag.set(value.concat(token)); + }; + + StateTree operation = new StateTree<>(); + StateTree operation_name = operation.then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set("left", local.get()))); + operation_name.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))).end(); + operation_name.then((validator) -> validator.validate((token) -> token.getValue().equals("="))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set("right", local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((parent, bag) -> { + AssignOperation op = new AssignOperation(bag.get("left"), bag.get("right")); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }); + + StateTree operation_return = operation.then((validator) -> validator.validate((token) -> token.getValue().equals("return"))); + operation_return.then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((parent,bag) -> { + ReturnOperation op = new ReturnOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }); + operation_return.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((parent,bag) -> { + ReturnOperation op = new ReturnOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }); + operation.then((validator) -> validator.validate((token) -> token.getValue().equals("throw"))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((parent,bag) -> { + ThrowOperation op = new ThrowOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }); + operation.then((validator) -> validator.validate((token) -> token.getValue().equals("do"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end((parent, bag) -> { + DoOperation op = new DoOperation(); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + + StateTree operation_else = operation.then((validator) -> validator.validate((token) -> token.getValue().equals("else"))) + .end((parent, bag) -> { + ElseOperation op = new ElseOperation(); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }); + operation_else.then(operation); + operation_else.then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end() +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + + StateTree operation_try = operation.then((validator) -> validator.validate((token) -> token.getValue().equals("try"))); + StateTree operation_try_base = operation_try.then((validator) -> validator.validate((token) -> token.getValue().equals("{"))); + operation_try.then((validator) -> validator.validate((token) -> token.getValue().equals("("))) + .then(new RedirectStateTree<>(VariableTests.get(), (global, local) -> global.set(local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(")"))) + .then(operation_try_base); + StateTree operation_try_end = operation_try_base.end((parent,bag) -> { + TryOperation op = new TryOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end((a,b) -> a); + + StateTree operation_finally = operation_try_end.then((validator) -> validator.validate((token) -> token.getValue().equals("finally"))); + operation_finally.then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end((parent, bag) -> { + FinallyOperation op = new FinallyOperation(); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + + }) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + + StateTree operation_catch_named = operation_try_end.then((validator) -> validator.validate((token) -> token.getValue().equals("catch"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("("))) + .then(new RedirectStateTree<>(TypeTests.get(), (global, local) -> { + List list = global.get("types"); + if(list == null){ + list = new ArrayList<>(); + global.set("types", list); + } + list.add(local.get()); + })); + operation_catch_named.then((validator) -> validator.validate((token) -> token.getValue().equals("|"))) + .then(operation_catch_named); + StateTree operation_catch = operation_catch_named.then((validator) -> validator.validate( + (token) -> token.getType().equals(TokenType.NAME), + (bag, token) -> bag.set("name", token) + )) + .then((validator) -> validator.validate((token) -> token.getValue().equals(")"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end((parent,bag) -> { + CatchOperation op = new CatchOperation(bag.get("types"), bag.get("name")); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + operation_catch.then(operation_catch_named); + operation_catch.then(operation_finally); + + + operation.then((validator) -> validator.validate((token) -> token.getValue().equals("continue"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((parent,bag) -> { + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(new ContinueOperation()); + return null; + }); + operation.then((validator) -> validator.validate((token) -> token.getValue().equals("break"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((parent,bag) -> { + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(new BreakOperation()); + return null; + }); + StateTree operation_if = operation.then((validator) -> validator.validate((token) -> token.getValue().equals("if"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("("))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(")"))) + .end((parent,bag) -> { + IfOperation op = new IfOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }); + operation_if.then(operation); + operation_if.then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end() +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + + StateTree switch_cases = new StateTree<>(); + StateTree switch_case_begin = switch_cases.then((validator) -> validator.validate((token) -> token.getValue().equals("case"))); + StateTree switch_case = switch_case_begin.then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(null))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(":"))); + switch_case.then(switch_case_begin); + switch_case.end((a,b) -> a); +// .multiple(function_container); + + switch_cases.then((validator) -> validator.validate((token) -> token.getValue().equals("default"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(":"))) + .end((a,b) -> a); +// .multiple(function_container); + + + operation.then((validator) -> validator.validate((token) -> token.getValue().equals("switch"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("("))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(null))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(")")) + && validator.validate((token) -> token.getValue().equals("{"))) + .end((a,b) -> a) + .multiple(switch_cases) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end((a,b) -> a); + + StateTree operation_for = operation.then((validator) -> validator.validate((token) -> token.getValue().equals("for"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("("))); + + StateTree operation_for_first_part = operation_for.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))); + + + StateTree operation_for_modifier = operation_for.then((validator) -> validator.validate( + (token) -> ModifierTests.getModifier(token.getValue()) > 0, + (bag, token) -> bag.set("final", true))); + operation_for_modifier.then(operation_for_modifier); + + StateTree operation_for_type = operation_for.then(new RedirectStateTree<>(TypeTests.get(), (global, local) -> global.set("init_type", local.get()))); + operation_for_modifier.then(operation_for_type); + + StateTree operation_for_assign = operation_for.then((validator) -> validator.validate( + (token) -> token.getType().equals(TokenType.NAME), + (bag, token) -> bag.set("varname", token))); + operation_for_modifier.then(operation_for_assign); + operation_for_type.then(operation_for_assign); + + StateTree operation_for_assign_end = operation_for_assign.then((validator) -> validator.validate((token) -> token.getValue().equals("="))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> { + Map map = global.get("init_values"); + if(map == null){ + map = new HashMap<>(); + global.set("init_values", map); + } + map.put(global.get("varname"), local.get()); + })); + + operation_for_assign.then(operation_for_assign); + operation_for_assign.then(operation_for_first_part); + + + operation_for_assign_end.then((validator) -> validator.validate((token) -> token.getValue().equals(","))) + .then(operation_for_assign); + operation_for_assign_end.then(operation_for_first_part); + + + StateTree operation_for_second_part = operation_for_first_part.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))); + + operation_for_first_part.then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(null))) + .then(operation_for_second_part); + + StateTree operation_for_end = operation_for_second_part.then((validator) -> validator.validate((token) -> token.getValue().equals(")"))); + operation_for_end.end((a,b) -> a); + + operation_for_end.then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end((a,b) -> a) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end((a,b) -> a); + + operation_for_assign.then((validator) -> validator.validate((token) -> token.getValue().equals(":"))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(null))) + .then(operation_for_end); + + StateTree operation_for_update = operation_for_second_part.then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(null))); + operation_for_update.then(operation_for_end); + operation_for_update.then((validator) -> validator.validate((token) -> token.getValue().equals(","))) + .then(operation_for_update); + + StateTree operation_while = operation.then((validator) -> validator.validate((token) -> token.getValue().equals("while"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("("))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(")"))); + operation_while.then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end((parent,bag) -> { + WhileOperation op = new WhileOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + + operation_while.then(new RedirectStateTree<>(operation, (global, local) -> global.set(null))) + .end(); + + operation_while.then((validator) -> validator.validate((token) -> token.getValue().equals(";"))) + .end((a,b) -> a); + + operation.then((validator) -> validator.validate((token) -> token.getValue().equals("synchronized"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("("))) + .then(new RedirectStateTree<>(ValueTests.get(), (global, local) -> global.set(local.get()))) + .then((validator) -> validator.validate((token) -> token.getValue().equals(")"))) + .then((validator) -> validator.validate((token) -> token.getValue().equals("{"))) + .end((parent,bag) -> { + SynchronizedOperation op = new SynchronizedOperation(bag.get()); + if(parent instanceof OperationContainer) ((OperationContainer)parent).addOperation(op); + return op; + }) +// .multiple(function_container) + .unique((validator) -> validator.validate((token) -> token.getValue().equals("}"))) + .end(); + +// function_container.then(variable); +// function_container.then(operation); + + return operation; + } + + private static Parser parser = new Parser(){ + { + setTokenizer(ModifierTests.TOKENIZER); + + setStateTree(get()); + } + }; + + JavaElement testCase(String value) throws Exception{ + TokenValidator.TOKENS = 0; + TokenValidator.MAX_VALIDATE = 0; + + JavaElement result = new JavaElement(); + + parser.parse(value, result); + + assertEquals(TokenValidator.TOKENS, TokenValidator.MAX_VALIDATE); + + return result; + } + + @Test + void breakOp() throws Exception{ + testCase("break;"); + } + + @Test + void CatchOp() throws Exception{ + System.out.println("exception"); + testCase("try{}catch(Exception e){}"); + System.out.println("exception|ioexception"); + testCase("try{}catch(Exception|IOException e){}"); +// System.out.println("exception - ioexception"); +// testCase("try{}catch(Exception e){}catch(IOException e){}"); + } + + @Test + void ContinueOp() throws Exception{ + testCase("continue;"); + } + + @Test + void doOp() throws Exception{ + testCase("do{}while(true);"); + } + + @Test + void elseOp() throws Exception{ + testCase("if(true){}else{}"); + testCase("if(true){}else if(true){}"); + } + + @Test + void finallyOp() throws Exception{ + testCase("try{}catch(Exception e){}finally{}"); + } + + @Test + void forOp() throws Exception{ + testCase("for(;;){}"); + } + + @Test + void ifOp() throws Exception{ + testCase("if(true){}"); + } + + @Test + void methodCallOp() throws Exception{ + testCase("System.out.println(\"hello\");"); + } + + @Test + void returnOp() throws Exception{ + testCase("return true;"); + } + + @Test + void switchOp() throws Exception{ + testCase("switch(var){ case 1: default:}"); + int var = 1; + switch(var){ case 1: break; default: break; } + } + + @Test + void synchronizedOp() throws Exception{ + testCase("synchronized(test){}"); + } + + @Test + void throwOp() throws Exception{ + testCase("throw e;"); + } + + @Test + void tryOp() throws Exception{ + testCase("try(Test test = new Test()){}"); + } + + @Test + void whileOp() throws Exception{ + testCase("while(true){}"); + } + + @Test + void assignOp() throws Exception{ + testCase("i=4;"); + } + + +}