├── sh ├── deploy.py ├── sh │ └── history.just ├── start.sh ├── update.sh ├── generate-jar-with-tests.sh └── generate-jar-without-tests.sh ├── art ├── const.png ├── complex.png ├── simple.png └── complex-result.png ├── src ├── main │ └── java │ │ └── com │ │ └── lfkdsk │ │ └── justel │ │ ├── utils │ │ ├── printer │ │ │ └── Printer.java │ │ ├── logger │ │ │ ├── LogLevel.java │ │ │ ├── LogTool.java │ │ │ ├── Printer.java │ │ │ ├── DebugLogTool.java │ │ │ ├── Settings.java │ │ │ └── Logger.java │ │ ├── collection │ │ │ ├── Tuple.java │ │ │ ├── EmptyArray.java │ │ │ └── ContainerHelpers.java │ │ ├── GeneratedId.java │ │ ├── table │ │ │ └── Charr.java │ │ ├── RandomUtils.java │ │ ├── json │ │ │ └── JSONException.java │ │ └── TypeUtils.java │ │ ├── compile │ │ ├── Compilable.java │ │ ├── generate │ │ │ ├── Generator.java │ │ │ ├── Var.java │ │ │ ├── JavaCodeGenerator.java │ │ │ └── JavaSource.java │ │ ├── compiler │ │ │ ├── JustCompiler.java │ │ │ └── JustCompilerImpl.java │ │ └── memory │ │ │ ├── JustMemClassLoader.java │ │ │ └── JustMemFileManager.java │ │ ├── exception │ │ ├── UnSupportMethodException.java │ │ ├── EvalException.java │ │ ├── CompilerException.java │ │ └── ParseException.java │ │ ├── repl │ │ ├── MockParser.java │ │ ├── MockLexer.java │ │ ├── MockGenerator.java │ │ └── MockAssignOperator.java │ │ ├── eval │ │ ├── Expressible.java │ │ ├── Evaluable.java │ │ ├── ExprBinder.java │ │ ├── ConstExpression.java │ │ └── Expression.java │ │ ├── template │ │ ├── dom │ │ │ ├── Template.java │ │ │ ├── NopComponent.java │ │ │ ├── RandomValComponent.java │ │ │ ├── DomComponent.java │ │ │ ├── DescriptionComponent.java │ │ │ ├── IgnoreDomComponent.java │ │ │ ├── SequenceDomComponent.java │ │ │ └── SingleDomComponent.java │ │ └── TemplateImpl.java │ │ ├── ast │ │ ├── function │ │ │ ├── Function.java │ │ │ ├── Operator.java │ │ │ └── ExtendFunctionExpr.java │ │ ├── tree │ │ │ ├── AstPostfixExpr.java │ │ │ ├── AstCondExpr.java │ │ │ ├── AstProgram.java │ │ │ ├── AstBinaryExpr.java │ │ │ └── AstFuncExpr.java │ │ ├── postfix │ │ │ ├── NotPostfix.java │ │ │ └── NegativePostfix.java │ │ ├── operators │ │ │ ├── OrOp.java │ │ │ ├── ModOp.java │ │ │ ├── MulOp.java │ │ │ ├── AmpersandOp.java │ │ │ ├── DivOp.java │ │ │ ├── MinusOp.java │ │ │ ├── EqualOp.java │ │ │ ├── UnEqualOp.java │ │ │ ├── PlusOp.java │ │ │ ├── LessThanOp.java │ │ │ ├── GreaterThanOp.java │ │ │ ├── LessThanEqualOp.java │ │ │ ├── GreaterThanEqualOp.java │ │ │ ├── AndOp.java │ │ │ ├── CondOp.java │ │ │ └── ArrayIndexExpr.java │ │ └── base │ │ │ └── AstLeaf.java │ │ ├── literal │ │ ├── Literal.java │ │ ├── StringLiteral.java │ │ ├── IDLiteral.java │ │ ├── BoolLiteral.java │ │ └── NumberLiteral.java │ │ ├── lexer │ │ └── Lexer.java │ │ ├── parser │ │ ├── JustParser.java │ │ └── ParserHelper.java │ │ ├── token │ │ ├── StringToken.java │ │ ├── IDToken.java │ │ ├── BoolToken.java │ │ └── NumberToken.java │ │ ├── optimizer │ │ └── Optimizer.java │ │ └── context │ │ ├── JustContext.java │ │ ├── JustMapContext.java │ │ └── JustArrayContext.java └── test │ └── java │ └── com │ └── lfkdsk │ └── justel │ ├── ast │ ├── tree │ │ ├── AstProgramTest.java │ │ ├── AstCondExprTest.java │ │ ├── AstFuncExprTest.java │ │ └── AstFuncArgumentsTest.java │ ├── postfix │ │ ├── NegativeExprTest.java │ │ ├── NotOpTest.java │ │ ├── NegativePostfixTest.java │ │ └── NotPostfixTest.java │ ├── operators │ │ ├── DivOpTest.java │ │ ├── AndOpTest.java │ │ ├── MulOpTest.java │ │ ├── EqualOpTest.java │ │ ├── MinusOpTest.java │ │ ├── OrOpTest.java │ │ ├── AmpersandOpTest.java │ │ ├── UnEqualOpTest.java │ │ ├── GreaterThanEqualOpTest.java │ │ ├── CondOpTest.java │ │ ├── LessThanOpTest.java │ │ ├── ModTest.java │ │ ├── LessThanEqualOpTest.java │ │ ├── GreaterThanOpTest.java │ │ ├── ArrayIndexExprTest.java │ │ └── DotExprTest.java │ ├── base │ │ └── AstNodeTest.java │ └── function │ │ └── ExtendFunctionExprTest.java │ ├── repl │ ├── MockAssignOperatorTest.java │ └── JustReplTest.java │ ├── compile │ ├── compiler │ │ ├── RepeatTest.java │ │ ├── CornerTest3.java │ │ └── JustCompilerImplTest.java │ └── generate │ │ └── JavaSourceTest.java │ ├── literal │ ├── BoolLiteralTest.java │ ├── StringLiteralTest.java │ ├── NumberLiteralTest.java │ └── IDLiteralTest.java │ ├── eval │ ├── EvaluableTest.java │ └── ExpressionTest.java │ ├── utils │ ├── FormatUtilsTest.java │ ├── collection │ │ ├── IndexEntryTest.java │ │ └── ArrayMapTest.java │ └── GeneratedIdTest.java │ ├── template │ ├── dom │ │ └── DomComponentTest.java │ └── TemplateImplTest.java │ └── lexer │ ├── RandomUtils.java │ └── JustLexerImplTest.java ├── .gitignore └── .travis.yml /sh/deploy.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sh/sh/history.just: -------------------------------------------------------------------------------- 1 | -q 2 | -------------------------------------------------------------------------------- /art/const.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/Just-Evaluator/HEAD/art/const.png -------------------------------------------------------------------------------- /sh/start.sh: -------------------------------------------------------------------------------- 1 | java -jar target/just-el-2.2.1-SNAPSHOT-jar-with-dependencies.jar -ae -------------------------------------------------------------------------------- /art/complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/Just-Evaluator/HEAD/art/complex.png -------------------------------------------------------------------------------- /art/simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/Just-Evaluator/HEAD/art/simple.png -------------------------------------------------------------------------------- /sh/update.sh: -------------------------------------------------------------------------------- 1 | git add -A 2 | git commit -m " update by script " 3 | git push origin master -------------------------------------------------------------------------------- /art/complex-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/Just-Evaluator/HEAD/art/complex-result.png -------------------------------------------------------------------------------- /sh/generate-jar-with-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "mvn package assembly:single" 3 | mvn package assembly:single 4 | 5 | -------------------------------------------------------------------------------- /sh/generate-jar-without-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "mvn package assembly:single -DskipTests" 3 | mvn package assembly:single -DskipTests -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/printer/Printer.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.printer; 2 | 3 | public interface Printer { 4 | void println(String var1); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/logger/LogLevel.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.logger; 2 | 3 | public enum LogLevel { 4 | 5 | /** 6 | * Prints all logs 7 | */ 8 | FULL, 9 | 10 | /** 11 | * No log will be printed 12 | */ 13 | NONE 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/Compilable.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Created by liufengkai on 2017/7/18. 7 | */ 8 | @FunctionalInterface 9 | public interface Compilable { 10 | String compile(JustContext context); 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/tree/AstProgramTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.ast.tree; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 6 | 7 | /** 8 | * Created by liufengkai on 2017/8/18. 9 | */ 10 | class AstProgramTest { 11 | 12 | @Test 13 | void testConst() { 14 | compiler("1111 + 111", null); 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/logger/LogTool.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.logger; 2 | 3 | public interface LogTool { 4 | void d(String tag, String message); 5 | 6 | void e(String tag, String message); 7 | 8 | void w(String tag, String message); 9 | 10 | void i(String tag, String message); 11 | 12 | void v(String tag, String message); 13 | 14 | void wtf(String tag, String message); 15 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/exception/UnSupportMethodException.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.exception; 2 | 3 | /** 4 | * UnSupport Method in Eval Or Compiler 5 | * 6 | * @author liufengkai 7 | * Created by liufengkai on 2017/7/24. 8 | */ 9 | public class UnSupportMethodException extends RuntimeException { 10 | 11 | public UnSupportMethodException(String message) { 12 | super(message); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | *.iml 5 | .idea/ 6 | 7 | # Log file 8 | *.log 9 | 10 | # BlueJ files 11 | *.ctxt 12 | 13 | # Mobile Tools for Java (J2ME) 14 | .mtj.tmp/ 15 | 16 | # Package Files # 17 | *.war 18 | *.ear 19 | *.zip 20 | *.tar.gz 21 | *.rar 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | hs_err_pid* 25 | target/ 26 | .classpath 27 | .project 28 | sh/history.just 29 | .settings/ -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/repl/MockParser.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.repl; 2 | 3 | import com.lfkdsk.justel.parser.BnfCom; 4 | import com.lfkdsk.justel.parser.JustParserImpl; 5 | 6 | /** 7 | * insert operator for REPL 8 | * 9 | * @author liufengkai 10 | */ 11 | public class MockParser extends JustParserImpl { 12 | 13 | public MockParser() { 14 | this.insertOperators("=", 14, BnfCom.Operators.RIGHT, MockAssignOperator.class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/eval/Expressible.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.eval; 2 | 3 | /** 4 | * Could convert to expr 5 | * 6 | * @author liufengkai 7 | * Created by liufengkai on 2017/9/8. 8 | * @see com.lfkdsk.justel.ast.base.AstNode 9 | * @see com.lfkdsk.justel.JustEL 10 | */ 11 | @FunctionalInterface 12 | public interface Expressible { 13 | 14 | /** 15 | * convert ast node to convert 16 | * 17 | * @return Expression 18 | */ 19 | Expression expr(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/Template.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | /** 4 | * Template File Interface 5 | * We just need a domCom object to 6 | * generateCode com.lfkdsk.justel.template file 7 | * 8 | * @author liufengkai 9 | * Created by liufengkai on 2017/7/19. 10 | */ 11 | @FunctionalInterface 12 | public interface Template { 13 | /** 14 | * generateCode-code com.lfkdsk.justel.template 15 | * 16 | * @return domCom-node 17 | */ 18 | DomCom generateTemplate(); 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/repl/MockAssignOperatorTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.repl; 2 | 3 | import com.lfkdsk.justel.JustEL; 4 | import com.lfkdsk.justel.context.JustMapContext; 5 | import org.junit.jupiter.api.Test; 6 | 7 | class MockAssignOperatorTest { 8 | 9 | @Test 10 | void eval() { 11 | JustEL.builder() 12 | .parser(new MockParser()) 13 | .lexer(new MockLexer()) 14 | .create() 15 | .eval("lfkdsk = \"lfkdsk\"", new JustMapContext()); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/exception/EvalException.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.exception; 2 | 3 | import com.lfkdsk.justel.ast.base.AstNode; 4 | 5 | /** 6 | * Eval Exception 7 | * 8 | * @author liufengkai 9 | * Created by liufengkai on 17/7/18. 10 | */ 11 | 12 | public class EvalException extends RuntimeException { 13 | 14 | public EvalException(String msg) { 15 | super(msg); 16 | } 17 | 18 | public EvalException(String msg, AstNode tree) { 19 | super(msg + " " + tree.location()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/exception/CompilerException.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.exception; 2 | 3 | import com.lfkdsk.justel.ast.base.AstNode; 4 | 5 | /** 6 | * Compiler Exception 7 | * 8 | * @author liufengkai 9 | * Created by liufengkai on 2017/7/20. 10 | */ 11 | public class CompilerException extends RuntimeException { 12 | 13 | public CompilerException(String message) { 14 | super(message); 15 | } 16 | 17 | public CompilerException(String msg, AstNode tree) { 18 | super(msg + " " + tree.location()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/repl/MockLexer.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.repl; 2 | 3 | import com.lfkdsk.justel.lexer.JustLexerImpl; 4 | import com.lfkdsk.justel.token.SepToken; 5 | 6 | import java.io.Reader; 7 | 8 | /** 9 | * insert symbol = operator for REPL 10 | * 11 | * @author liufengkai 12 | */ 13 | public class MockLexer extends JustLexerImpl { 14 | 15 | public MockLexer() { 16 | insertSymbol("=", new SepToken(2000, "=")); 17 | } 18 | 19 | public MockLexer(Reader reader) { 20 | super(reader); 21 | insertSymbol("=", new SepToken(2000, "=")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/eval/Evaluable.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.eval; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Evaluable => To mark this node could be evaluated. 7 | * 8 | * @author liufengkai 9 | * Created by liufengkai on 2017/7/18. 10 | * @see Expression 11 | * @see ConstExpression 12 | * @see com.lfkdsk.justel.ast.base.AstNode 13 | */ 14 | @FunctionalInterface 15 | public interface Evaluable { 16 | 17 | /** 18 | * call this node 19 | * 20 | * @param context context => 21 | * @return the result name 22 | */ 23 | Object eval(JustContext context); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/collection/Tuple.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.collection; 2 | 3 | /** 4 | * Tuple 5 | * 6 | * @author liufengkai 7 | * Created by liufengkai on 2017/8/18. 8 | */ 9 | public class Tuple { 10 | public final F first; 11 | public final S second; 12 | 13 | public Tuple(F first, S second) { 14 | this.first = first; 15 | this.second = second; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "Tuple{" + 21 | "first=" + first + 22 | ", second=" + second + 23 | '}'; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/function/Function.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.function; 10 | 11 | /** 12 | * Created by liufengkai on 2017/7/27. 13 | */ 14 | public interface Function { 15 | 16 | String funcName(); 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/compile/compiler/RepeatTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.compiler; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.context.JustMapContext; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static com.lfkdsk.justel.compile.compiler.CompareTest.compiler; 8 | 9 | /** 10 | * Created by liufengkai on 2017/9/28. 11 | */ 12 | public class RepeatTest { 13 | static String expr = "i == 100 || i == 100|| i == 100|| i == 100|| i == 100"; 14 | 15 | @Test 16 | void testRepeat() { 17 | JustContext vars = new JustMapContext(); 18 | vars.put("i", 100); 19 | compiler(expr, vars); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/eval/ExprBinder.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.eval; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | public final class ExprBinder { 6 | private final JustContext contexts; 7 | 8 | private final String expr; 9 | 10 | private ExprBinder(JustContext contexts, String expr) { 11 | this.contexts = contexts; 12 | this.expr = expr; 13 | } 14 | 15 | public static ExprBinder of(JustContext contexts, String expr) { 16 | return new ExprBinder(contexts, expr); 17 | } 18 | 19 | public JustContext getContexts() { 20 | return contexts; 21 | } 22 | 23 | public String getExpr() { 24 | return expr; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/literal/BoolLiteralTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.literal; 2 | 3 | import com.lfkdsk.justel.utils.logger.Logger; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 7 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 8 | import static org.junit.jupiter.api.Assertions.*; 9 | 10 | /** 11 | * Created by liufengkai on 2017/8/10. 12 | */ 13 | class BoolLiteralTest { 14 | 15 | @Test 16 | void boolEval() { 17 | runExpr("true", true, null); 18 | } 19 | 20 | @Test 21 | void boolCompile() { 22 | Logger.init(); 23 | Logger.i(compiler("true", null)); 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/eval/EvaluableTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.eval; 2 | 3 | import com.lfkdsk.justel.ast.base.AstNode; 4 | import com.lfkdsk.justel.lexer.JustLexerImpl; 5 | import com.lfkdsk.justel.parser.JustParserImpl; 6 | import com.lfkdsk.justel.utils.logger.Logger; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static com.lfkdsk.justel.utils.FormatUtils.reformatAstPrint; 10 | 11 | class EvaluableTest { 12 | 13 | @Test 14 | void evalTest() { 15 | Logger.init(); 16 | AstNode node = new JustParserImpl().parser(new JustLexerImpl().scanner("\"lfkdsk\" + lfkdsk + 10000 + 100.0")); 17 | String reformat = reformatAstPrint(node.toString()); 18 | 19 | Logger.v(reformat); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/literal/StringLiteralTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.literal; 2 | 3 | import com.lfkdsk.justel.utils.logger.Logger; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 7 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 8 | import static org.junit.jupiter.api.Assertions.*; 9 | 10 | /** 11 | * Created by liufengkai on 2017/8/10. 12 | */ 13 | class StringLiteralTest { 14 | 15 | @Test 16 | void stringEval() { 17 | runExpr("\"lfkdsk\"", true, null); 18 | } 19 | 20 | @Test 21 | void stringCompile() { 22 | Logger.init(); 23 | Logger.i(compiler("\"lfkdsk\"", null)); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/NopComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Nop Component. 7 | * nopString will not be added to builder. 8 | * 9 | * @author liufengkai 10 | * Created by liufengkai on 2017/7/19. 11 | */ 12 | public class NopComponent implements DomComponent { 13 | 14 | public NopComponent(String... nopString) { 15 | // nopString useless 16 | } 17 | 18 | @Override 19 | public StringBuilder generateCode(JustContext context, StringBuilder builder) { 20 | return builder; 21 | } 22 | 23 | @Override 24 | public boolean isValidate(JustContext context) { 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/RandomValComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.utils.GeneratedId; 5 | 6 | /** 7 | * Random Value. 8 | * use generate id to create node. 9 | * 10 | * @author liufengkai 11 | * Created by liufengkai on 2017/7/20. 12 | */ 13 | public class RandomValComponent implements DomComponent { 14 | 15 | @Override 16 | public StringBuilder generateCode(JustContext context, StringBuilder builder) { 17 | return builder.append("val").append(GeneratedId.generateAtomId()); 18 | } 19 | 20 | @Override 21 | public boolean isValidate(JustContext context) { 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/logger/Printer.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.logger; 2 | 3 | public interface Printer { 4 | 5 | Printer t(String tag, int methodCount); 6 | 7 | Settings init(String tag); 8 | 9 | Settings getSettings(); 10 | 11 | void d(String message, Object... args); 12 | 13 | void e(String message, Object... args); 14 | 15 | void e(Throwable throwable, String message, Object... args); 16 | 17 | void w(String message, Object... args); 18 | 19 | void i(String message, Object... args); 20 | 21 | void v(String message, Object... args); 22 | 23 | void wtf(String message, Object... args); 24 | 25 | void json(String json); 26 | 27 | void xml(String xml); 28 | 29 | void clear(); 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/compile/compiler/CornerTest3.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.compiler; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.context.JustMapContext; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static com.lfkdsk.justel.compile.compiler.CompareTest.compiler; 8 | 9 | 10 | /** 11 | * Created by liufengkai on 2017/8/11. 12 | */ 13 | public class CornerTest3 { 14 | @Test 15 | void ELEngineCornerTest() { 16 | JustContext vars = new JustMapContext(); 17 | vars.put("i", 100); 18 | vars.put("pi", 3.14d); 19 | vars.put("d", -3.9); 20 | vars.put("b", (byte) 4); 21 | compiler(" pi*d+b-(1000-d*b/pi)/(pi+99-i*d)-i*pi*d/b", vars); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/DomComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Basic DomComponent. 7 | * 8 | * @author liufengkai 9 | * Created by liufengkai on 2017/7/18. 10 | */ 11 | public interface DomComponent { 12 | 13 | /** 14 | * Generate-Code 15 | * 16 | * @param context Vars-Context 17 | * @param builder Builder 18 | * @return return the builder in generateCode 19 | */ 20 | StringBuilder generateCode(JustContext context, StringBuilder builder); 21 | 22 | /** 23 | * isValidate 24 | * 25 | * @param context Vars-Context 26 | * @return is validate 27 | */ 28 | boolean isValidate(JustContext context); 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/tree/AstCondExprTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.ast.tree; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.context.JustMapContext; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 8 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 9 | 10 | /** 11 | * Created by liufengkai on 2017/8/10. 12 | */ 13 | class AstCondExprTest { 14 | 15 | @Test 16 | void condExpr() { 17 | runExpr("true ? 100 : -100", true, null); 18 | } 19 | 20 | @Test 21 | void condCompiler() { 22 | JustContext context = new JustMapContext(); 23 | context.put("lfkdsk", 101); 24 | compiler("lfkdsk > 100 ? 100 : -100", context); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/logger/DebugLogTool.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.logger; 2 | 3 | 4 | import com.lfkdsk.justel.utils.printer.Log; 5 | 6 | public class DebugLogTool implements LogTool { 7 | 8 | public void d(String tag, String message) { 9 | Log.d(tag, message); 10 | } 11 | 12 | public void e(String tag, String message) { 13 | Log.e(tag, message); 14 | } 15 | 16 | public void w(String tag, String message) { 17 | Log.w(tag, message); 18 | } 19 | 20 | public void i(String tag, String message) { 21 | Log.i(tag, message); 22 | } 23 | 24 | public void v(String tag, String message) { 25 | Log.v(tag, message); 26 | } 27 | 28 | public void wtf(String tag, String message) { 29 | Log.wtf(tag, message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/eval/ConstExpression.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.eval; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.utils.ObjectHelper; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | /** 8 | * Constant Expression 9 | * 10 | * @author liufengkai 11 | * Created by liufengkai on 2017/8/11. 12 | * @see com.lfkdsk.justel.ast.tree.AstProgram 13 | * @see com.lfkdsk.justel.JustEL 14 | */ 15 | public final class ConstExpression implements Expression { 16 | 17 | private final Object constVal; 18 | 19 | public ConstExpression(@NotNull Object constVal) { 20 | this.constVal = ObjectHelper.requireNonNull(constVal, "const expression could not null"); 21 | } 22 | 23 | @Override 24 | public Object eval(JustContext context) { 25 | return constVal; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/literal/Literal.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.literal; 2 | 3 | import com.lfkdsk.justel.ast.base.AstLeaf; 4 | import com.lfkdsk.justel.context.JustContext; 5 | import com.lfkdsk.justel.exception.UnSupportMethodException; 6 | import com.lfkdsk.justel.token.Token; 7 | 8 | /** 9 | * Literal is an AstLeaf. 10 | * Literal is an wrapper of LiterToken. 11 | * 12 | * @author liufengkai 13 | * Created by liufengkai on 2017/7/22. 14 | */ 15 | public abstract class Literal extends AstLeaf { 16 | 17 | public Literal(Token token) { 18 | super(token); 19 | } 20 | 21 | public String name() { 22 | return token.getText(); 23 | } 24 | 25 | @Override 26 | public Object eval(JustContext env) { 27 | throw new UnSupportMethodException("Cannot call abstract literal " + token.toString()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/eval/ExpressionTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.eval; 2 | 3 | import com.lfkdsk.justel.JustEL; 4 | import com.lfkdsk.justel.ast.base.AstNodeTest; 5 | import com.lfkdsk.justel.context.JustMapContext; 6 | import com.lfkdsk.justel.utils.logger.Logger; 7 | import org.junit.jupiter.api.Test; 8 | 9 | /** 10 | * Created by liufengkai on 2017/9/4. 11 | */ 12 | class ExpressionTest { 13 | 14 | @Test 15 | void eval() { 16 | Logger.init(); 17 | Logger.i(JustEL 18 | .builder() 19 | .parser(lexer -> AstNodeTest.toNode("lfkdsk")) 20 | .compiler(code -> context -> context.get("lfkdsk")) 21 | .create() 22 | .eval("lfkdsk", new JustMapContext() {{ 23 | put("lfkdsk", 1000); 24 | }}) 25 | .toString()); 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/GeneratedId.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * Generate spec id : use atomic integer => id 7 | * 8 | * @author liufengkai 9 | * Created by liufengkai on 16/7/14. 10 | */ 11 | public final class GeneratedId { 12 | 13 | private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 14 | 15 | private GeneratedId() {} 16 | 17 | /** 18 | * Generate a value suitable for use 19 | * 20 | * @return a generated ID value 21 | */ 22 | public static int generateAtomId() { 23 | for (; ; ) { 24 | final int result = sNextGeneratedId.get(); 25 | final int newValue = result + 1; 26 | if (sNextGeneratedId.compareAndSet(result, newValue)) { 27 | 28 | return result; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/DescriptionComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Description Component. 7 | * des will be skip. 8 | * 9 | * @author liufengkai 10 | * Created by liufengkai on 2017/7/19. 11 | */ 12 | public class DescriptionComponent implements DomComponent { 13 | 14 | private String[] desString; 15 | 16 | public DescriptionComponent(String[] desString) { 17 | this.desString = desString; 18 | } 19 | 20 | @Override 21 | public StringBuilder generateCode(JustContext context, StringBuilder builder) { 22 | for (String des : desString) { 23 | builder.append("//").append(des).append("\n"); 24 | } 25 | return builder; 26 | } 27 | 28 | @Override 29 | public boolean isValidate(JustContext context) { 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/literal/NumberLiteralTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.literal; 2 | 3 | import com.lfkdsk.justel.utils.logger.Logger; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 7 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 8 | import static org.junit.jupiter.api.Assertions.*; 9 | 10 | /** 11 | * Created by liufengkai on 2017/8/10. 12 | */ 13 | class NumberLiteralTest { 14 | 15 | @Test 16 | void numberEval() { 17 | runExpr("123333333L", true, null); 18 | runExpr("123333333.100000", true, null); 19 | runExpr("0.22222222", true, null); 20 | } 21 | 22 | @Test 23 | void numberCompile() { 24 | Logger.init(); 25 | 26 | Logger.i(compiler("123333333L",null)); 27 | Logger.i(compiler("123333333.100000",null)); 28 | Logger.i(compiler("0.22222222",null)); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/IgnoreDomComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Ignore Component. 7 | * just control generateCode code not about exchange Vars 8 | * 9 | * @author liufengkai 10 | * Created by liufengkai on 2017/7/18. 11 | */ 12 | public class IgnoreDomComponent implements DomComponent { 13 | 14 | private String[] ignoreDomString; 15 | 16 | IgnoreDomComponent(String... ignoreDomString) { 17 | this.ignoreDomString = ignoreDomString; 18 | } 19 | 20 | @Override 21 | public StringBuilder generateCode(JustContext context, StringBuilder builder) { 22 | for (String ignore : ignoreDomString) { 23 | builder.append(ignore).append(" "); 24 | } 25 | return builder; 26 | } 27 | 28 | @Override 29 | public boolean isValidate(JustContext context) { 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/literal/StringLiteral.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.literal; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.token.Token; 5 | 6 | import static com.lfkdsk.justel.utils.TypeUtils.isNull; 7 | 8 | /** 9 | * String Literal => 10 | * - "lfkdsk" 11 | * - "\"lfkdsk\"" 12 | * 13 | * @author liufengkai 14 | * Created by liufengkai on 2017/7/18. 15 | */ 16 | public class StringLiteral extends Literal { 17 | 18 | public StringLiteral(Token token) { 19 | super(token); 20 | } 21 | 22 | public String value() { 23 | return token.getText(); 24 | } 25 | 26 | @Override 27 | public Object eval(JustContext env) { 28 | if (!isNull(value())) { 29 | return value(); 30 | } 31 | 32 | return super.eval(env); 33 | } 34 | 35 | @Override 36 | public String compile(JustContext env) { 37 | return "(\"" + value() + "\")"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/eval/Expression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.eval; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | 13 | /** 14 | * Expression : Evaluable Expression. 15 | * 16 | * @author liufengkai 17 | * Created by liufengkai on 2017/7/20. 18 | * @see Evaluable 19 | * @see com.lfkdsk.justel.JustEL 20 | */ 21 | @FunctionalInterface 22 | public interface Expression extends Evaluable { 23 | 24 | /** 25 | * Eval value with context 26 | * 27 | * @param context context => 28 | * @return value 29 | */ 30 | @Override 31 | Object eval(JustContext context); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/postfix/NegativeExprTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.postfix; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 14 | 15 | /** 16 | * Created by liufengkai on 2017/7/28. 17 | */ 18 | class NegativeExprTest { 19 | 20 | @Test 21 | void testInteger() { 22 | runExpr("-11111", true, null); 23 | } 24 | 25 | @Test 26 | void testFloat() { 27 | runExpr("-1111.000111f", true, null); 28 | } 29 | 30 | @Test 31 | void testDouble() { 32 | runExpr("-1111.00110111d", true, null); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/function/Operator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.function; 10 | 11 | import com.lfkdsk.justel.ast.base.AstLeaf; 12 | import com.lfkdsk.justel.token.Token; 13 | 14 | /** 15 | * Operator 16 | * eq: factor { OP factor } 17 | * 18 | * @author liufengkai 19 | * Created by liufengkai on 2017/7/26. 20 | */ 21 | public class Operator extends AstLeaf { 22 | 23 | public Operator(Token token) { 24 | super(token); 25 | } 26 | 27 | public String operator() { 28 | return getText(); 29 | } 30 | 31 | public String getText() { 32 | return token.getText(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/tree/AstFuncExprTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 14 | 15 | /** 16 | * Created by liufengkai on 2017/8/2. 17 | */ 18 | class AstFuncExprTest { 19 | 20 | @Test 21 | void testAstFunc() { 22 | runExpr("lfkdsk.function(1111,2222)", false, null); 23 | } 24 | 25 | @Test 26 | void testPoint() { 27 | runExpr("a.c", false, null); 28 | } 29 | 30 | @Test 31 | void testAstFuncParser() { 32 | runExpr("function(1111,2222)", false, null); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/table/Charr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.lfkdsk.justel.utils.table; 7 | 8 | /** 9 | * 10 | * @author Thedath Oudarya 11 | */ 12 | class Charr { 13 | 14 | protected static final char S = ' '; 15 | 16 | protected static final char NL = '\n'; 17 | 18 | protected static final char P = '+'; 19 | 20 | protected static final char D = '-'; 21 | 22 | protected static final char VL = '|'; 23 | 24 | private final int x; 25 | 26 | private final int y; 27 | 28 | private final char c; 29 | 30 | protected Charr(int x, int y, char c) { 31 | this.x = x; 32 | this.y = y; 33 | this.c = c; 34 | } 35 | 36 | protected int getX() { 37 | return x; 38 | } 39 | 40 | protected int getY() { 41 | return y; 42 | } 43 | 44 | protected char getC() { 45 | return c; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/postfix/NotOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.postfix; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 16 | 17 | /** 18 | * Created by liufengkai on 2017/7/28. 19 | */ 20 | class NotOpTest { 21 | 22 | @Test 23 | void testBoolean() { 24 | runExpr("!true", true, null); 25 | } 26 | 27 | @Test 28 | void testID() { 29 | JustContext context = new JustMapContext(); 30 | context.put("lfkdsk", true); 31 | runExpr("!lfkdsk", true, context); 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/utils/FormatUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils; 2 | 3 | import com.lfkdsk.justel.utils.logger.Logger; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static com.lfkdsk.justel.utils.FormatUtils.insertNewLine; 7 | import static com.lfkdsk.justel.utils.FormatUtils.reformatAstPrint; 8 | 9 | class FormatUtilsTest { 10 | 11 | @Test 12 | void testReformatString() { 13 | Logger.init(); 14 | Logger.v(reformatAstPrint("((+ lfkdsk 1))")); 15 | Logger.v(reformatAstPrint("((- (+ lfkdsk 1) lfkdsk))")); 16 | Logger.v(reformatAstPrint("((== (- (+ lfkdsk 1) lfkdsk) true))")); 17 | } 18 | 19 | @Test 20 | void beautifulPrint() { 21 | System.out.println(FormatUtils.beautifulPrint("lfkdsk", "11111111111111111", "fffff")); 22 | } 23 | 24 | @Test 25 | void beautifulReformat() { 26 | System.out.println(FormatUtils.beautifulPrint("lfkdsk", "11111111111111111", 27 | insertNewLine(new StringBuilder(reformatAstPrint("(== (- (+ lfkdsk 1) lfkdsk) true)")), 28 | "\n","").toString())); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/repl/MockGenerator.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.repl; 2 | 3 | import com.lfkdsk.justel.ast.base.AstNode; 4 | import com.lfkdsk.justel.compile.generate.Generator; 5 | import com.lfkdsk.justel.compile.generate.JavaCodeGenerator; 6 | import com.lfkdsk.justel.compile.generate.JavaSource; 7 | import com.lfkdsk.justel.context.JustContext; 8 | import com.lfkdsk.justel.template.TemplateImpl; 9 | import com.lfkdsk.justel.template.dom.Template; 10 | 11 | public class MockGenerator implements Generator { 12 | private JavaCodeGenerator javaCodeGenerator = new JavaCodeGenerator(); 13 | private Template template = new MockTemplate(); 14 | 15 | public static class MockTemplate extends TemplateImpl { 16 | MockTemplate() { 17 | importGen.reset(importGen.sep("import com.lfkdsk.justel.repl.ReplMethodHelper;")); 18 | } 19 | } 20 | 21 | 22 | @Override 23 | public JavaSource generate(JustContext context, AstNode rootNode) { 24 | javaCodeGenerator.setMTemplate(template.generateTemplate()); 25 | return javaCodeGenerator.generate(context, rootNode); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/lexer/Lexer.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.lexer; 2 | 3 | import com.lfkdsk.justel.token.Token; 4 | import com.lfkdsk.justel.utils.collection.ArrayQueue; 5 | 6 | import java.util.Queue; 7 | 8 | /** 9 | * Lexer 10 | * File/String Lexer. We wont focus on 11 | * the Lexer is a real Lexer or just a 12 | * list message. 13 | * Created by liufengkai on 2017/7/18. 14 | */ 15 | @FunctionalInterface 16 | public interface Lexer { 17 | 18 | // /** 19 | // * peek first serial nodes 20 | // * 21 | // * @param index first serial nodes 22 | // * @return Token 23 | // */ 24 | // Token peek(int index); 25 | // 26 | // /** 27 | // * get first node of list 28 | // * 29 | // * @return Token 30 | // */ 31 | // Token read(); 32 | 33 | 34 | // void reset(String expr); 35 | 36 | Queue scanner(String expr); 37 | 38 | /** 39 | * has more tokens in Lexer 40 | * 41 | * @return has more? 42 | */ 43 | default boolean hasMore() { 44 | return true; 45 | } 46 | 47 | default Queue tokens() { 48 | return new ArrayQueue<>(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/parser/JustParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.parser; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.exception.ParseException; 13 | import com.lfkdsk.justel.token.Token; 14 | 15 | import java.util.Queue; 16 | 17 | /** 18 | * Just Parser Interface 19 | * 20 | * @author liufengkai 21 | * Created by liufengkai on 2017/7/26. 22 | */ 23 | @FunctionalInterface 24 | public interface JustParser { 25 | 26 | 27 | /** 28 | * Parse with Lexer(Provide Tokens) 29 | * 30 | * @param lexer Tokens Lexer 31 | * @return Root Node of AST 32 | * @throws ParseException Parse 33 | */ 34 | AstNode parser(Queue lexer) throws ParseException; 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/postfix/NegativePostfixTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.ast.postfix; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.context.JustMapContext; 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 9 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 10 | import static org.junit.jupiter.api.Assertions.*; 11 | 12 | /** 13 | * Created by liufengkai on 2017/8/10. 14 | */ 15 | class NegativePostfixTest { 16 | 17 | @Test 18 | void negativeEval() { 19 | JustContext context = new JustMapContext(); 20 | context.put("lfkdsk", 100); 21 | String result = runExpr("- lfkdsk ", true, context); 22 | Assertions.assertEquals(Integer.parseInt(result), -100); 23 | } 24 | 25 | @Test 26 | void negativeCompiler() { 27 | JustContext context = new JustMapContext(); 28 | context.put("lfkdsk", 100); 29 | String result = compiler("- lfkdsk ", context); 30 | Assertions.assertEquals(Integer.parseInt(result), -100); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/generate/Generator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.compile.generate; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.context.JustContext; 13 | 14 | /** 15 | * Basic Generator 16 | * Generate Source Code -> NEED: 17 | * 1. context => generate var 18 | * 2. Ast node => return expr 19 | * 20 | * @author liufengkai 21 | * Created by liufengkai on 2017/8/4. 22 | * @see JavaCodeGenerator 23 | */ 24 | @FunctionalInterface 25 | public interface Generator { 26 | 27 | /** 28 | * Generate Source Code 29 | * 30 | * @param context context-env 31 | * @param rootNode root-node 32 | * @return SourceNode 33 | */ 34 | JavaSource generate(JustContext context, AstNode rootNode); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/compiler/JustCompiler.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.compiler; 2 | 3 | import com.lfkdsk.justel.compile.generate.JavaSource; 4 | import com.lfkdsk.justel.eval.Expression; 5 | 6 | /** 7 | * Just Compiler Class 8 | * 9 | * @author liufengkai 10 | * Created by liufengkai on 2017/7/20. 11 | */ 12 | @FunctionalInterface 13 | public interface JustCompiler { 14 | 15 | /** 16 | * Compile JavaSource Code 17 | * 18 | * @param code source code 19 | * @return Expression 20 | * @see Expression 21 | * @see JavaSource 22 | */ 23 | Expression compile(JavaSource code); 24 | 25 | /** 26 | * Load Class => ClassLoader 27 | * 28 | * @param loader loader 29 | * @param classQualifiedName class's qualified name 30 | * @param spec clazz 31 | * @return object 32 | * @throws ClassNotFoundException 33 | */ 34 | @SuppressWarnings("unchecked") 35 | default Class loadClass(ClassLoader loader, String classQualifiedName) 36 | throws ClassNotFoundException { 37 | return (Class) loader.loadClass(classQualifiedName); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/postfix/NotPostfixTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.ast.postfix; 2 | 3 | import com.lfkdsk.justel.context.JustMapContext; 4 | import org.junit.jupiter.api.Assertions; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 8 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 9 | 10 | /** 11 | * Created by liufengkai on 2017/8/10. 12 | */ 13 | class NotPostfixTest { 14 | 15 | @Test 16 | void notEval() { 17 | String result = runExpr("!true", true, null); 18 | Assertions.assertFalse(Boolean.parseBoolean(result)); 19 | } 20 | 21 | @Test 22 | void notCompiler() { 23 | String result = compiler("!true", null); 24 | Assertions.assertFalse(Boolean.parseBoolean(result)); 25 | } 26 | 27 | @Test 28 | void notEqualCompiler() { 29 | String result = compiler("lfkdsk == 1000 && !(lfkdsk == 1000) && lfkdsk == 1000 && lfkdsk == 1000 && lfkdsk == 1000 && lfkdsk == 1000 && lfkdsk == 1000" 30 | , new JustMapContext(){{ 31 | put("lfkdsk",1000); 32 | }}); 33 | Assertions.assertFalse(Boolean.parseBoolean(result)); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/exception/ParseException.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.exception; 2 | 3 | import com.lfkdsk.justel.token.Token; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * ParseException Parser Error 9 | * 10 | * @author liufengkai Created by liufengkai on 16/7/11. 11 | */ 12 | public class ParseException extends RuntimeException { 13 | 14 | public ParseException(Token token) { 15 | this("", token); 16 | } 17 | 18 | public ParseException(String msg, Token token) { 19 | super("syntax error around " + location(token) + " . " + msg); 20 | } 21 | 22 | /** 23 | * get location in file 24 | * 25 | * @param token com.lfkdsk.justel.token 26 | * @return return the description of com.lfkdsk.justel.exception 27 | */ 28 | private static String location(Token token) { 29 | if (token == Token.EOF) { 30 | return " the last of line "; 31 | } else { 32 | return "\"" + token.getText() + "\" at line " + token.getLineNumber(); 33 | } 34 | } 35 | 36 | public ParseException(IOException exc) { 37 | super(exc); 38 | } 39 | 40 | public ParseException(String msg) { 41 | super(msg); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/SequenceDomComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | /** 9 | * Sequence Component 10 | * We could bind a set of components in one Sequence. 11 | * 12 | * @author liufengkai 13 | * Created by liufengkai on 2017/7/18. 14 | */ 15 | public class SequenceDomComponent implements DomComponent { 16 | 17 | private List sequenceDom; 18 | 19 | SequenceDomComponent(DomComponent... sequenceDom) { 20 | this(Arrays.asList(sequenceDom)); 21 | } 22 | 23 | SequenceDomComponent(List sequenceDom) { 24 | this.sequenceDom = sequenceDom; 25 | } 26 | 27 | @Override 28 | public StringBuilder generateCode(JustContext context, StringBuilder builder) { 29 | for (DomComponent domComponent : sequenceDom) { 30 | domComponent.generateCode(context, builder); 31 | } 32 | return builder; 33 | } 34 | 35 | @Override 36 | public boolean isValidate(JustContext context) { 37 | return sequenceDom.stream().allMatch((DomComponent con) -> con.isValidate(context)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/token/StringToken.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.token; 2 | 3 | /** 4 | * String Token. 5 | * used in lexer => will be add to spec Literal. 6 | * 7 | * @author liufengkai 8 | * Created by liufengkai on 2017/7/24. 9 | * @see com.lfkdsk.justel.token.Token 10 | * @see com.lfkdsk.justel.lexer.Lexer 11 | * @see com.lfkdsk.justel.literal.StringLiteral 12 | */ 13 | public class StringToken extends Token implements Comparable { 14 | private String text; 15 | 16 | public StringToken(int lineNumber, String text) { 17 | super(lineNumber, Token.STRING); 18 | this.text = text; 19 | } 20 | 21 | @Override 22 | public String getText() { 23 | return text; 24 | } 25 | 26 | @Override 27 | public boolean isString() { 28 | return true; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "StringToken{" + 34 | "text='" + text + '\'' + 35 | ", lineNumber=" + lineNumber + 36 | ", tag=" + tag + 37 | '}'; 38 | } 39 | 40 | @Override 41 | public int compareTo(StringToken o) { 42 | return getText().compareTo(o.getText()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/tree/AstPostfixExpr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | 13 | /** 14 | * Abstract Postfix Expr => 15 | * - [ expr ] 16 | * - .id 17 | * - ( args | null ) 18 | * 19 | * @author liufengkai 20 | * Created by liufengkai on 2017/7/27. 21 | * @see com.lfkdsk.justel.ast.operators.ArrayIndexExpr 22 | * @see com.lfkdsk.justel.ast.operators.DotExpr 23 | * @see AstFuncArguments 24 | */ 25 | public interface AstPostfixExpr { 26 | 27 | /** 28 | * Evaluate Postfix Expr 29 | * 30 | * @param env env 31 | * @param value name 32 | * @return eval result 33 | */ 34 | Object eval(JustContext env, Object value); 35 | 36 | Object compile(JustContext env, Object value, StringBuilder builder); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/literal/IDLiteral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.literal; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.exception.EvalException; 13 | import com.lfkdsk.justel.token.Token; 14 | 15 | /** 16 | * ID Literal. 17 | * => The Language support's ID Literal 18 | * 19 | * @author liufengkai 20 | * Created by liufengkai on 2017/7/26. 21 | */ 22 | public class IDLiteral extends Literal { 23 | 24 | public IDLiteral(Token token) { 25 | super(token); 26 | } 27 | 28 | @Override 29 | public Object eval(JustContext env) { 30 | Object value = env.get(name()); 31 | 32 | if (value == null) { 33 | throw new EvalException("undefined name: " + name(), this); 34 | } else { 35 | return value; 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/token/IDToken.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.token; 2 | 3 | /** 4 | * ID Token. 5 | * 6 | * @author liufengkai 7 | * Created by liufengkai on 2017/7/24. 8 | * @see com.lfkdsk.justel.token.Token 9 | * @see com.lfkdsk.justel.lexer.JustLexerImpl 10 | * @see com.lfkdsk.justel.literal.IDLiteral 11 | */ 12 | public class IDToken extends Token { 13 | 14 | /** 15 | * Token String. 16 | */ 17 | private String text; 18 | 19 | /** 20 | * ID Token 21 | * 22 | * @param lineNumber local number. 23 | * @param text text token 24 | */ 25 | public IDToken(int lineNumber, String text) { 26 | super(lineNumber, Token.ID); 27 | this.text = text; 28 | 29 | if (text.equals(Token.EOL)) { 30 | this.tag = Token.EOL_TAG; 31 | } 32 | } 33 | 34 | public boolean isIdentifier() { 35 | return true; 36 | } 37 | 38 | @Override 39 | public String getText() { 40 | return text; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "IDToken{" + 46 | "text='" + text + '\'' + 47 | ", lineNumber=" + lineNumber + 48 | ", tag=" + tag + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/literal/BoolLiteral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.literal; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.token.Token; 13 | 14 | import static com.lfkdsk.justel.token.BoolToken.BooleanEnum.TRUE; 15 | import static com.lfkdsk.justel.token.BoolToken.booleanValue; 16 | 17 | /** 18 | * Boolean Literal => Support two Boolean Value. 19 | * - true 20 | * - false 21 | * 22 | * @author liufengkai 23 | * Created by liufengkai on 2017/7/26. 24 | */ 25 | public class BoolLiteral extends Literal { 26 | 27 | public BoolLiteral(Token token) { 28 | super(token); 29 | } 30 | 31 | public boolean value() { 32 | return booleanValue(token.getText()) == TRUE; 33 | } 34 | 35 | @Override 36 | public Object eval(JustContext env) { 37 | return value() ? Boolean.TRUE : Boolean.FALSE; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/DivOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 14 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 15 | 16 | /** 17 | * Created by liufengkai on 2017/7/29. 18 | */ 19 | class DivOpTest { 20 | 21 | @Test 22 | void testDivInteger() { 23 | runExpr("1 / 0", true, null); 24 | } 25 | 26 | @Test 27 | void testDivIntInt() { 28 | runExpr("1 / 1", true, null); 29 | } 30 | 31 | @Test 32 | void testDivIntFloat() { 33 | runExpr("2 / 0.5f ", true, null); 34 | } 35 | 36 | @Test 37 | void testDivIntDouble() { 38 | runExpr("1 / 0.111111d", true, null); 39 | } 40 | 41 | @Test 42 | void testDivCompiler() { 43 | compiler("1 / 0.1111111d", null); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/AndOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 16 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 17 | 18 | /** 19 | * Created by liufengkai on 2017/7/27. 20 | */ 21 | class AndOpTest { 22 | @Test 23 | void eval() { 24 | runExpr("true && true", true, new JustMapContext()); 25 | } 26 | 27 | @Test 28 | void idAndEval() { 29 | JustContext context = new JustMapContext(); 30 | context.put("lfkdsk", Boolean.TRUE); 31 | runExpr("lfkdsk && lfkdsk", true, context); 32 | } 33 | 34 | @Test 35 | void testAndCompiler() { 36 | compiler("true && true", new JustMapContext()); 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/dom/SingleDomComponent.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | 5 | /** 6 | * Bind Alternate Structure In AST 7 | * Usage: 8 | * DomCom.bind("${localVars}") 9 | * We bind a var block in com.lfkdsk.justel.template file and it will 10 | * be replace in structure in generateCode code. 11 | * 12 | * @author liufengkai 13 | * Created by liufengkai on 2017/7/18. 14 | */ 15 | public class SingleDomComponent implements DomComponent { 16 | 17 | /** 18 | * var name eg: ${localVars} which will be 19 | * never changed in life-circle 20 | */ 21 | private final String arg; 22 | 23 | SingleDomComponent(String arg) { 24 | this.arg = arg; 25 | } 26 | 27 | /** 28 | * generateCode local level code 29 | * 30 | * @param context var-com.lfkdsk.justel.context 31 | * @param builder string-append-builder 32 | * @return appended string builder 33 | */ 34 | @Override 35 | public StringBuilder generateCode(JustContext context, 36 | StringBuilder builder) { 37 | return builder.append(context.get(arg).toString()).append(" "); 38 | } 39 | 40 | @Override 41 | public boolean isValidate(JustContext context) { 42 | return context.contain(arg); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/MulOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 14 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 15 | 16 | /** 17 | * Created by liufengkai on 2017/7/29. 18 | */ 19 | class MulOpTest { 20 | 21 | @Test 22 | void testMulInteger() { 23 | runExpr("2 * 2000", true, null); 24 | } 25 | 26 | @Test 27 | void testMulFloat() { 28 | runExpr("2.1111f * 2000.1111f", true, null); 29 | } 30 | 31 | @Test 32 | void testMulDouble() { 33 | runExpr("2.11111d * 2000.222222d", true, null); 34 | } 35 | 36 | @Test 37 | void testMulCompiler() { 38 | compiler("2 * 2000", null); 39 | 40 | compiler("2.1111f * 2000.1111f", null); 41 | 42 | compiler("2.11111d * 2000.222222d", null); 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by liufengkai on 16/4/16. 7 | */ 8 | public class RandomUtils { 9 | public static int RandomInt(int min, int max) { 10 | return (int) (min + Math.random() * (max - min)); 11 | } 12 | 13 | public static float RandomFloat(double min, double max) { 14 | return (float) (min + Math.random() * (max - min)); 15 | } 16 | 17 | public static String RandomString(int length) { 18 | String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 19 | Random random = new Random(); 20 | StringBuilder sb = new StringBuilder(); 21 | for (int i = 0; i < length; i++) { 22 | int number = random.nextInt(62); 23 | sb.append(str.charAt(number)); 24 | } 25 | return sb.toString(); 26 | } 27 | 28 | public static String RandomStringWithPerfix(String perfix, int length) { 29 | String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 30 | Random random = new Random(); 31 | StringBuilder sb = new StringBuilder(); 32 | for (int i = 0; i < length - perfix.length(); i++) { 33 | int number = random.nextInt(62); 34 | sb.append(str.charAt(number)); 35 | } 36 | return perfix + sb.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/EqualOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 14 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 15 | 16 | /** 17 | * Created by liufengkai on 2017/7/28. 18 | */ 19 | class EqualOpTest { 20 | 21 | @Test 22 | void testEqualIntegerValue() { 23 | runExpr("1222 == 1222", true, null); 24 | } 25 | 26 | @Test 27 | void testEqualBoolean() { 28 | runExpr("true == true", true, null); 29 | } 30 | 31 | @Test 32 | void testEqualFloat() { 33 | runExpr("111.222f == 111.222f", true, null); 34 | } 35 | 36 | @Test 37 | void testEqualDouble() { 38 | runExpr("11111.22222222d == 11111.22222222d", true, null); 39 | } 40 | 41 | @Test 42 | void testEqualCompiler() { 43 | compiler("11111.22222222d == 11111.22222222d", null); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/compile/generate/JavaSourceTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.generate; 2 | 3 | import com.lfkdsk.justel.ast.base.AstNode; 4 | import com.lfkdsk.justel.ast.function.ExtendFunctionExprTest; 5 | import com.lfkdsk.justel.context.JustContext; 6 | import com.lfkdsk.justel.context.JustMapContext; 7 | import com.lfkdsk.justel.lexer.JustLexerImpl; 8 | import com.lfkdsk.justel.lexer.Lexer; 9 | import com.lfkdsk.justel.parser.JustParser; 10 | import com.lfkdsk.justel.parser.JustParserImpl; 11 | import com.lfkdsk.justel.utils.logger.Logger; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import java.io.StringReader; 15 | 16 | /** 17 | * Created by liufengkai on 2017/8/11. 18 | */ 19 | class JavaSourceTest { 20 | 21 | @Test 22 | void testReFormatSourceCode() { 23 | Logger.init(); 24 | ExtendFunctionExprTest.ExtendFunc func = new ExtendFunctionExprTest.ExtendFunc(); 25 | JustContext context = new JustMapContext(); 26 | context.putExtendFunc(func); 27 | 28 | Logger.init("gen-code"); 29 | Lexer lexer = new JustLexerImpl(new StringReader("add(111,222)")); 30 | JustParser parser = new JustParserImpl(); 31 | AstNode rootNode = parser.parser(lexer.tokens()); 32 | Generator generator = new JavaCodeGenerator(); 33 | JavaSource javaSource = generator.generate(context, rootNode); 34 | 35 | Logger.i(javaSource.toString()); 36 | } 37 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/literal/IDLiteralTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.literal; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import com.lfkdsk.justel.utils.logger.Logger; 14 | import com.lfkdsk.justel.utils.printer.Log; 15 | import org.junit.jupiter.api.Test; 16 | 17 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 18 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 19 | 20 | /** 21 | * Created by liufengkai on 2017/8/3. 22 | */ 23 | class IDLiteralTest { 24 | 25 | @Test 26 | void testLocalVar() { 27 | JustContext context = new JustMapContext(); 28 | context.put("id","SSSSSS"); 29 | runExpr("id", false, context); 30 | } 31 | 32 | @Test 33 | void testLocalVarCompiler() { 34 | JustContext context = new JustMapContext(); 35 | context.put("id","SSSSSS"); 36 | Logger.init(); 37 | Logger.i(compiler("id", context)); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/optimizer/Optimizer.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.optimizer; 2 | 3 | import com.lfkdsk.justel.ast.base.AstNode; 4 | import com.lfkdsk.justel.utils.collection.Tuple; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.function.Consumer; 9 | 10 | /** 11 | * Created by liufengkai on 2017/9/8. 12 | */ 13 | public class Optimizer { 14 | 15 | private AstNode root; 16 | 17 | private Map>>> optimizers = new HashMap<>(); 18 | 19 | public Optimizer(AstNode root) { 20 | this.root = root; 21 | } 22 | 23 | public AstNode optimizer(AstNode parent) { 24 | for (int i = 0; i < root.childCount(); i++) { 25 | AstNode child = root.child(i); 26 | Consumer>> 27 | consumer = optimizers.get(child.getClass()); 28 | 29 | if (consumer != null) { 30 | Tuple> tuple = new Tuple<>(child, new Tuple<>(parent, i)); 31 | consumer.accept(tuple); 32 | } 33 | 34 | optimizer(child); 35 | } 36 | 37 | return root; 38 | } 39 | 40 | public void addOptimizer(Class clazz, 41 | Consumer>> consumer) { 42 | optimizers.put(clazz, consumer); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/repl/JustReplTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.repl; 2 | 3 | import com.lfkdsk.justel.JustEL; 4 | import com.lfkdsk.justel.context.JustArrayContext; 5 | import org.fusesource.jansi.Ansi; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.fusesource.jansi.Ansi.ansi; 9 | 10 | class JustReplTest { 11 | 12 | @Test 13 | void testPrintLogo() { 14 | String logoStr = JustRepl.logoStr.replace("█", ansi().fg(Ansi.Color.GREEN).a("█").reset().toString()); 15 | System.out.println(logoStr); 16 | } 17 | 18 | @Test 19 | void testAssign() { 20 | JustEL justEL = JustEL.builder() 21 | .lexer(new MockLexer()) 22 | .parser(new MockParser()) 23 | .generator(new MockGenerator()) 24 | .create(); 25 | 26 | justEL.compile("lfkdsk = \"lfkdsk\" + \"lfk\"", new JustArrayContext() {{ 27 | }}); 28 | } 29 | 30 | @Test 31 | void testStringAdder() { 32 | JustEL justEL = JustEL.builder().create(); 33 | justEL.compile("\"fffff\" + \"fffff\"", new JustArrayContext()); 34 | } 35 | 36 | @Test 37 | void testStringNumberAdder() { 38 | JustEL justEL = JustEL.builder().create(); 39 | justEL.compile("\"fffff\" + 1", new JustArrayContext()); 40 | // Lexer lexer = new JustLexerImpl(); 41 | // lexer.scanner("1111 + \"fffff\""); 42 | } 43 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/MinusOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 14 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 15 | 16 | /** 17 | * Created by liufengkai on 2017/7/29. 18 | */ 19 | class MinusOpTest { 20 | @Test 21 | void testMinusInteger() { 22 | runExpr("111 - 100", true, null); 23 | } 24 | 25 | @Test 26 | void testMinusFloatInteger() { 27 | runExpr("111.1 - 10", true, null); 28 | } 29 | 30 | @Test 31 | void testMinusIntegerFloat() { 32 | runExpr("111 - 100.111111f", true, null); 33 | } 34 | 35 | @Test 36 | void testMinusDouble() { 37 | runExpr("111.00000001111d - 100", true, null); 38 | } 39 | 40 | @Test 41 | void testMinusCompiler() { 42 | compiler("111 - 100", null); 43 | compiler("111.1 - 10", null); 44 | compiler("111 - 100.111111f", null); 45 | compiler("111.00000001111d - 100", null); 46 | } 47 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/OrOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 16 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 17 | 18 | /** 19 | * Created by liufengkai on 2017/7/29. 20 | */ 21 | class OrOpTest { 22 | 23 | @Test 24 | void testOrBoolean() { 25 | runExpr("true || false", true, null); 26 | } 27 | 28 | @Test 29 | void testOrIDToken() { 30 | JustContext context = new JustMapContext(); 31 | context.put("lfkdsk", true); 32 | context.put("lfk", true); 33 | runExpr("lfkdsk || lfk", true, context); 34 | } 35 | 36 | @Test 37 | void testOrCompiler() { 38 | compiler("true || false", null); 39 | 40 | JustContext context = new JustMapContext(); 41 | context.put("lfkdsk", true); 42 | context.put("lfk", true); 43 | compiler("lfkdsk || lfk", context); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/AmpersandOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import com.lfkdsk.justel.utils.logger.Logger; 14 | import org.junit.jupiter.api.Test; 15 | 16 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 17 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 18 | 19 | /** 20 | * Created by liufengkai on 2017/7/28. 21 | */ 22 | class AmpersandOpTest { 23 | 24 | @Test 25 | void testAmpersandInteger() { 26 | runExpr("1111 & 1111", true, null); 27 | } 28 | 29 | @Test 30 | void testAmpersandID() { 31 | JustContext context = new JustMapContext(); 32 | context.put("lfkdsk", 1111); 33 | runExpr("lfkdsk & 1211", true, context); 34 | 35 | Logger.i(String.valueOf(1111 & 1211)); 36 | } 37 | 38 | @Test 39 | void testAmpersandCompiler() { 40 | JustContext context = new JustMapContext(); 41 | context.put("lfkdsk", 1111); 42 | compiler("lfkdsk & 1211", context); 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/UnEqualOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 14 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 15 | 16 | /** 17 | * Created by liufengkai on 2017/7/28. 18 | */ 19 | class UnEqualOpTest { 20 | 21 | @Test 22 | void testUnEqualIntegerValue() { 23 | runExpr("1222 != 1222", true, null); 24 | } 25 | 26 | @Test 27 | void testUnEqualBoolean() { 28 | runExpr("true != true", true, null); 29 | } 30 | 31 | @Test 32 | void testUnEqualFloat() { 33 | runExpr("111.222f != 111.222f", true, null); 34 | } 35 | 36 | @Test 37 | void testUnEqualDouble() { 38 | runExpr("11111.22222222d != 11111.22222222d", true, null); 39 | } 40 | 41 | @Test 42 | void testUnEqualCompiler() { 43 | compiler("1222 != 1222",null); 44 | compiler("true != true",null); 45 | compiler("111.222f != 111.222f",null); 46 | compiler("11111.22222222d != 11111.22222222d",null); 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/compile/compiler/JustCompilerImplTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.compiler; 2 | 3 | import com.lfkdsk.justel.compile.generate.JavaSource; 4 | import com.lfkdsk.justel.context.JustMapContext; 5 | import com.lfkdsk.justel.eval.Expression; 6 | import org.junit.jupiter.api.Test; 7 | import com.lfkdsk.justel.template.TemplateImpl; 8 | import com.lfkdsk.justel.template.dom.DomCom; 9 | import com.lfkdsk.justel.utils.GeneratedId; 10 | 11 | /** 12 | * Created by liufengkai on 2017/7/20. 13 | */ 14 | class JustCompilerImplTest { 15 | @Test 16 | void compile() { 17 | DomCom templateGen = new TemplateImpl().generateTemplate(); 18 | JustCompilerImpl compiler = new JustCompilerImpl(); 19 | JustMapContext context = new JustMapContext(); 20 | String className = "JustEL" + GeneratedId.generateAtomId(); 21 | context.put("${attrs}", ""); 22 | context.put("${className}", className); 23 | context.put("${localVars}", "int i = 10;"); 24 | context.put("${expression}", "0"); 25 | String sourceCode = templateGen.fakeGenerateString(context); 26 | JavaSource source = new JavaSource("com.lfkdsk.justel.generatecode", className, sourceCode); 27 | 28 | for (int i = 0; i < 20; i++) { 29 | long startTime = System.currentTimeMillis(); 30 | // System.out.println(sourceCode); 31 | Expression expr = compiler.compile(source); 32 | 33 | System.out.println(System.currentTimeMillis() - startTime); 34 | } 35 | 36 | // System.out.println(expr); 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/postfix/NotPostfix.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.postfix; 10 | 11 | import com.lfkdsk.justel.ast.base.AstList; 12 | import com.lfkdsk.justel.ast.base.AstNode; 13 | import com.lfkdsk.justel.context.JustContext; 14 | 15 | import java.util.List; 16 | 17 | import static com.lfkdsk.justel.utils.TypeUtils.isBoolean; 18 | 19 | /** 20 | * ! Postfix 21 | * 22 | * @author liufengkai 23 | * Created by liufengkai on 2017/7/26. 24 | */ 25 | public class NotPostfix extends AstList { 26 | 27 | public NotPostfix(List children) { 28 | super(children, AstNode.NOT_OP); 29 | } 30 | 31 | private AstNode operand() { 32 | return child(0); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "! " + operand(); 38 | } 39 | 40 | @Override 41 | public Object eval(JustContext env) { 42 | Object value = this.operand().eval(env); 43 | 44 | if (isBoolean(value)) { 45 | return !(Boolean) value; 46 | } 47 | 48 | return super.eval(env); 49 | } 50 | 51 | @Override 52 | public String compile(JustContext env) { 53 | return "! " + operand().compile(env); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/GreaterThanEqualOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Assertions; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 15 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 16 | 17 | /** 18 | * Created by liufengkai on 2017/7/31. 19 | */ 20 | class GreaterThanEqualOpTest { 21 | @Test 22 | void testGTE() { 23 | String returnStr = runExpr("11111 >= 11111", true, null); 24 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 25 | } 26 | 27 | @Test 28 | void testComparableGTE() { 29 | String returnStr = runExpr("\"lfkdsk\" >= \"lfk\" ", true, null); 30 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 31 | } 32 | 33 | @Test 34 | void testDoubleGTE() { 35 | String returnStr = runExpr("1111.000100d >= 1000.11111d", true, null); 36 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 37 | } 38 | 39 | @Test 40 | void testGTECompiler() { 41 | String returnStr = compiler("1111.000100d >= 1000.11111d", null); 42 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/repl/MockAssignOperator.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.repl; 2 | 3 | import com.lfkdsk.justel.ast.base.AstLeaf; 4 | import com.lfkdsk.justel.ast.base.AstNode; 5 | import com.lfkdsk.justel.ast.function.OperatorExpr; 6 | import com.lfkdsk.justel.context.JustContext; 7 | import com.lfkdsk.justel.exception.EvalException; 8 | import com.lfkdsk.justel.literal.IDLiteral; 9 | import com.lfkdsk.justel.token.Token; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * = operator for REPL 15 | * 16 | * @author liufengkai 17 | */ 18 | public class MockAssignOperator extends OperatorExpr { 19 | 20 | public MockAssignOperator(List children) { 21 | super(children, 2000); 22 | } 23 | 24 | @Override 25 | public String funcName() { 26 | return "="; 27 | } 28 | 29 | @Override 30 | public String compile(JustContext env) { 31 | StringBuilder builder = new StringBuilder(); 32 | 33 | // add value to env 34 | eval(env); 35 | 36 | builder.append(leftChild().toString()) 37 | .append("=") 38 | .append(rightChild().compile(env)); 39 | 40 | return builder.toString(); 41 | } 42 | 43 | @Override 44 | public Object eval(JustContext env) { 45 | AstLeaf node = (AstLeaf) leftChild(); 46 | Object value = rightChild().eval(env); 47 | int tag = node.token().getTag(); 48 | if (tag == Token.ID) { 49 | // 重设值 50 | env.put(((IDLiteral) node).name(), value); 51 | 52 | return value; 53 | } else { 54 | throw new EvalException("bad assign ", node); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/template/dom/DomComponentTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template.dom; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static com.lfkdsk.justel.compile.generate.JavaSource.GENERATE_DEFAULT_PACKAGE; 6 | 7 | /** 8 | * Created by liufengkai on 2017/9/4. 9 | */ 10 | class DomComponentTest { 11 | 12 | @Test 13 | void testComponent() { 14 | 15 | DomCom templateGen = DomCom.rule() 16 | .append(DomCom.rule() 17 | .sep("package") 18 | .sep(GENERATE_DEFAULT_PACKAGE + ";")) 19 | .append(DomCom.rule() 20 | .sep("import com.lfkdsk.justel.context.JustContext;") 21 | .sep("import com.lfkdsk.justel.eval.Expression;")) 22 | .append(DomCom.rule() 23 | .sep("public class") 24 | .bind("${className}") 25 | .sep("implements Expression ") 26 | .sep("{") 27 | .append(DomCom.rule() 28 | .bind("${attrs}") 29 | .sep("@Override public Object eval(JustContext context) {") 30 | .bind("${localVars}") 31 | .sep("return") 32 | .bind("${expression}") 33 | .sep(";}")) 34 | .sep("}")); 35 | 36 | 37 | templateGen.randomVal() 38 | .nop("*****") 39 | .des("lfkdsk", 40 | "lfkdsk") 41 | .fakeGenerateComponent(); 42 | 43 | 44 | 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/CondOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import org.junit.jupiter.api.Assertions; 14 | import org.junit.jupiter.api.Test; 15 | 16 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 17 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 18 | 19 | /** 20 | * Created by liufengkai on 2017/8/2. 21 | */ 22 | class CondOpTest { 23 | 24 | @Test 25 | void testCondOp() { 26 | String returnStr = runExpr("true ? true : false", true, null); 27 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 28 | } 29 | 30 | @Test 31 | void testExprCondOp() { 32 | JustContext context = new JustMapContext(); 33 | context.put("lfkdsk", 101); 34 | String returnStr = runExpr("lfkdsk > 100 ? lfkdsk + 1 : lfkdsk + 2", true, context); 35 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 102); 36 | } 37 | 38 | @Test 39 | void testExprCompileCond() { 40 | JustContext context = new JustMapContext(); 41 | context.put("lfkdsk", true); 42 | compiler("lfkdsk ? 123 : 123.123f", context); 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/utils/collection/IndexEntryTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.collection; 2 | 3 | import com.lfkdsk.justel.compile.generate.Var; 4 | import com.lfkdsk.justel.utils.logger.Logger; 5 | import org.junit.jupiter.api.BeforeEach; 6 | import org.junit.jupiter.api.Test; 7 | 8 | class IndexEntryTest { 9 | 10 | private ArrayBinder arrayBinder; 11 | 12 | @BeforeEach 13 | void setUp() { 14 | arrayBinder = new ArrayBinder<>(); 15 | Logger.init(); 16 | } 17 | 18 | @Test 19 | void testIndexEntryTest() { 20 | arrayBinder.put("lfkdsk", new Object()); 21 | arrayBinder.put("lfkdsk1", new Object()); 22 | arrayBinder.put("lfkdsk2", new Object()); 23 | Logger.d(String.valueOf(arrayBinder.indexOf("lfkdsk"))); 24 | Logger.d(String.valueOf(arrayBinder.indexOf("lfkdsk2"))); 25 | Logger.d(String.valueOf(arrayBinder.indexOf("lfkdsk1"))); 26 | } 27 | 28 | public String generateVarAssignCode(Var var) { 29 | StringBuilder builder = new StringBuilder(); 30 | 31 | String typeDeclare = Var.getTypeDeclare(var.getType()); 32 | 33 | builder.append(typeDeclare).append(" ") 34 | .append(var.getName()).append("=") 35 | .append("((").append(var.getType().getCanonicalName()).append(")") 36 | .append("context.getWith(").append(arrayBinder.indexOf(var.getName())).append(")").append(");"); 37 | 38 | return builder.toString(); 39 | } 40 | 41 | @Test 42 | void testVar() { 43 | Var var = new Var("lfkdsk", new Object()); 44 | arrayBinder.put(var.getName(), var.getValue()); 45 | Logger.v(generateVarAssignCode(var)); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/OrOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.TypeUtils.isBoolean; 20 | 21 | /** 22 | * || Operator 23 | * eq: bool_expr || bool_expr 24 | * 25 | * @author liufengkai 26 | * Created by liufengkai on 2017/7/28. 27 | * @see OperatorExpr 28 | */ 29 | public class OrOp extends OperatorExpr { 30 | 31 | public OrOp(List children) { 32 | super(children, Token.OR); 33 | } 34 | 35 | @Override 36 | public String funcName() { 37 | return SepToken.OR_TOKEN.getText(); 38 | } 39 | 40 | @Override 41 | public Object eval(JustContext env) { 42 | Object leftValue = leftChild().eval(env); 43 | Object rightValue = rightChild().eval(env); 44 | 45 | if (isBoolean(leftValue) && isBoolean(rightValue)) { 46 | return leftValue == Boolean.TRUE 47 | || rightValue == Boolean.TRUE; 48 | } 49 | 50 | return super.eval(env); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/ModOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeModValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 21 | 22 | /** 23 | * % Operator 24 | * eq: num % num 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/8/2. 28 | * @see OperatorExpr 29 | */ 30 | public class ModOp extends OperatorExpr { 31 | 32 | public ModOp(List children) { 33 | super(children, Token.MOD); 34 | } 35 | 36 | @Override 37 | public String funcName() { 38 | return SepToken.MOD_TOKEN.getText(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | Object left = leftChild().eval(env); 44 | Object right = rightChild().eval(env); 45 | 46 | if (isNumber(left) && isNumber(right)) { 47 | return computeModValue((Number) left, (Number) right); 48 | } 49 | 50 | return super.eval(env); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/postfix/NegativePostfix.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.postfix; 10 | 11 | import com.lfkdsk.justel.ast.base.AstList; 12 | import com.lfkdsk.justel.ast.base.AstNode; 13 | import com.lfkdsk.justel.context.JustContext; 14 | 15 | import java.util.List; 16 | 17 | import static com.lfkdsk.justel.utils.NumberUtils.computeNegative; 18 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 19 | 20 | /** 21 | * - Postfix 22 | * 23 | * @author liufengkai 24 | * Created by liufengkai on 2017/7/26. 25 | */ 26 | public class NegativePostfix extends AstList { 27 | 28 | public NegativePostfix(List children) { 29 | super(children, AstNode.NEGATIVE_OP); 30 | } 31 | 32 | public AstNode operand() { 33 | return child(0); 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "-" + operand(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | Object value = this.operand().eval(env); 44 | 45 | if (isNumber(value)) { 46 | 47 | return computeNegative((Number) value); 48 | } 49 | 50 | return super.eval(env); 51 | } 52 | 53 | @Override 54 | public String compile(JustContext env) { 55 | return "-" + operand().compile(env); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/MulOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeMulValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 21 | 22 | /** 23 | * * Operator 24 | * eq: expr * expr. 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/29. 28 | * @see OperatorExpr 29 | */ 30 | public class MulOp extends OperatorExpr { 31 | 32 | public MulOp(List children) { 33 | super(children, Token.MULTIPLY); 34 | } 35 | 36 | @Override 37 | public String funcName() { 38 | return SepToken.MULTIPLY_TOKEN.getText(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | Object left = leftChild().eval(env); 44 | Object right = rightChild().eval(env); 45 | 46 | if (isNumber(left) && isNumber(right)) { 47 | return computeMulValue((Number) left, (Number) right); 48 | } 49 | 50 | return super.eval(env); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/LessThanOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Assertions; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 15 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 16 | 17 | /** 18 | * Created by liufengkai on 2017/8/2. 19 | */ 20 | class LessThanOpTest { 21 | @Test 22 | void testLessThan() { 23 | String result = runExpr("123 < 123 ", true, null); 24 | Assertions.assertFalse(Boolean.valueOf(result)); 25 | } 26 | 27 | @Test 28 | void testDoubleLessThan() { 29 | String result = runExpr("123.111111d < 111.111111d", true, null); 30 | Assertions.assertFalse(Boolean.valueOf(result)); 31 | } 32 | 33 | @Test 34 | void testComparableLessThan() { 35 | String result = runExpr(" \"lfkdsk\" < \"lfk\" ", true, null); 36 | Assertions.assertFalse(Boolean.valueOf(result)); 37 | } 38 | 39 | @Test 40 | void testLTCompiler() { 41 | String result = compiler("123 < 123 ", null); 42 | Assertions.assertFalse(Boolean.valueOf(result)); 43 | 44 | result = compiler("123.111111d < 111.111111d", null); 45 | Assertions.assertFalse(Boolean.valueOf(result)); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/AmpersandOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | 16 | import java.util.List; 17 | 18 | import static com.lfkdsk.justel.utils.NumberUtils.computeAmpersandValue; 19 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 20 | 21 | /** 22 | * & Operator 23 | * eq: left & right 24 | * 25 | * @author liufengkai 26 | * Created by liufengkai on 2017/7/26. 27 | * @see OperatorExpr 28 | */ 29 | public class AmpersandOp extends OperatorExpr { 30 | 31 | public AmpersandOp(List children) { 32 | super(children, AstNode.AMPERSAND_OP); 33 | } 34 | 35 | @Override 36 | public String funcName() { 37 | return SepToken.AMPERSAND_TOKEN.getText(); 38 | } 39 | 40 | @Override 41 | public Object eval(JustContext env) { 42 | Object leftValue = leftChild().eval(env); 43 | Object rightValue = rightChild().eval(env); 44 | 45 | if (isNumber(leftValue) && isNumber(rightValue)) { 46 | return computeAmpersandValue((Number) leftValue, (Number) rightValue); 47 | } 48 | 49 | return super.eval(env); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/DivOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeDivValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 21 | 22 | /** 23 | * / Operator 24 | * eq: num / num 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/29. 28 | * @see OperatorExpr 29 | */ 30 | public class DivOp extends OperatorExpr { 31 | 32 | public DivOp(List children) { 33 | super(children, Token.DIVIDE); 34 | } 35 | 36 | @Override 37 | public String funcName() { 38 | return SepToken.DIVIDE_TOKEN.getText(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | 44 | Object left = leftChild().eval(env); 45 | Object right = rightChild().eval(env); 46 | 47 | if (isNumber(left) && isNumber(right)) { 48 | 49 | // id(num) / id(num) 50 | return computeDivValue((Number) left, (Number) right); 51 | } 52 | 53 | return super.eval(env); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/ModTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.utils.NumberUtils; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 16 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 17 | 18 | /** 19 | * Created by liufengkai on 2017/8/2. 20 | */ 21 | class ModTest { 22 | 23 | @Test 24 | void testModInteger() { 25 | String returnStr = runExpr("100 % 10", true, null); 26 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 0); 27 | } 28 | 29 | @Test 30 | void testModDouble() { 31 | String returnStr = runExpr("1111.1111d % 10.1111d", true, null); 32 | Assertions.assertEquals((double) Double.valueOf(returnStr), 9.001199999999999); 33 | } 34 | 35 | @Test 36 | void testModCompiler() { 37 | String returnStr = compiler("100 % 10", null); 38 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 0); 39 | 40 | returnStr = compiler("1111.1111d % 10.1111d", null); 41 | Assertions.assertEquals((double) Double.valueOf(returnStr), 9.001199999999999); 42 | } 43 | 44 | @Test 45 | void testModMethod() { 46 | NumberUtils.computeDivValue(0, 0); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/MinusOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeMinusValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 21 | 22 | /** 23 | * - Operator 24 | * eq: num - num 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/29. 28 | * @see OperatorExpr 29 | */ 30 | public class MinusOp extends OperatorExpr { 31 | 32 | public MinusOp(List children) { 33 | super(children, Token.MINUS); 34 | } 35 | 36 | @Override 37 | public String funcName() { 38 | return SepToken.MINUS_TOKEN.getText(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | Object left = leftChild().eval(env); 44 | Object right = rightChild().eval(env); 45 | 46 | if (isNumber(left) && isNumber(right)) { 47 | 48 | // id(num) - id(num) 49 | return computeMinusValue((Number) left, (Number) right); 50 | } 51 | 52 | return super.eval(env); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/LessThanEqualOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Assertions; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 15 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 16 | 17 | /** 18 | * Created by liufengkai on 2017/8/2. 19 | */ 20 | class LessThanEqualOpTest { 21 | @Test 22 | void testLTE() { 23 | String returnStr = runExpr("11111 <= 11111", true, null); 24 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 25 | } 26 | 27 | @Test 28 | void testComparableLTE() { 29 | String returnStr = runExpr("\"lfkdsk\" <= \"lfk\" ", true, null); 30 | Assertions.assertFalse(Boolean.valueOf(returnStr)); 31 | } 32 | 33 | @Test 34 | void testDoubleLTE() { 35 | String returnStr = runExpr("1111.000100d <= 1000.11111d", true, null); 36 | Assertions.assertFalse(Boolean.valueOf(returnStr)); 37 | } 38 | 39 | @Test 40 | void testLTECompiler() { 41 | String returnStr = compiler("11111 <= 11111", null); 42 | Assertions.assertTrue(Boolean.valueOf(returnStr)); 43 | 44 | returnStr = compiler("1111.000100d <= 1000.11111d", null); 45 | Assertions.assertFalse(Boolean.valueOf(returnStr)); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/template/TemplateImpl.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template; 2 | 3 | import com.lfkdsk.justel.template.dom.DomCom; 4 | import com.lfkdsk.justel.template.dom.Template; 5 | 6 | import static com.lfkdsk.justel.compile.generate.JavaSource.GENERATE_DEFAULT_PACKAGE; 7 | 8 | 9 | /** 10 | * Simple Template Impl 11 | * Use fixed structure Ast to save the com.lfkdsk.justel.template 12 | * and we can use it to generateCode-code as com.lfkdsk.justel.template file 13 | * Created by liufengkai on 2017/7/18. 14 | */ 15 | public class TemplateImpl implements Template { 16 | 17 | protected final DomCom packageGen = DomCom.rule() 18 | .sep("package") 19 | .sep(GENERATE_DEFAULT_PACKAGE + ";"); 20 | 21 | protected final DomCom importGen = DomCom.rule() 22 | .sep("import com.lfkdsk.justel.context.JustContext;") 23 | .sep("import com.lfkdsk.justel.eval.Expression;"); 24 | 25 | protected final DomCom functionGen = DomCom.rule() 26 | .bind("${attrs}") 27 | .sep("@Override public Object eval(JustContext context) {") 28 | .bind("${localVars}") 29 | .sep("return") 30 | .bind("${expression}") 31 | .sep(";}"); 32 | 33 | protected final DomCom classGen = DomCom.rule() 34 | .sep("public class") 35 | .bind("${className}") 36 | .sep("implements Expression ") 37 | .sep("{") 38 | .append(functionGen) 39 | .sep("}"); 40 | 41 | protected final DomCom templateGen = DomCom.rule() 42 | .append(packageGen) 43 | .append(importGen) 44 | .append(classGen); 45 | 46 | @Override 47 | public DomCom generateTemplate() { 48 | return templateGen; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/collection/EmptyArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.lfkdsk.justel.utils.collection; 18 | 19 | public final class EmptyArray { 20 | private EmptyArray() {} 21 | 22 | public static final boolean[] BOOLEAN = new boolean[0]; 23 | public static final byte[] BYTE = new byte[0]; 24 | public static final char[] CHAR = new char[0]; 25 | public static final double[] DOUBLE = new double[0]; 26 | public static final float[] FLOAT = new float[0]; 27 | public static final int[] INT = new int[0]; 28 | public static final long[] LONG = new long[0]; 29 | 30 | public static final Class[] CLASS = new Class[0]; 31 | public static final Object[] OBJECT = new Object[0]; 32 | public static final String[] STRING = new String[0]; 33 | public static final Throwable[] THROWABLE = new Throwable[0]; 34 | public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0]; 35 | public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0]; 36 | public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE = 37 | new java.lang.reflect.TypeVariable[0]; 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/lexer/RandomUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.lexer; 10 | 11 | import java.util.Random; 12 | 13 | /** 14 | * Created by liufengkai on 16/4/16. 15 | */ 16 | public class RandomUtils { 17 | public static int RandomInt(int min, int max) { 18 | return (int) (min + Math.random() * (max - min)); 19 | } 20 | 21 | public static float RandomFloat(double min, double max) { 22 | return (float) (min + Math.random() * (max - min)); 23 | } 24 | 25 | public static String RandomString(int length) { 26 | String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 27 | Random random = new Random(); 28 | StringBuilder sb = new StringBuilder(); 29 | for (int i = 0; i < length; i++) { 30 | int number = random.nextInt(62); 31 | sb.append(str.charAt(number)); 32 | } 33 | return sb.toString(); 34 | } 35 | 36 | public static String RandomStringWithPerfix(String perfix, int length) { 37 | String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 38 | Random random = new Random(); 39 | StringBuilder sb = new StringBuilder(); 40 | for (int i = 0; i < length - perfix.length(); i++) { 41 | int number = random.nextInt(62); 42 | sb.append(str.charAt(number)); 43 | } 44 | return perfix + sb.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/utils/GeneratedIdTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.utils; 10 | 11 | import com.lfkdsk.justel.utils.logger.Logger; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import java.util.Hashtable; 16 | 17 | /** 18 | * Created by liufengkai on 2017/8/4. 19 | */ 20 | class GeneratedIdTest { 21 | 22 | @Test 23 | void testGenerateId() throws InterruptedException { 24 | Logger.init("gen-code"); 25 | // need curr - table 26 | 27 | for (int j = 0; j < 20; j++) { 28 | // hash-table current-control is needed 29 | Hashtable set = new Hashtable<>(); 30 | 31 | for (int i = 0; i < 100; i++) { 32 | new Thread(() -> { 33 | Integer integer = GeneratedId.generateAtomId(); 34 | 35 | if (set.contains(integer)) { 36 | Logger.e(set.put(integer, set.get(integer) + 1).toString()); 37 | throw new RuntimeException("fuck"); 38 | } else { 39 | set.put(integer, 1); 40 | } 41 | 42 | Logger.v(String.valueOf(integer)); 43 | }).start(); 44 | } 45 | 46 | 47 | // just wait thread completed 48 | Thread.sleep(1000); 49 | Assertions.assertEquals(set.size(), 100); 50 | } 51 | 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/EqualOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | 16 | import java.util.List; 17 | 18 | import static com.lfkdsk.justel.utils.TypeUtils.*; 19 | 20 | /** 21 | * == Operator 22 | * eq: expr == expr 23 | * 24 | * @author liufengkai 25 | * Created by liufengkai on 2017/7/26. 26 | * @see OperatorExpr 27 | */ 28 | public class EqualOp extends OperatorExpr { 29 | 30 | public EqualOp(List children) { 31 | super(children, AstNode.EQUAL_OP); 32 | } 33 | 34 | @Override 35 | public String funcName() { 36 | return SepToken.EQUAL_TOKEN.getText(); 37 | } 38 | 39 | @Override 40 | public Object eval(JustContext env) { 41 | Object left = leftChild().eval(env); 42 | Object right = rightChild().eval(env); 43 | 44 | // boolean == boolean 45 | if (isBoolean(left) && isBoolean(right)) { 46 | 47 | return left.equals(right); 48 | } else if (isNumber(left) && isNumber(right)) { 49 | 50 | // num == num 51 | return left.equals(right); 52 | } else if (isString(left) && isString(right)) { 53 | 54 | return left.equals(right); 55 | } 56 | 57 | return super.eval(env); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/json/JSONException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.lfkdsk.justel.utils.json; 18 | 19 | // Note: this class was written without inspecting the non-free org.json sourcecode. 20 | 21 | /** 22 | * Thrown to indicate a problem with the JSON API. Such problems include: 23 | *
    24 | *
  • Attempts to parse or construct malformed documents 25 | *
  • Use of null as a name 26 | *
  • Use of numeric types not available to JSON, such as {@link 27 | * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}. 28 | *
  • Lookups using an out of range index or nonexistent name 29 | *
  • Type mismatches on lookups 30 | *
31 | *

32 | *

Although this is a checked exception, it is rarely recoverable. Most 33 | * callers should simply wrap this exception in an unchecked exception and 34 | * rethrow: 35 | *

  public JSONArray toJSONObject() {
36 |  *     try {
37 |  *         JSONObject result = new JSONObject();
38 |  *         ...
39 |  *     } catch (JSONException e) {
40 |  *         throw new RuntimeException(e);
41 |  *     }
42 |  * }
43 | */ 44 | public class JSONException extends Exception { 45 | 46 | public JSONException(String s) { 47 | super(s); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/tree/AstCondExpr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import com.lfkdsk.justel.ast.base.AstList; 12 | import com.lfkdsk.justel.ast.base.AstNode; 13 | import com.lfkdsk.justel.ast.operators.CondOp; 14 | import com.lfkdsk.justel.context.JustContext; 15 | 16 | import java.util.List; 17 | 18 | import static com.lfkdsk.justel.utils.TypeUtils.isBoolean; 19 | 20 | /** 21 | * Ast Cond Expr 22 | * conExpr - conOp 23 | * conExpr - ? trueExpr : falseExpr 24 | * 25 | * @author liufengkai 26 | * Created by liufengkai on 2017/8/2. 27 | */ 28 | public class AstCondExpr extends AstList { 29 | 30 | public AstCondExpr(List children) { 31 | super(children, AstNode.COND_EXPR); 32 | } 33 | 34 | public static boolean isAstCondExpr(AstNode child) { 35 | return child.childCount() == 2 && child.child(1) instanceof CondOp; 36 | } 37 | 38 | private AstNode condExpr() { 39 | return child(0); 40 | } 41 | 42 | private CondOp condOp() { 43 | return (CondOp) child(1); 44 | } 45 | 46 | @Override 47 | public Object eval(JustContext env) { 48 | Object boolValue = condExpr().eval(env); 49 | CondOp condOp = condOp(); 50 | 51 | if (isBoolean(boolValue)) { 52 | // set cond value 53 | condOp.setCond((Boolean) boolValue); 54 | 55 | return condOp.eval(env); 56 | } 57 | 58 | return super.eval(env); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/UnEqualOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | 16 | import java.util.List; 17 | 18 | import static com.lfkdsk.justel.utils.TypeUtils.*; 19 | 20 | /** 21 | * != Operator 22 | * eq: expr != expr 23 | * 24 | * @author liufengkai 25 | * Created by liufengkai on 2017/7/26. 26 | * @see OperatorExpr 27 | */ 28 | public class UnEqualOp extends OperatorExpr { 29 | 30 | public UnEqualOp(List children) { 31 | super(children, AstNode.UN_EQUAL_OP); 32 | } 33 | 34 | @Override 35 | public String funcName() { 36 | return SepToken.NOT_EQUAL_TOKEN.getText(); 37 | } 38 | 39 | @Override 40 | public Object eval(JustContext env) { 41 | Object left = leftChild().eval(env); 42 | Object right = rightChild().eval(env); 43 | 44 | // boolean != boolean 45 | if (isBoolean(left) && isBoolean(right)) { 46 | 47 | return !left.equals(right); 48 | } else if (isNumber(left) && isNumber(right)) { 49 | 50 | // num != num 51 | return !left.equals(right); 52 | } else if (isString(left) && isString(right)) { 53 | 54 | return !left.equals(right); 55 | } 56 | 57 | return super.eval(env); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/GreaterThanOpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import org.junit.jupiter.api.Assertions; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 15 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 16 | 17 | /** 18 | * Created by liufengkai on 2017/7/31. 19 | */ 20 | class GreaterThanOpTest { 21 | 22 | @Test 23 | void testGreaterThan() { 24 | String result = runExpr("123 > 123 ", true, null); 25 | Assertions.assertFalse(Boolean.valueOf(result)); 26 | } 27 | 28 | @Test 29 | void testDoubleGreaterThan() { 30 | String result = runExpr("123.111111d > 111.111111d", true, null); 31 | Assertions.assertTrue(Boolean.valueOf(result)); 32 | } 33 | 34 | @Test 35 | void testComparableGreaterThan() { 36 | String result = runExpr(" \"lfkdsk\" > \"lfk\" ", true, null); 37 | Assertions.assertTrue(Boolean.valueOf(result)); 38 | } 39 | 40 | @Test 41 | void testGTCompiler() { 42 | // String result = compiler(" \"lfkdsk\" > \"lfk\" ", null); 43 | // Assertions.assertTrue(Boolean.valueOf(result)); 44 | 45 | String result = compiler("123.111111d > 111.111111d", null); 46 | Assertions.assertTrue(Boolean.valueOf(result)); 47 | 48 | result = compiler("123 > 123 ", null); 49 | Assertions.assertFalse(Boolean.valueOf(result)); 50 | 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/PlusOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computePlusValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.*; 21 | 22 | /** 23 | * + Operator: 24 | * eq:left + operator 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/26. 28 | * @see OperatorExpr 29 | */ 30 | public class PlusOp extends OperatorExpr { 31 | 32 | public PlusOp(List children) { 33 | super(children, Token.PLUS_OP); 34 | } 35 | 36 | @Override 37 | public String funcName() { 38 | return SepToken.PLUS_TOKEN.getText(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | Object left = leftChild().eval(env); 44 | Object right = rightChild().eval(env); 45 | 46 | if (isString(left) || isString(right)) { 47 | 48 | // "" + "" 49 | return String.valueOf(left) + String.valueOf(right); 50 | } else if (isNumber(left) && isNumber(right)) { 51 | 52 | // id(num) + id(num) 53 | return computePlusValue((Number) left, (Number) right); 54 | } 55 | 56 | return super.eval(env); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/memory/JustMemClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.memory; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * Memory Class Loader 10 | * Load Class From Memory 11 | * Created by liufengkai on 2017/7/20. 12 | */ 13 | public class JustMemClassLoader extends ClassLoader { 14 | 15 | /** 16 | * Compile Bytes Map. 17 | * Key => Class Qualified Name 18 | * Value => JVM Byte Codes 19 | */ 20 | private final Map compileBytesMap = new HashMap<>(); 21 | 22 | /** 23 | * compiled name set 24 | */ 25 | private final Set compiledNameSet = new HashSet<>(); 26 | 27 | public JustMemClassLoader(ClassLoader parent) { 28 | super(parent); 29 | } 30 | 31 | public JustMemClassLoader(ClassLoader parent, 32 | Map compileBytesMap) { 33 | super(parent); 34 | this.compileBytesMap.putAll(compileBytesMap); 35 | } 36 | 37 | /** 38 | * add bytes class 39 | * 40 | * @param qualifiedClassName class-qualified-name 41 | * @param bytes bytes 42 | * @return add to map 43 | */ 44 | byte[] addBytesClass(String qualifiedClassName, byte[] bytes) { 45 | return compileBytesMap.put(qualifiedClassName, bytes); 46 | } 47 | 48 | @Override 49 | protected Class findClass(String qualifiedClassName) throws ClassNotFoundException { 50 | if (!compiledNameSet.contains(qualifiedClassName)) { 51 | byte[] bytes = compileBytesMap.remove(qualifiedClassName); 52 | if (bytes != null) { 53 | compiledNameSet.add(qualifiedClassName); 54 | return defineClass(qualifiedClassName, bytes, 0, bytes.length); 55 | } 56 | } 57 | 58 | return super.findClass(qualifiedClassName); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/LessThanOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isComparable; 21 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 22 | 23 | /** 24 | * < Operator 25 | * eq: expr < expr. 26 | * 27 | * @author liufengkai 28 | * Created by liufengkai on 2017/8/2. 29 | * @see OperatorExpr 30 | */ 31 | public class LessThanOp extends OperatorExpr { 32 | 33 | public LessThanOp(List children) { 34 | super(children, Token.LESS_THAN); 35 | } 36 | 37 | @Override 38 | public String funcName() { 39 | return SepToken.LESS_TOKEN.getText(); 40 | } 41 | 42 | @Override 43 | @SuppressWarnings("unchecked") 44 | public Object eval(JustContext env) { 45 | Object left = leftChild().eval(env); 46 | Object right = rightChild().eval(env); 47 | 48 | if (isNumber(left) && isNumber(right)) { 49 | return Double.compare(computeValue(left), computeValue(right)) < 0; 50 | } else if (isComparable(left) && isComparable(right)) { 51 | return ((Comparable) left).compareTo(right) < 0; 52 | } 53 | 54 | return super.eval(env); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/GreaterThanOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isComparable; 21 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 22 | 23 | /** 24 | * > Operator 25 | * eq: expr > expr 26 | * 27 | * @author liufengkai 28 | * Created by liufengkai on 2017/7/31. 29 | * @see OperatorExpr 30 | */ 31 | public class GreaterThanOp extends OperatorExpr { 32 | 33 | public GreaterThanOp(List children) { 34 | super(children, Token.GREAT_THAN); 35 | } 36 | 37 | @Override 38 | public String funcName() { 39 | return SepToken.GREAT_TOKEN.getText(); 40 | } 41 | 42 | @Override 43 | @SuppressWarnings("unchecked") 44 | public Object eval(JustContext env) { 45 | Object left = leftChild().eval(env); 46 | Object right = rightChild().eval(env); 47 | 48 | if (isNumber(left) && isNumber(right)) { 49 | return Double.compare(computeValue(left), computeValue(right)) > 0; 50 | } else if (isComparable(left) && isComparable(right)) { 51 | return ((Comparable) left).compareTo(right) > 0; 52 | } 53 | 54 | return super.eval(env); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/LessThanEqualOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isComparable; 21 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 22 | 23 | /** 24 | * <= Operator 25 | * eq: expr <= expr. 26 | * 27 | * @author liufengkai 28 | * Created by liufengkai on 2017/8/2. 29 | * @see OperatorExpr 30 | */ 31 | public class LessThanEqualOp extends OperatorExpr { 32 | 33 | public LessThanEqualOp(List children) { 34 | super(children, Token.LESS_EQUAL_THAN); 35 | } 36 | 37 | @Override 38 | public String funcName() { 39 | return SepToken.LTE_TOKEN.getText(); 40 | } 41 | 42 | @Override 43 | @SuppressWarnings("unchecked") 44 | public Object eval(JustContext env) { 45 | Object left = leftChild().eval(env); 46 | Object right = rightChild().eval(env); 47 | 48 | if (isNumber(left) && isNumber(right)) { 49 | return Double.compare(computeValue(left), computeValue(right)) <= 0; 50 | } else if (isComparable(left) && isComparable(right)) { 51 | return ((Comparable) left).compareTo(right) <= 0; 52 | } 53 | 54 | return super.eval(env); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/GreaterThanEqualOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.SepToken; 15 | import com.lfkdsk.justel.token.Token; 16 | 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.NumberUtils.computeValue; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isComparable; 21 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 22 | 23 | /** 24 | * >= Operator 25 | * eq: expr >= expr 26 | * 27 | * @author liufengkai 28 | * Created by liufengkai on 2017/7/31. 29 | * @see OperatorExpr 30 | */ 31 | public class GreaterThanEqualOp extends OperatorExpr { 32 | 33 | public GreaterThanEqualOp(List children) { 34 | super(children, Token.GREAT_EQUAL_THAN); 35 | } 36 | 37 | @Override 38 | public String funcName() { 39 | return SepToken.GTE_TOKEN.getText(); 40 | } 41 | 42 | @Override 43 | @SuppressWarnings("unchecked") 44 | public Object eval(JustContext env) { 45 | Object left = leftChild().eval(env); 46 | Object right = rightChild().eval(env); 47 | 48 | if (isNumber(left) && isNumber(right)) { 49 | return Double.compare(computeValue(left), computeValue(right)) >= 0; 50 | } else if (isComparable(left) && isComparable(right)) { 51 | return ((Comparable) left).compareTo(right) >= 0; 52 | } 53 | 54 | return super.eval(env); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/context/JustContext.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.context; 2 | 3 | import com.lfkdsk.justel.ast.function.ExtendFunctionExpr; 4 | import com.lfkdsk.justel.compile.generate.Var; 5 | 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | /** 10 | * Context => { key : name } 11 | * 12 | * @author liufengkai 13 | * Created by liufengkai on 2017/7/18. 14 | */ 15 | public interface JustContext { 16 | 17 | boolean contain(String name); 18 | 19 | Object remove(String key); 20 | 21 | Object get(String objName); 22 | 23 | Object put(String key, Object val); 24 | 25 | Object getCache(Integer astHash); 26 | 27 | Object putCache(Integer key, Object val); 28 | 29 | ExtendFunctionExpr putExtendFunc(ExtendFunctionExpr expr); 30 | 31 | ExtendFunctionExpr getExtendFunc(String name); 32 | 33 | /** 34 | * Warning:!!! 35 | * Add Code to Java Source Code Straightly 36 | * 37 | * @param command command line 38 | * @return value 39 | */ 40 | Object command(String command); 41 | 42 | Collection varsKeySet(); 43 | 44 | List commandList(); 45 | 46 | List functions(); 47 | 48 | boolean clearVars(); 49 | 50 | default int indexOf(String key) { 51 | throw new UnsupportedOperationException("Unsupported method indexOf "); 52 | } 53 | 54 | default Object getWith(int index) { 55 | throw new UnsupportedOperationException("Unsupported method getWith "); 56 | } 57 | 58 | default String generateVarAssignCode(Var var) { 59 | StringBuilder builder = new StringBuilder(); 60 | 61 | String typeDeclare = Var.getTypeDeclare(var.getType()); 62 | 63 | builder.append(typeDeclare).append(" ") 64 | .append(var.getName()).append("=") 65 | .append("((").append(var.getType().getCanonicalName()).append(")") 66 | .append("context.get(\"").append(var.getName()).append("\")").append(");"); 67 | 68 | return builder.toString(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/ArrayIndexExprTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import org.junit.jupiter.api.Assertions; 14 | import org.junit.jupiter.api.Test; 15 | 16 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 17 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 18 | 19 | /** 20 | * Created by liufengkai on 2017/8/2. 21 | */ 22 | class ArrayIndexExprTest { 23 | 24 | @Test 25 | void testParser() { 26 | runExpr("lfkdsk[1]", false, null); 27 | } 28 | 29 | @Test 30 | void testArrayIndexExpr() { 31 | JustContext context = new JustMapContext(); 32 | // Integer[][] lfkdsk = new Integer[][]{{1, 2}, {2, 3}, {2, 10}}; 33 | int[][] lfkdsk = new int[][]{{1, 2}, {2, 3}, {2, 10}}; 34 | context.put("lfkdsk", lfkdsk); 35 | String returnStr = runExpr("lfkdsk[2][1]", true, context); 36 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 10); 37 | } 38 | 39 | @Test 40 | void testObjectArrayIndexExpr() { 41 | JustContext context = new JustMapContext(); 42 | Integer[][] lfkdsk = new Integer[][]{{1, 2}, {2, 3}, {2, 10}}; 43 | context.put("lfkdsk", lfkdsk); 44 | String returnStr = runExpr("lfkdsk[2][1]", true, context); 45 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 10); 46 | } 47 | 48 | @Test 49 | void testArrayCompiler() { 50 | JustContext context = new JustMapContext(); 51 | context.put("lfkdsk", new Object[]{1, 2, 2}); 52 | compiler("lfkdsk[2]", context); 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/base/AstNodeTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.ast.base; 2 | 3 | import com.lfkdsk.justel.ast.tree.AstProgram; 4 | import com.lfkdsk.justel.context.JustContext; 5 | import com.lfkdsk.justel.context.JustMapContext; 6 | import com.lfkdsk.justel.lexer.JustLexerImpl; 7 | import com.lfkdsk.justel.parser.JustParserImpl; 8 | import com.lfkdsk.justel.utils.logger.Logger; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.util.HashMap; 13 | 14 | /** 15 | * Created by liufengkai on 2017/9/28. 16 | */ 17 | public class AstNodeTest { 18 | 19 | @Test 20 | void testHash() { 21 | String a = " lfkdsk == 1"; 22 | String b = "lfkdsk==1"; 23 | 24 | AstNode aNode = toNode(a); 25 | AstNode bNode = toNode(b); 26 | 27 | Logger.init(); 28 | Logger.v(aNode.hashCode() + ""); 29 | Logger.v(bNode.hashCode() + ""); 30 | Assertions.assertTrue(aNode.hashCode() == bNode.hashCode()); 31 | Assertions.assertTrue(aNode.equals(bNode)); 32 | 33 | String c = "(lfkdsk ==1)"; 34 | AstNode cNode = toNode(c); 35 | Logger.v(cNode.hashCode() + ""); 36 | } 37 | 38 | public static AstNode toNode(String arg) { 39 | JustLexerImpl lexer = new JustLexerImpl(); 40 | JustParserImpl parser = new JustParserImpl(); 41 | 42 | return parser.parser(lexer.scanner(arg)); 43 | } 44 | 45 | @Test 46 | void testHashTree() { 47 | Logger.init(); 48 | String str = "lfkdsk == 1 || (lfkdsk == 1)"; 49 | HashMap cache = new HashMap<>(); 50 | 51 | JustContext context = new JustMapContext() {{ 52 | put("lfkdsk", 1); 53 | }}; 54 | 55 | AstProgram node = (AstProgram) toNode(str); 56 | AstNode node1 = node.getChildren().get(0); 57 | AstNode a1 = node1.child(0); 58 | AstNode a2 = node1.child(2); 59 | 60 | Object re1 = a1.eval(context); 61 | cache.put(a1.hashCode(), re1); 62 | 63 | Object re2 = cache.get(a2.hashCode()); 64 | Logger.v(re2.toString()); 65 | } 66 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | notifications: 3 | email: true 4 | jdk: 5 | - oraclejdk8 6 | install: 7 | - mvn install -DskipTests -Dmaven.javadoc.skip=true 8 | script: 9 | - echo "mvn package assembly:single" 10 | - mvn package assembly:single 11 | before_deploy: 12 | - git config --local user.name "JustWe" 13 | - git config --local user.email "lfk_dsk@hotmail.com" 14 | - git tag "Just-Evaluator-$(date +'%Y%m%d%H%M%S')" 15 | - mv target/*.jar 16 | - rm -rf target/surefire-reports/ 17 | deploy: 18 | provider: releases 19 | skip_cleanup: true 20 | version: 21 | name: ${PKG_VERSION} 22 | api_key: 23 | secure: Pe/Lrhz3hTO/4th9slAaiZIFd0cK9VZRr/wnGXjwMNgSDoumrXGAY0/7U6sNhBFCdamexCeyoLY2puztLdPLfMHJ7DI3Sto1VO4tJOjMsz5AO0RX79VVxpo0678YKLOOCfBW7+jrK/7hNgdNTBRVS/6BER3Zvmb8R5ioLp/T/ayWxCQDqkfT+UxST8phhhxkw5CNfs5lPtle1IyiCblWXZ5GDPzcAkOELI2IYbbP/c63cTgZDqD8UoTEbKpi3TUKnQm8VoRoyElyLauxpqb8+xI0zfSI6IEANKsSYWoXQ4whY/iEumz4d8ySR0NWFIj/hjaVuCsvzc2zzitjbKsyBc+696br12kPXeMVuWQ6aBewjRZt+Ss9nJ9u/RgAVgmLrFphgxHzc9a0Zaa0LoDnwqtfmASSNpW+m5hqTWCTAa5+NFHUe5Ev2rV/LnLKzJNTo6/W4DruKrS8oq4veLqmalxOEKs7mPVpXFnVC77kBmd8Lke9KjMh1BQU08SyE0eZGLlqwmiJgYPOV0dAqN96iYKKgUbLksROPPZTC8oc8+6mqT1BZZjNPHw+k8LCk2LkQXEPPO3wtegNZNgebeeji6EF5KvmDf5pptelT94xzyEBBdc/K6nWROna/NJq9Bw0tKBLfe+I3Fgq+KIHYBZIF0UuLJKnvP2tnqZNbYwZVso= 24 | file: target/just-el-2.2.1-SNAPSHOT-jar-with-dependencies.jar 25 | on: 26 | repo: lfkdsk/Just-Evaluator 27 | all_branches: false 28 | branch: master 29 | env: 30 | global: 31 | secure: b3sV0h2+Trg1DFC7T+LqpcXn9SXdGES53f4awMfF0dtcFF6h+MO+c2tBKK0UGQJA6QcxngIHyLaZ7tLRa4m88RZiZccRZmTdHWVdsbTNv6BsIJYDlPB6kky9S3ulgdYgPASG2d+ECNWqvkgujDbIz0pxq5rZQzjelDSzWM8+z1KXvLAkfAWDC5pSYYsZy7yQ+1innK5yYm6la89weD/jsG2sAN+y3TFifss4+a+L/BAxCjfV7bhWV47mXuchu5N0GN6HMxOC4zlu8I++T+3X5Xkkrq19Gbhai9s9OMjqGUjPch05Nl8gpMDylFs5HvF/AgDm8ms/ebrs3fcJpeFGrrQ8xEaCYwlIpVBdOIgIIYUq4Mr5hifo1ErCrfMxEZRMoxgZLBGp+lMRbE6kPj4fQtJs+dP77+Psh2aPrp6BfC1QRZu48NejyUH5Sss2og8t1qAsL3EdBoe6hGP9AGEAO78zE9Om6bsbnSyMUo3CNxGTXQIdVayHHuoEy4Tz5xRsJzMo8ohPT1gLghOwPReUAu0B5JXDCUXzOZhUnLgFrUM6HVkKsmRUQn9WaHYElAjkC3KS+rVWRbgoOkQlOaniuw+vrjEQOJ6b31ouagHrOC3B1xOiTvEKdwyAaeD/4kb6Sl1oeHCh7vHxtNsOJlpurs6llEoLb2GhC/gmE4mPmkA= 32 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/generate/Var.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.compile.generate; 10 | 11 | import com.lfkdsk.justel.utils.ReflectUtils; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | /** 15 | * Var Abstract Class 16 | * 17 | * @author liufengkai 18 | * Created by liufengkai on 2017/8/4. 19 | */ 20 | public final class Var { 21 | 22 | private String name; 23 | 24 | private Class type; 25 | 26 | private Object value; 27 | 28 | private static Var cache = new Var("object", new Object()); 29 | 30 | public Var(@NotNull String name, @NotNull Object value) { 31 | this.name = name; 32 | this.value = value; 33 | this.type = value.getClass(); 34 | } 35 | 36 | public static String getTypeDeclare(Class objType) { 37 | String typeDeclare = objType.getCanonicalName(); 38 | 39 | if (typeDeclare == null) typeDeclare = objType.getName(); 40 | 41 | if (ReflectUtils.isPrimitiveOrWrapNumber(objType)) { 42 | objType = ReflectUtils.toPrimitiveClass(objType); 43 | typeDeclare = objType.getSimpleName(); 44 | } 45 | 46 | return typeDeclare; 47 | } 48 | 49 | private void setValue(@NotNull Object o) { 50 | this.value = o; 51 | this.type = o.getClass(); 52 | } 53 | 54 | private void setName(@NotNull String name) { 55 | this.name = name; 56 | } 57 | 58 | public static Var of(String name, Object obj) { 59 | cache.setValue(obj); 60 | cache.setName(name); 61 | 62 | return cache; 63 | } 64 | 65 | public String getName() { 66 | return name; 67 | } 68 | 69 | public Class getType() { 70 | return type; 71 | } 72 | 73 | public Object getValue() { 74 | return value; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/AndOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.exception.EvalException; 15 | import com.lfkdsk.justel.token.SepToken; 16 | import com.lfkdsk.justel.token.Token; 17 | 18 | import java.util.List; 19 | 20 | import static com.lfkdsk.justel.utils.TypeUtils.isBoolean; 21 | 22 | /** 23 | * && Operator 24 | * eq: expr && expr 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/27. 28 | * @see OperatorExpr 29 | */ 30 | public class AndOp extends OperatorExpr { 31 | 32 | public AndOp(List children) { 33 | super(children, Token.AND); 34 | } 35 | 36 | @Override 37 | public String funcName() { 38 | return SepToken.AND_TOKEN.getText(); 39 | } 40 | 41 | @Override 42 | public Object eval(JustContext env) { 43 | if (operator().tag() != Token.AND) { 44 | throw new EvalException("cannot invalidate operator && ", this); 45 | } 46 | 47 | Object leftValue = leftChild().eval(env); 48 | Object rightValue = rightChild().eval(env); 49 | 50 | // check null 51 | // Object returnVal = checkNull( 52 | // leftValue, 53 | // rightValue, 54 | // (left -> left == Boolean.TRUE), 55 | // (right -> right == Boolean.TRUE)); 56 | // 57 | // if (returnVal != Boolean.FALSE) return returnVal; 58 | 59 | // is boolean 60 | if (isBoolean(leftValue) && isBoolean(rightValue)) { 61 | return leftValue == Boolean.TRUE 62 | && rightValue == Boolean.TRUE; 63 | } 64 | 65 | return super.eval(env); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/logger/Settings.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.logger; 2 | 3 | public final class Settings { 4 | 5 | private int methodCount = 2; 6 | private boolean showThreadInfo = true; 7 | private int methodOffset = 0; 8 | private LogTool logTool; 9 | 10 | /** 11 | * Determines how logs will printed 12 | */ 13 | private LogLevel logLevel = LogLevel.FULL; 14 | 15 | public Settings hideThreadInfo() { 16 | showThreadInfo = false; 17 | return this; 18 | } 19 | 20 | /** 21 | * Use {@link #methodCount} 22 | */ 23 | @Deprecated 24 | public Settings setMethodCount(int methodCount) { 25 | return methodCount(methodCount); 26 | } 27 | 28 | public Settings methodCount(int methodCount) { 29 | if (methodCount < 0) { 30 | methodCount = 0; 31 | } 32 | this.methodCount = methodCount; 33 | return this; 34 | } 35 | 36 | /** 37 | * Use {@link #logLevel} 38 | */ 39 | @Deprecated 40 | public Settings setLogLevel(LogLevel logLevel) { 41 | return logLevel(logLevel); 42 | } 43 | 44 | public Settings logLevel(LogLevel logLevel) { 45 | this.logLevel = logLevel; 46 | return this; 47 | } 48 | 49 | /** 50 | * Use {@link #methodOffset} 51 | */ 52 | @Deprecated 53 | public Settings setMethodOffset(int offset) { 54 | return methodOffset(offset); 55 | } 56 | 57 | public Settings methodOffset(int offset) { 58 | this.methodOffset = offset; 59 | return this; 60 | } 61 | 62 | public Settings logTool(LogTool logTool) { 63 | this.logTool = logTool; 64 | return this; 65 | } 66 | 67 | public int getMethodCount() { 68 | return methodCount; 69 | } 70 | 71 | public boolean isShowThreadInfo() { 72 | return showThreadInfo; 73 | } 74 | 75 | public LogLevel getLogLevel() { 76 | return logLevel; 77 | } 78 | 79 | public int getMethodOffset() { 80 | return methodOffset; 81 | } 82 | 83 | public LogTool getLogTool() { 84 | if (logTool == null) { 85 | logTool = new DebugLogTool(); 86 | } 87 | return logTool; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/token/BoolToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.token; 10 | 11 | import com.lfkdsk.justel.exception.UnSupportMethodException; 12 | 13 | /** 14 | * Boolean Token 15 | * 16 | * @author liufengkai 17 | * Created by liufengkai on 2017/7/26. 18 | * @see com.lfkdsk.justel.token.Token 19 | * @see com.lfkdsk.justel.token.ReservedToken 20 | * @see com.lfkdsk.justel.literal.BoolLiteral 21 | */ 22 | public class BoolToken extends ReservedToken { 23 | 24 | public enum BooleanEnum { 25 | TRUE("true"), 26 | FALSE("false"); 27 | 28 | private final String booleanToken; 29 | 30 | BooleanEnum(String token) { 31 | this.booleanToken = token; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return booleanToken; 37 | } 38 | } 39 | 40 | public BoolToken(int lineNumber, BooleanEnum booleanEnum) { 41 | super(lineNumber, booleanEnum.toString()); 42 | } 43 | 44 | /** 45 | * Judge token => Boolean Value 46 | * 47 | * @param token tokenString 48 | * @return BooleanEnum 49 | */ 50 | public static BooleanEnum booleanValue(String token) { 51 | for (BooleanEnum booleanEnum : BooleanEnum.values()) { 52 | if (booleanEnum.booleanToken.equals(token)) { 53 | return booleanEnum; 54 | } 55 | } 56 | 57 | throw new UnSupportMethodException("use wrong boolean token " + token); 58 | } 59 | 60 | @Override 61 | public boolean isBool() { 62 | return true; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "BoolToken{" + 68 | "token='" + token + '\'' + 69 | ", lineNumber=" + lineNumber + 70 | ", tag=" + tag + 71 | '}'; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/CondOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.token.Token; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * Cond Operator 20 | * expr ? expr : expr 21 | * 22 | * @author liufengkai 23 | * Created by liufengkai on 2017/7/29. 24 | * @see OperatorExpr 25 | */ 26 | public class CondOp extends OperatorExpr { 27 | 28 | private Boolean isCond = null; 29 | 30 | public CondOp(List children) { 31 | super(children, Token.COND); 32 | } 33 | 34 | @Override 35 | public String funcName() { 36 | return "?:"; 37 | } 38 | 39 | public void setCond(boolean cond) { 40 | isCond = cond; 41 | } 42 | 43 | private AstNode trueExpr() { 44 | return child(0); 45 | } 46 | 47 | private AstNode falseExpr() { 48 | return child(1); 49 | } 50 | 51 | @Override 52 | public Object eval(JustContext env) { 53 | if (isCond != null) { 54 | if (isCond) { 55 | return trueExpr().eval(env); 56 | } else { 57 | return falseExpr().eval(env); 58 | } 59 | } 60 | 61 | return super.eval(env); 62 | } 63 | 64 | @Override 65 | public String compile(JustContext env) { 66 | return "?" + trueExpr().toString() + ":" + falseExpr().toString(); 67 | } 68 | 69 | @Override 70 | protected boolean isShouldSplit() { 71 | return false; 72 | } 73 | 74 | @Override 75 | public boolean isConstNode() { 76 | return false; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return "(?: " + trueExpr().toString() + " " + falseExpr().toString() + ")"; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/function/ExtendFunctionExprTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.function; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import com.lfkdsk.justel.utils.logger.Logger; 14 | import org.junit.jupiter.api.Assertions; 15 | import org.junit.jupiter.api.Test; 16 | 17 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 18 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 19 | 20 | /** 21 | * Created by liufengkai on 2017/8/3. 22 | */ 23 | public class ExtendFunctionExprTest { 24 | 25 | public static class ExtendFunc extends ExtendFunctionExpr { 26 | 27 | @Override 28 | public String funcName() { 29 | return "add"; 30 | } 31 | 32 | @Override 33 | public Object call(Object... params) { 34 | Integer left = (Integer) params[0]; 35 | Integer right = (Integer) params[1]; 36 | 37 | if (left != null && right != null) { 38 | return left + right; 39 | } 40 | 41 | return this.call(params); 42 | } 43 | } 44 | 45 | 46 | @Test 47 | void testExtendFunc() { 48 | ExtendFunc func = new ExtendFunc(); 49 | String returnStr = runExpr("add(1111,2222)", 50 | true, 51 | new JustMapContext() {{ 52 | putExtendFunc(func); 53 | }}); 54 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 3333); 55 | } 56 | 57 | 58 | @Test 59 | void testExtendFuncCompiler() { 60 | Logger.init(); 61 | ExtendFunc func = new ExtendFunc(); 62 | JustContext context = new JustMapContext(); 63 | context.putExtendFunc(func); 64 | String returnStr = compiler("add(1111,2222)", context); 65 | Assertions.assertEquals((int) Integer.valueOf(returnStr), 3333); 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/literal/NumberLiteral.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.literal; 2 | 3 | import com.lfkdsk.justel.context.JustContext; 4 | import com.lfkdsk.justel.exception.ParseException; 5 | import com.lfkdsk.justel.token.NumberToken; 6 | import com.lfkdsk.justel.token.Token; 7 | 8 | import static com.lfkdsk.justel.utils.NumberUtils.castTokenValue; 9 | 10 | /** 11 | * Number Literal. 12 | * We support two kinds of Number Value : 13 | * - Long Value 14 | * - Integer Value 15 | * - Float Value 16 | * - Double Value 17 | * 18 | * @author liufengkai 19 | * Created by liufengkai on 2017/7/24. 20 | */ 21 | public class NumberLiteral extends Literal { 22 | 23 | /** 24 | * Inner number 25 | */ 26 | private Number number; 27 | 28 | public NumberLiteral(Token token) { 29 | super(token); 30 | 31 | if (token instanceof NumberToken) { 32 | this.number = ((NumberToken) token).getNumberValue(); 33 | } else { 34 | throw new ParseException("UnSupport number name where token " + 35 | "type is not NumberToken"); 36 | } 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | switch (token.getTag()) { 42 | case Token.INTEGER: 43 | return String.valueOf(number.intValue()); 44 | case Token.LONG: 45 | return String.valueOf(number.longValue()); 46 | case Token.FLOAT: 47 | return String.valueOf(number.floatValue()); 48 | case Token.DOUBLE: 49 | return String.valueOf(number.doubleValue()); 50 | default: 51 | return "undefine number literal"; 52 | } 53 | } 54 | 55 | public NumberToken numberToken() { 56 | return (NumberToken) token; 57 | } 58 | 59 | @Override 60 | public Object eval(JustContext env) { 61 | return castTokenValue(numberToken()); 62 | } 63 | 64 | @Override 65 | public String compile(JustContext env) { 66 | switch (token.getTag()) { 67 | case Token.LONG: 68 | return number.longValue() + "L"; 69 | case Token.FLOAT: 70 | return number.floatValue() + "F"; 71 | case Token.DOUBLE: 72 | return number.doubleValue() + "D"; 73 | } 74 | 75 | return super.compile(env); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/context/JustMapContext.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.context; 2 | 3 | import com.lfkdsk.justel.ast.function.ExtendFunctionExpr; 4 | import com.lfkdsk.justel.utils.ObjectHelper; 5 | 6 | import java.util.*; 7 | 8 | /** 9 | * Just Map Context 10 | * 11 | * @author liufengkai 12 | * Created by liufengkai on 2017/7/18. 13 | */ 14 | public class JustMapContext implements JustContext { 15 | 16 | private Map map = new HashMap<>(); 17 | 18 | private List commandList = new LinkedList<>(); 19 | 20 | private Map extFunc = new HashMap<>(); 21 | 22 | private Map astCache = new HashMap<>(); 23 | 24 | @Override 25 | public boolean contain(String name) { 26 | return map.containsKey(name); 27 | } 28 | 29 | @Override 30 | public Object remove(String key) { 31 | return map.remove(key); 32 | } 33 | 34 | @Override 35 | public Object get(String objName) { 36 | return map.get(objName); 37 | } 38 | 39 | @Override 40 | public Object put(String key, Object val) { 41 | return map.put(key, val); 42 | } 43 | 44 | @Override 45 | public Object getCache(Integer astHash) { 46 | return astCache.get(astHash); 47 | } 48 | 49 | @Override 50 | public Object putCache(Integer key, Object val) { 51 | return astCache.put(key, val); 52 | } 53 | 54 | @Override 55 | public ExtendFunctionExpr putExtendFunc(ExtendFunctionExpr expr) { 56 | return extFunc.put(expr.funcName(), expr); 57 | } 58 | 59 | @Override 60 | public ExtendFunctionExpr getExtendFunc(String name) { 61 | return extFunc.get(name); 62 | } 63 | 64 | @Override 65 | public Object command(String command) { 66 | ObjectHelper.requireNonNull(command, "command could not null"); 67 | 68 | return commandList.add(command); 69 | } 70 | 71 | @Override 72 | public Collection varsKeySet() { 73 | return map.keySet(); 74 | } 75 | 76 | @Override 77 | public List commandList() { 78 | return commandList; 79 | } 80 | 81 | @Override 82 | public List functions() { 83 | return new ArrayList<>(extFunc.keySet()); 84 | } 85 | 86 | @Override 87 | public boolean clearVars() { 88 | map.clear(); 89 | return true; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/function/ExtendFunctionExpr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.function; 10 | 11 | import com.lfkdsk.justel.ast.tree.AstFuncArguments; 12 | import com.lfkdsk.justel.ast.tree.AstFuncExpr; 13 | import com.lfkdsk.justel.context.JustContext; 14 | import com.lfkdsk.justel.eval.Evaluable; 15 | import com.lfkdsk.justel.exception.EvalException; 16 | 17 | /** 18 | * ExtendFunction Basic Expr 19 | * 20 | * @author liufengkai 21 | * Created by liufengkai on 2017/8/3. 22 | */ 23 | public abstract class ExtendFunctionExpr implements Function, Evaluable { 24 | 25 | /** 26 | * FuncExpr Node 27 | */ 28 | private AstFuncExpr astFuncNode; 29 | 30 | /** 31 | * bind this to AstFuncNode 32 | * 33 | * @param astFuncNode FuncExpr Node 34 | */ 35 | public void bindToAstFunc(AstFuncExpr astFuncNode) { 36 | this.astFuncNode = astFuncNode; 37 | } 38 | 39 | @Override 40 | public Object eval(JustContext env) { 41 | if (astFuncNode != null) { 42 | AstFuncArguments args = astFuncNode.funcArgs(); 43 | int count = args.childCount(); 44 | // compute new args 45 | Object[] newArgs = new Object[count]; 46 | for (int i = 0; i < count; i++) { 47 | newArgs[i] = args.child(i).eval(env); 48 | } 49 | 50 | if (!paramsCheck(newArgs)) { 51 | throw new EvalException("didn't pass params check."); 52 | } 53 | 54 | return call(newArgs); 55 | } 56 | 57 | throw new EvalException("Undefined eval func"); 58 | } 59 | 60 | /** 61 | * call the function value 62 | * 63 | * @param params params 64 | * @return is valid? 65 | */ 66 | public abstract Object call(Object... params); 67 | 68 | /** 69 | * check params value and type 70 | * 71 | * @param params paramsx 72 | * @return is valid? 73 | */ 74 | protected boolean paramsCheck(Object[] params) { 75 | return true; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/tree/AstProgram.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import com.lfkdsk.justel.ast.base.AstList; 12 | import com.lfkdsk.justel.ast.base.AstNode; 13 | import com.lfkdsk.justel.ast.function.OperatorExpr; 14 | import com.lfkdsk.justel.context.JustContext; 15 | import com.lfkdsk.justel.eval.ConstExpression; 16 | import com.lfkdsk.justel.eval.Expression; 17 | 18 | import java.util.List; 19 | 20 | import static com.lfkdsk.justel.utils.TypeUtils.isOperatorExpr; 21 | 22 | /** 23 | * Ast Program 24 | * Program is just a wrapper of Ast. 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/26. 28 | */ 29 | public class AstProgram extends AstList { 30 | 31 | private boolean isProgramConst = false; 32 | 33 | private ConstExpression constExpression = null; 34 | 35 | public AstProgram(List children) { 36 | super(children, PROGRAM); 37 | } 38 | 39 | public AstNode program() { 40 | return child(0); 41 | } 42 | 43 | public boolean checkConst() { 44 | AstNode program = program(); 45 | 46 | if (isOperatorExpr(program)) { 47 | this.isProgramConst = ((OperatorExpr) program).isConstNode(); 48 | } 49 | 50 | return isProgramConst; 51 | } 52 | 53 | @Override 54 | public Object eval(JustContext env) { 55 | if (isProgramConst) { 56 | if (constExpression == null) { 57 | constExpression = new ConstExpression(program().eval(env)); 58 | } 59 | 60 | return constExpression.eval(env); 61 | } 62 | 63 | return program().eval(env); 64 | } 65 | 66 | public boolean isProgramConst() { 67 | return isProgramConst; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return super.toString(); 73 | } 74 | 75 | public Expression getConstExpression(JustContext env) { 76 | return constExpression == null 77 | ? constExpression = new ConstExpression(program().eval(env)) 78 | : constExpression; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/template/TemplateImplTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.template; 2 | 3 | import com.lfkdsk.justel.context.JustMapContext; 4 | import com.lfkdsk.justel.template.dom.DomCom; 5 | import org.junit.jupiter.api.Test; 6 | 7 | /** 8 | * Created by liufengkai on 2017/7/25. 9 | */ 10 | class TemplateImplTest { 11 | @Test 12 | void generateTemplate() { 13 | JustMapContext context = new JustMapContext(); 14 | context.put("${attrs}", "@Override"); 15 | context.put("${className}", "FakeName"); 16 | context.put("${localVars}", "int i = 10;"); 17 | context.put("${expression}", "0;"); 18 | 19 | DomCom templateGen = new TemplateImpl().generateTemplate(); 20 | 21 | for (int j = 0; j < 20; j++) { 22 | long start = System.currentTimeMillis(); 23 | for (int i = 0; i < 100 * 100; i++) { 24 | templateGen.fakeGenerateString(context); 25 | } 26 | long end = System.currentTimeMillis(); 27 | System.out.println(end - start); 28 | } 29 | } 30 | 31 | @Test 32 | void generateWithStringReplace() { 33 | String template = "package com.greenpineyu.fel.compile;\n" + 34 | "\n" + 35 | "import com.greenpineyu.fel.common.*;\n" + 36 | "import com.greenpineyu.fel.Expression;\n" + 37 | "import com.greenpineyu.fel.context.*;\n" + 38 | "//import org.apache.commons.lang3.ObjectUtils;\n" + 39 | "//import org.apache.commons.lang3.StringUtils;\n" + 40 | "\n" + 41 | "public class ${classname} implements Expression {\n" + 42 | " ${attrs}\n" + 43 | " public Object call(FelContext context) {\n" + 44 | " ${localVars}\n" + 45 | " return ${expression};\n" + 46 | " }\n" + 47 | "}\n"; 48 | for (int j = 0; j < 20; j++) { 49 | long start = System.currentTimeMillis(); 50 | for (int i = 0; i < 100 * 100; i++) { 51 | String src = template; 52 | src = StringUtils.replace(src, "${attrs}", "lfkdsk"); 53 | src = StringUtils.replace(src, "${localVars}", "lfkdsk"); 54 | src = StringUtils.replace(src, "${expression}", "lfkdsk"); 55 | } 56 | long end = System.currentTimeMillis(); 57 | System.out.println(end - start); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/tree/AstFuncArgumentsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 16 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 17 | 18 | /** 19 | * Created by liufengkai on 2017/8/2. 20 | */ 21 | public class AstFuncArgumentsTest { 22 | @Test 23 | void testParserFuncArgs() { 24 | // parser 25 | runExpr("lfkdsk(lfkdsk,lfkdsk,lfkdsk)", false, null); 26 | } 27 | 28 | public static class O { 29 | private int lfkdsk = 100; 30 | 31 | private int[] lllll = new int[]{111, 111, 11222}; 32 | 33 | public class Inner { 34 | public String sayHello(String ss) { 35 | return "Hello World" + ss; 36 | } 37 | } 38 | 39 | private Inner inner = new Inner(); 40 | 41 | public Inner getInner() { 42 | return inner; 43 | } 44 | 45 | public int[] getLllll() { 46 | return lllll; 47 | } 48 | 49 | public int getLfkdsk() { 50 | return lfkdsk; 51 | } 52 | } 53 | 54 | 55 | @Test 56 | void testGetter() { 57 | JustContext context = new JustMapContext(); 58 | context.put("O", new O()); 59 | runExpr("O.lfkdsk", true, context); 60 | } 61 | 62 | @Test 63 | void testMultiFunctionCall() { 64 | JustContext context = new JustMapContext(); 65 | context.put("O", new O()); 66 | runExpr("O.inner.sayHello(\"lfkdsk\")", true, context); 67 | runExpr("O.getInner().sayHello(\"lfkdsk\")", true, context); 68 | } 69 | 70 | @Test 71 | void testCompilerGetter() { 72 | JustContext context = new JustMapContext(); 73 | context.put("O", new O()); 74 | compiler("O.lfkdsk", context); 75 | compiler("O.lllll[2]", context); 76 | compiler("O.getLllll()[2]", context); 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/TypeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.utils; 10 | 11 | import com.lfkdsk.justel.ast.function.OperatorExpr; 12 | import com.lfkdsk.justel.literal.IDLiteral; 13 | import com.lfkdsk.justel.literal.Literal; 14 | import com.lfkdsk.justel.literal.NumberLiteral; 15 | import com.lfkdsk.justel.literal.StringLiteral; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * Type Utils 21 | * 22 | * @author liufengkai 23 | * Created by liufengkai on 2017/7/28. 24 | */ 25 | public final class TypeUtils { 26 | 27 | private TypeUtils () {} 28 | 29 | public static boolean isNumber(Object obj) { 30 | return obj instanceof Number; 31 | } 32 | 33 | public static boolean isBoolean(Object obj) { 34 | return obj instanceof Boolean; 35 | } 36 | 37 | public static boolean isString(Object obj) { 38 | return obj instanceof String; 39 | } 40 | 41 | public static boolean isInteger(Object obj) { 42 | return obj instanceof Integer; 43 | } 44 | 45 | public static boolean isObjectArray(Object obj) { 46 | return obj instanceof Object[]; 47 | } 48 | 49 | public static boolean isList(Object obj) { 50 | return obj instanceof List; 51 | } 52 | 53 | public static boolean isArray(Object obj) { 54 | return obj.getClass().isArray(); 55 | } 56 | 57 | public static boolean isLiteral(Object obj) { 58 | return obj instanceof Literal; 59 | } 60 | 61 | public static boolean isNumberLiteral(Object obj) { 62 | return obj instanceof NumberLiteral; 63 | } 64 | 65 | public static boolean isStringLiteral(Object obj) { 66 | return obj instanceof StringLiteral; 67 | } 68 | 69 | public static boolean isIDLiteral(Object obj) { 70 | return obj instanceof IDLiteral; 71 | } 72 | 73 | public static boolean isOperatorExpr(Object obj) { 74 | return obj instanceof OperatorExpr; 75 | } 76 | 77 | public static boolean isNull(Object obj) { 78 | return obj == null; 79 | } 80 | 81 | public static boolean isComparable(Object obj) { 82 | return obj instanceof Comparable; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/base/AstLeaf.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.base; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.exception.EvalException; 13 | import com.lfkdsk.justel.exception.ParseException; 14 | import com.lfkdsk.justel.token.Token; 15 | import com.lfkdsk.justel.utils.ObjectHelper; 16 | import org.jetbrains.annotations.NotNull; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Iterator; 20 | 21 | /** 22 | * AST Leaf Node 23 | * 24 | * @author liufengkai 25 | * Created by liufengkai on 17/7/11. 26 | */ 27 | public class AstLeaf extends AstNode { 28 | 29 | private static final ArrayList empty = new ArrayList<>(); 30 | 31 | protected Token token; 32 | 33 | public AstLeaf(@NotNull Token token) { 34 | super(token.getTag()); 35 | this.token = ObjectHelper.requireNonNull(token, "token could not be null"); 36 | } 37 | 38 | public Token token() { 39 | return token; 40 | } 41 | 42 | @Override 43 | public AstNode child(int index) { 44 | throw new IndexOutOfBoundsException(); 45 | } 46 | 47 | @Override 48 | public Iterator children() { 49 | return empty.iterator(); 50 | } 51 | 52 | @Override 53 | public int childCount() { 54 | return 0; 55 | } 56 | 57 | @Override 58 | public String location() { 59 | return "at line " + token.getLineNumber(); 60 | } 61 | 62 | @Override 63 | public AstNode resetChild(int index, AstNode node) { 64 | throw new ParseException("Didn't support this method in Leaf"); 65 | } 66 | 67 | @Override 68 | public int computeAstLevel() { 69 | return astLevel = 1; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | if (evalString == null) { 75 | evalString = token.getText(); 76 | } 77 | 78 | return evalString; 79 | } 80 | 81 | public Object eval(JustContext env) { 82 | throw new EvalException("can not eval : " + toString(), this); 83 | } 84 | 85 | @Override 86 | public String compile(JustContext env) { 87 | return toString(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/logger/Logger.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.logger; 2 | 3 | public final class Logger { 4 | private static final String DEFAULT_TAG = "JustDB-LOGGER"; 5 | 6 | private static Printer printer = new LoggerPrinter(); 7 | 8 | // no instance 9 | private Logger() { 10 | 11 | } 12 | 13 | /** 14 | * It is used to get the settings object in order to change settings 15 | * 16 | * @return the settings object 17 | */ 18 | public static Settings init() { 19 | return init(DEFAULT_TAG); 20 | } 21 | 22 | /** 23 | * It is used to change the tag 24 | * 25 | * @param tag is the given string which will be used in Logger as TAG 26 | */ 27 | public static Settings init(String tag) { 28 | printer = new LoggerPrinter(); 29 | return printer.init(tag); 30 | } 31 | 32 | public static void clear() { 33 | printer.clear(); 34 | printer = null; 35 | } 36 | 37 | public static Printer t(String tag) { 38 | return printer.t(tag, printer.getSettings().getMethodCount()); 39 | } 40 | 41 | public static Printer t(int methodCount) { 42 | return printer.t(null, methodCount); 43 | } 44 | 45 | public static Printer t(String tag, int methodCount) { 46 | return printer.t(tag, methodCount); 47 | } 48 | 49 | public static void d(String message, Object... args) { 50 | printer.d(message, args); 51 | } 52 | 53 | public static void e(String message, Object... args) { 54 | printer.e(null, message, args); 55 | } 56 | 57 | public static void e(Throwable throwable, String message, Object... args) { 58 | printer.e(throwable, message, args); 59 | } 60 | 61 | public static void i(String message, Object... args) { 62 | printer.i(message, args); 63 | } 64 | 65 | public static void v(String message, Object... args) { 66 | printer.v(message, args); 67 | } 68 | 69 | public static void w(String message, Object... args) { 70 | printer.w(message, args); 71 | } 72 | 73 | public static void wtf(String message, Object... args) { 74 | printer.wtf(message, args); 75 | } 76 | 77 | /** 78 | * Formats the json content and print it 79 | * 80 | * @param json the json content 81 | */ 82 | public static void json(String json) { 83 | printer.json(json); 84 | } 85 | 86 | /** 87 | * Formats the json content and print it 88 | * 89 | * @param xml the xml content 90 | */ 91 | public static void xml(String xml) { 92 | printer.xml(xml); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/ast/operators/DotExprTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.context.JustContext; 12 | import com.lfkdsk.justel.context.JustMapContext; 13 | import com.lfkdsk.justel.utils.logger.Logger; 14 | import org.junit.jupiter.api.Test; 15 | 16 | import static com.lfkdsk.justel.compile.generate.JavaCodeGeneratorTest.compiler; 17 | import static com.lfkdsk.justel.parser.JustParserImplTest.runExpr; 18 | 19 | /** 20 | * Created by liufengkai on 2017/8/2. 21 | */ 22 | public class DotExprTest { 23 | 24 | public class O { 25 | String ffff = "sss"; 26 | 27 | public class F { 28 | String llll = "fff"; 29 | 30 | public String getLlll() { 31 | return llll; 32 | } 33 | } 34 | 35 | F f = new F(); 36 | 37 | public F getF() { 38 | return f; 39 | } 40 | 41 | public String lfk() { 42 | return "fffffff"; 43 | } 44 | 45 | public String lfkdsk(String val) { 46 | return val; 47 | } 48 | } 49 | 50 | @Test 51 | void testDotExpr() { 52 | JustContext context = new JustMapContext(); 53 | context.put("lfkdsk", new O()); 54 | runExpr("lfkdsk.lfk()", true, context); 55 | } 56 | 57 | @Test 58 | void testDotValueExpr() { 59 | JustContext context = new JustMapContext(); 60 | context.put("lfkdsk", new O()); 61 | runExpr("lfkdsk.ffff", true, context); 62 | } 63 | 64 | @Test 65 | void testDotManyExpr() { 66 | JustContext context = new JustMapContext(); 67 | context.put("lfkdsk", new O()); 68 | runExpr("lfkdsk.lfkdsk(\"1111111\")", true, context); 69 | } 70 | 71 | @Test 72 | void testDotExprCompiler() { 73 | JustContext context = new JustMapContext(); 74 | context.put("lfkdsk", new O()); 75 | Logger.init(); 76 | Logger.i(compiler("lfkdsk.lfkdsk(\"1111111\")", context)); 77 | } 78 | 79 | @Test 80 | void testDotEvalDouble() { 81 | JustContext context = new JustMapContext(); 82 | context.put("lfkdsk", new O()); 83 | Logger.init(); 84 | Logger.i(compiler("lfkdsk.f.llll", context)); 85 | } 86 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/tree/AstBinaryExpr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import com.lfkdsk.justel.ast.base.AstLeaf; 12 | import com.lfkdsk.justel.ast.base.AstList; 13 | import com.lfkdsk.justel.ast.base.AstNode; 14 | import com.lfkdsk.justel.ast.function.Operator; 15 | import com.lfkdsk.justel.context.JustContext; 16 | import com.lfkdsk.justel.exception.CompilerException; 17 | import com.lfkdsk.justel.exception.EvalException; 18 | import com.lfkdsk.justel.parser.BnfCom; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Ast Binary Expr 24 | * Binary Expr will be replace by Operator Expr 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/26. 28 | * @see com.lfkdsk.justel.parser.JustParserImpl 29 | * @see com.lfkdsk.justel.ast.function.OperatorExpr 30 | */ 31 | public class AstBinaryExpr extends AstList { 32 | 33 | public AstBinaryExpr(List children) { 34 | super(children, AstNode.BINARY_EXPR); 35 | } 36 | 37 | public AstNode leftChild() { 38 | return child(0); 39 | } 40 | 41 | public AstNode rightChild() { 42 | return child(2); 43 | } 44 | 45 | public AstLeaf midOp() { 46 | return (AstLeaf) child(1); 47 | } 48 | 49 | /** 50 | * Reset AstBinaryExpr to Particular Expr 51 | * We use BinaryExpr to handle priority of Operator. 52 | * So we should change it to particular Expr to compute the name. 53 | * 54 | * @param expr Origin AstBinaryExpr 55 | * @param operators Support Operators 56 | * @return New Particular Expr 57 | */ 58 | private AstNode resetAstExpr(AstBinaryExpr expr, BnfCom.Operators operators) { 59 | // operator is Operator 60 | Operator operator = (Operator) expr.midOp(); 61 | // get the factory of sub-node 62 | BnfCom.Factory factory = operators.get(operator.operator()).factory; 63 | // use list to make new node 64 | 65 | return factory.make(expr.getChildren()); 66 | } 67 | 68 | @Override 69 | public Object eval(JustContext env) { 70 | throw new EvalException("can not call basic binary expr node", this); 71 | } 72 | 73 | @Override 74 | public String compile(JustContext env) { 75 | throw new CompilerException("can not compile basic binary expr node", this); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/operators/ArrayIndexExpr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.operators; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.ast.function.OperatorExpr; 13 | import com.lfkdsk.justel.ast.tree.AstPostfixExpr; 14 | import com.lfkdsk.justel.context.JustContext; 15 | 16 | import java.lang.reflect.Array; 17 | import java.util.List; 18 | 19 | import static com.lfkdsk.justel.utils.TypeUtils.isArray; 20 | import static com.lfkdsk.justel.utils.TypeUtils.isNumber; 21 | import static com.lfkdsk.justel.utils.TypeUtils.isObjectArray; 22 | 23 | /** 24 | * [] Array Index 25 | * eq: Object[] \ int[] \ float[] 26 | * 27 | * @author liufengkai 28 | * Created by liufengkai on 2017/7/26. 29 | * @see OperatorExpr 30 | * @see AstPostfixExpr 31 | */ 32 | public class ArrayIndexExpr extends OperatorExpr implements AstPostfixExpr { 33 | 34 | public ArrayIndexExpr(List children) { 35 | super(children, AstNode.ARRAY_INDEX_OP); 36 | } 37 | 38 | public AstNode index() { 39 | return child(0); 40 | } 41 | 42 | @Override 43 | public Object eval(JustContext env, Object value) { 44 | Object index = index().eval(env); 45 | // index of array 46 | if (isNumber(index)) { 47 | if (isObjectArray(value)) { 48 | // object array 49 | return ((Object[]) value)[(int) index]; 50 | } else if (isArray(value)) { 51 | 52 | // origin array 53 | return Array.get(value, (Integer) index); 54 | } 55 | } 56 | 57 | return this.eval(env); 58 | } 59 | 60 | @Override 61 | public Object compile(JustContext env, Object value, StringBuilder builder) { 62 | return builder.append(compile(env)); 63 | } 64 | 65 | @Override 66 | public String compile(JustContext env) { 67 | return "[" + index().toString() + "]"; 68 | } 69 | 70 | @Override 71 | public String funcName() { 72 | return "[]"; 73 | } 74 | 75 | @Override 76 | public boolean isConstNode() { 77 | return false; 78 | } 79 | 80 | @Override 81 | protected boolean isShouldSplit() { 82 | return false; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "([] " + index().toString() + ")"; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/generate/JavaCodeGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.compile.generate; 10 | 11 | import com.lfkdsk.justel.ast.base.AstNode; 12 | import com.lfkdsk.justel.context.JustContext; 13 | import com.lfkdsk.justel.context.JustMapContext; 14 | import com.lfkdsk.justel.template.TemplateImpl; 15 | import com.lfkdsk.justel.template.dom.DomCom; 16 | import com.lfkdsk.justel.utils.GeneratedId; 17 | import lombok.Getter; 18 | import lombok.Setter; 19 | 20 | import java.util.*; 21 | 22 | /** 23 | * Java Code => Generator 24 | * AST + Template Tree => Java Source Code 25 | * 26 | * @author liufengkai 27 | * Created by liufengkai on 2017/7/20. 28 | */ 29 | public final class JavaCodeGenerator implements Generator { 30 | 31 | @Getter 32 | @Setter 33 | private DomCom mTemplate = new TemplateImpl().generateTemplate(); 34 | 35 | private String generateLocalVars(JustContext context) { 36 | if (context == null) return ""; 37 | StringBuilder builder = new StringBuilder(); 38 | 39 | Collection keySet = context.varsKeySet(); 40 | for (String key : keySet) { 41 | Var var = Var.of(key, context.get(key)); 42 | builder.append(context.generateVarAssignCode(var)); 43 | } 44 | 45 | List commandSet = context.commandList(); 46 | 47 | for (String command : commandSet) { 48 | builder.append(command); 49 | } 50 | 51 | return builder.toString(); 52 | } 53 | 54 | @Override 55 | public JavaSource generate(JustContext context, AstNode rootNode) { 56 | JustContext templateContext = new JustMapContext(); 57 | String className = "JustEL" + GeneratedId.generateAtomId(); 58 | 59 | templateContext.put("${className}", className); 60 | templateContext.put("${expression}", rootNode.compile(context)); 61 | // after generate Ast -> generate local vars 62 | // some vars maybe latter than AST Compile 63 | templateContext.put("${localVars}", generateLocalVars(context)); 64 | templateContext.put("${attrs}", ""); 65 | 66 | return new JavaSource(JavaSource.GENERATE_DEFAULT_PACKAGE, 67 | className, mTemplate.fakeGenerateString(templateContext)); 68 | 69 | } 70 | 71 | public static Generator create() { 72 | return new JavaCodeGenerator(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/utils/collection/ContainerHelpers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.lfkdsk.justel.utils.collection; 18 | 19 | class ContainerHelpers { 20 | static final int[] EMPTY_INTS = new int[0]; 21 | static final long[] EMPTY_LONGS = new long[0]; 22 | static final Object[] EMPTY_OBJECTS = new Object[0]; 23 | 24 | public static int idealIntArraySize(int need) { 25 | return idealByteArraySize(need * 4) / 4; 26 | } 27 | 28 | public static int idealLongArraySize(int need) { 29 | return idealByteArraySize(need * 8) / 8; 30 | } 31 | 32 | public static int idealByteArraySize(int need) { 33 | for (int i = 4; i < 32; i++) 34 | if (need <= (1 << i) - 12) 35 | return (1 << i) - 12; 36 | 37 | return need; 38 | } 39 | 40 | public static boolean equal(Object a, Object b) { 41 | return a == b || (a != null && a.equals(b)); 42 | } 43 | 44 | // This is Arrays.binarySearch(), but doesn't do any argument validation. 45 | static int binarySearch(int[] array, int size, int value) { 46 | int lo = 0; 47 | int hi = size - 1; 48 | 49 | while (lo <= hi) { 50 | int mid = (lo + hi) >>> 1; 51 | int midVal = array[mid]; 52 | 53 | if (midVal < value) { 54 | lo = mid + 1; 55 | } else if (midVal > value) { 56 | hi = mid - 1; 57 | } else { 58 | return mid; // value found 59 | } 60 | } 61 | return ~lo; // value not present 62 | } 63 | 64 | static int binarySearch(long[] array, int size, long value) { 65 | int lo = 0; 66 | int hi = size - 1; 67 | 68 | while (lo <= hi) { 69 | final int mid = (lo + hi) >>> 1; 70 | final long midVal = array[mid]; 71 | 72 | if (midVal < value) { 73 | lo = mid + 1; 74 | } else if (midVal > value) { 75 | hi = mid - 1; 76 | } else { 77 | return mid; // value found 78 | } 79 | } 80 | return ~lo; // value not present 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/utils/collection/ArrayMapTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.utils.collection; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | 8 | class ArrayMapTest { 9 | 10 | @Test 11 | void testSkipTest() { 12 | SkipList skipList = new SkipList<>(); 13 | skipList.put("a", 3600); 14 | skipList.put("b", 10); 15 | skipList.put("c", 100); 16 | 17 | int sum = 0; 18 | long start = System.currentTimeMillis(); 19 | for (int i = 0; i < 1_0000_0000; i++) { 20 | int a = (int) skipList.get("a"); 21 | int b = (int) skipList.get("b"); 22 | int c = (int) skipList.get("c"); 23 | sum += a + b + c; 24 | } 25 | 26 | System.out.println(" " + (System.currentTimeMillis() - start) + " ms"); 27 | } 28 | 29 | @Test 30 | void testHashTest() { 31 | HashMap hashMap = new HashMap<>(); 32 | hashMap.put("a", 3600); 33 | hashMap.put("b", 10); 34 | hashMap.put("c", 100); 35 | 36 | int sum = 0; 37 | long start = System.currentTimeMillis(); 38 | for (int i = 0; i < 1_0000_0000; i++) { 39 | int a = (int) hashMap.get("a"); 40 | int b = (int) hashMap.get("b"); 41 | int c = (int) hashMap.get("c"); 42 | 43 | sum += a + b + c; 44 | } 45 | 46 | System.out.println(" " + (System.currentTimeMillis() - start) + " ms"); 47 | } 48 | 49 | @Test 50 | void testArrayHashTest() { 51 | ArrayMap arrayMap = new ArrayMap<>(); 52 | arrayMap.put("a", 3600); 53 | arrayMap.put("b", 10); 54 | arrayMap.put("c", 100); 55 | 56 | int sum = 0; 57 | long start = System.currentTimeMillis(); 58 | for (int i = 0; i < 1_0000_0000; i++) { 59 | int a = (int) arrayMap.get("a"); 60 | int b = (int) arrayMap.get("b"); 61 | int c = (int) arrayMap.get("c"); 62 | 63 | sum += a + b + c; 64 | } 65 | 66 | System.out.println(" " + (System.currentTimeMillis() - start) + " ms"); 67 | } 68 | 69 | @Test 70 | void testArray() { 71 | ArrayList arrayMap = new ArrayList<>(); 72 | arrayMap.add(3600); 73 | arrayMap.add(10); 74 | arrayMap.add(100); 75 | 76 | int sum = 0; 77 | long start = System.currentTimeMillis(); 78 | for (int i = 0; i < 1_0000_0000; i++) { 79 | int a = (int) arrayMap.get(0); 80 | int b = (int) arrayMap.get(1); 81 | int c = (int) arrayMap.get(2); 82 | 83 | sum += a + b + c; 84 | } 85 | 86 | System.out.println(" " + (System.currentTimeMillis() - start) + " ms"); 87 | 88 | } 89 | } -------------------------------------------------------------------------------- /src/test/java/com/lfkdsk/justel/lexer/JustLexerImplTest.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.lexer; 2 | 3 | import com.lfkdsk.justel.context.JustArrayContext; 4 | import com.lfkdsk.justel.parser.JustParserImpl; 5 | import com.lfkdsk.justel.utils.logger.Logger; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.StringReader; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | /** 13 | * Created by liufengkai on 2017/7/24. 14 | */ 15 | class JustLexerImplTest { 16 | 17 | @Test 18 | void testLexer() { 19 | for (int j = 0; j < 20; j++) { 20 | String lfkdsk = String.valueOf(" \"" + RandomUtils.RandomString(10) + "\"" 21 | + " " + RandomUtils.RandomFloat(2, 20) + " " + 22 | RandomUtils.RandomInt(10, 200) + " " + "|| && *"); 23 | 24 | long startTime = System.currentTimeMillis(); 25 | for (int i = 0; i < 1000; i++) { 26 | JustLexerImpl lexer = new JustLexerImpl(new StringReader(lfkdsk)); 27 | lexer.hasMore(); 28 | } 29 | System.out.println(System.currentTimeMillis() - startTime); 30 | } 31 | } 32 | 33 | @Test 34 | void testNewSymbol() { 35 | JustLexerImpl lexer = new JustLexerImpl(new StringReader("== !== #= != ")); 36 | lexer.hasMore(); 37 | } 38 | 39 | @Test 40 | void testPoint() { 41 | JustLexerImpl lexer = new JustLexerImpl(new StringReader("a.c")); 42 | lexer.hasMore(); 43 | System.out.println("complete"); 44 | } 45 | 46 | @Test 47 | void testString() { 48 | JustLexerImpl lexer = new JustLexerImpl(); 49 | Logger.init(); 50 | // Logger.v(lexer.scanner("\"\" + \"\"").toString()); 51 | // Logger.v(lexer.scanner("\"fffff\" + \"\"").toString()); 52 | // Logger.v(lexer.scanner("\"fffff\" + \"ffffff\"").toString()); 53 | // Logger.v(lexer.scanner("\"fffff\" + \\ffffff\\").toString()); 54 | Logger.v(lexer.scanner("\" \"lfkdsk\" + \"lfkdsk\" \" + \\ffffff\\ \"").toString()); 55 | } 56 | 57 | @Test 58 | void testPattern() { 59 | Pattern pattern = Pattern.compile("(\"(\\\\\"|\\\\\\\\|\\\\n|[^\"])*\")"); 60 | Matcher matcher = pattern.matcher("\"\\\n\""); 61 | Logger.init(); 62 | Logger.v(matcher.toString()); 63 | Logger.v(String.valueOf(matcher.matches())); 64 | if (matcher.matches()) { 65 | Logger.v(matcher.group()); 66 | } 67 | } 68 | 69 | @Test 70 | void testAString() { 71 | Lexer lexer = new JustLexerImpl(); 72 | Logger.init(); 73 | Logger.v(lexer.scanner("\"lfkdsk\" + lfkdsk + 10000 + 100.0").toString()); 74 | Logger.v(new JustParserImpl().parser(lexer.tokens()).eval(new JustArrayContext() {{ 75 | put("lfkdsk", 1); 76 | }}).toString()); 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/memory/JustMemFileManager.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.memory; 2 | 3 | import com.lfkdsk.justel.compile.generate.JavaSource; 4 | 5 | import javax.tools.*; 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.FilterOutputStream; 8 | import java.io.IOException; 9 | import java.io.OutputStream; 10 | import java.net.URI; 11 | 12 | /** 13 | * Just Memory FileManager 14 | * 15 | * @author liufengkai 16 | * Created by liufengkai on 2017/7/20. 17 | */ 18 | public class JustMemFileManager extends ForwardingJavaFileManager { 19 | 20 | /** 21 | * bind to memory class-loader 22 | */ 23 | private final JustMemClassLoader classLoader; 24 | 25 | public JustMemFileManager(JavaFileManager fileManager, JustMemClassLoader memClassLoader) { 26 | super(fileManager); 27 | this.classLoader = memClassLoader; 28 | } 29 | 30 | @Override 31 | public void close() throws IOException { 32 | super.close(); 33 | } 34 | 35 | public JavaFileObject makeStringSource(JavaSource source) { 36 | return new MemInputJavaFileObject(source); 37 | } 38 | 39 | @Override 40 | public JavaFileObject getJavaFileForOutput(Location location, String className, 41 | JavaFileObject.Kind kind, FileObject sibling) throws IOException { 42 | if (kind == JavaFileObject.Kind.CLASS) { 43 | return new MemOutputJavaFileObject(className); 44 | } else { 45 | return super.getJavaFileForOutput(location, className, kind, sibling); 46 | } 47 | } 48 | 49 | static class MemInputJavaFileObject extends SimpleJavaFileObject { 50 | final JavaSource source; 51 | 52 | protected MemInputJavaFileObject(JavaSource source) { 53 | super(URI.create("string:///" + source.getFileName()), Kind.SOURCE); 54 | this.source = source; 55 | } 56 | 57 | @Override 58 | public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { 59 | return source.getSourceCodeCharSequence(); 60 | } 61 | } 62 | 63 | class MemOutputJavaFileObject extends SimpleJavaFileObject { 64 | 65 | final String className; 66 | 67 | MemOutputJavaFileObject(String className) { 68 | super(URI.create("string:///" + className), Kind.CLASS); 69 | this.className = className; 70 | } 71 | 72 | @Override 73 | public OutputStream openOutputStream() throws IOException { 74 | return new FilterOutputStream(new ByteArrayOutputStream() { 75 | @Override 76 | public void close() throws IOException { 77 | super.close(); 78 | classLoader.addBytesClass(className, this.toByteArray()); 79 | } 80 | }); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/generate/JavaSource.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.generate; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.nio.CharBuffer; 6 | 7 | import static com.lfkdsk.justel.utils.FormatUtils.beautifulPrint; 8 | import static com.lfkdsk.justel.utils.FormatUtils.insertNewLine; 9 | 10 | /** 11 | * Java Source : 12 | * - package name 13 | * - class name 14 | * - source code 15 | * - code => char (cache) 16 | * 17 | * @author liufengkai 18 | * Created by liufengkai on 2017/7/20. 19 | */ 20 | public final class JavaSource { 21 | 22 | /** 23 | * default generate package 24 | */ 25 | public static final String GENERATE_DEFAULT_PACKAGE = "com.lfkdsk.justel.generatecode"; 26 | 27 | private final String packageName; 28 | 29 | private final String className; 30 | 31 | private final String sourceCode; 32 | 33 | /** 34 | * source code => code char 35 | */ 36 | private CharSequence sourceCodeChar; 37 | 38 | public JavaSource(@NotNull String packageName, 39 | @NotNull String className, 40 | @NotNull String sourceCode) { 41 | this.className = className; 42 | this.sourceCode = sourceCode; 43 | this.packageName = packageName; 44 | } 45 | 46 | /** 47 | * class qualified name 48 | * 49 | * @return package name + class name. 50 | */ 51 | public String getClassQualifiedName() { 52 | return packageName + "." + className; 53 | } 54 | 55 | /** 56 | * file name 57 | * 58 | * @return xxx.java 59 | */ 60 | public String getFileName() { 61 | return className + ".java"; 62 | } 63 | 64 | /** 65 | * return char sequence 66 | * 67 | * @return char sequence. 68 | */ 69 | public CharSequence getSourceCodeCharSequence() { 70 | return sourceCodeChar == null ? sourceCodeChar = CharBuffer.wrap(sourceCode) : sourceCodeChar; 71 | } 72 | 73 | /** 74 | * Re-Format SourceCode -> Formatted Source Code 75 | * WARNING: JUST USED IN `toString` Method to Debug Source Code 76 | * 77 | * @return formatted source code 78 | */ 79 | private String reformatToPrint() { 80 | StringBuilder builder = new StringBuilder(sourceCode); 81 | 82 | builder = insertNewLine(builder, "{", "\r\n"); 83 | builder = insertNewLine(builder, ";", "\r\n"); 84 | 85 | String[] args = { 86 | " : ", 87 | "PackageName : " + packageName, 88 | "ClassName : " + className, 89 | "SourceCode : ", 90 | builder.toString() 91 | }; 92 | 93 | return beautifulPrint(args); 94 | } 95 | 96 | @Override 97 | public String toString() { 98 | 99 | return reformatToPrint(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/parser/ParserHelper.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.parser; 2 | 3 | import com.lfkdsk.justel.ast.base.AstList; 4 | import com.lfkdsk.justel.ast.base.AstNode; 5 | import com.lfkdsk.justel.ast.function.Operator; 6 | import com.lfkdsk.justel.ast.tree.*; 7 | 8 | import static com.lfkdsk.justel.ast.tree.AstCondExpr.isAstCondExpr; 9 | import static com.lfkdsk.justel.ast.tree.AstFuncExpr.isAstFuncExpr; 10 | 11 | /** 12 | * Parser Helper 13 | * 14 | * @author liufengkai 15 | * Created by liufengkai on 2017/8/18. 16 | */ 17 | final class ParserHelper { 18 | 19 | private ParserHelper() { 20 | 21 | } 22 | 23 | /** 24 | * Reset AstBinaryExpr to Particular Expr 25 | * We use BinaryExpr to handle priority of Operator. 26 | * So we should change it to particular Expr to compute the name. 27 | * 28 | * @param expr Origin AstBinaryExpr 29 | * @param operators Support Operators 30 | * @return New Particular Expr 31 | */ 32 | private static AstNode resetAstExpr(AstBinaryExpr expr, BnfCom.Operators operators) { 33 | 34 | // operator is Operator 35 | Operator operator = (Operator) expr.midOp(); 36 | // get the factory of sub-node 37 | BnfCom.Factory factory = operators.get(operator.operator()).factory; 38 | // use list to make new node 39 | 40 | return factory.make(expr.getChildren()); 41 | } 42 | 43 | /** 44 | * transform binary expr to spec expr 45 | * 46 | * @param parent parent node 47 | * @param operators Operators 48 | * @see JustParserImpl 49 | */ 50 | private static AstNode transformAst(AstNode parent, BnfCom.Operators operators) { 51 | for (int i = 0; i < parent.childCount(); i++) { 52 | AstNode child = parent.child(i); 53 | 54 | // fix binary => special expr 55 | if (child instanceof AstBinaryExpr) { 56 | child = resetAstExpr((AstBinaryExpr) child, operators); 57 | parent.resetChild(i, child); 58 | 59 | } else if (child instanceof AstPrimaryExpr) { 60 | // fix primary(func) => function expr 61 | if (isAstFuncExpr(child)) { 62 | child = new AstFuncExpr(((AstPrimaryExpr) child).getChildren()); 63 | parent.resetChild(i, child); 64 | } 65 | } else if (isAstCondExpr(child)) { 66 | // fix primary(cond) => cond expr 67 | child = new AstCondExpr(((AstList) child).getChildren()); 68 | parent.resetChild(i, child); 69 | } 70 | 71 | transformAst(child, operators); 72 | } 73 | 74 | return parent; 75 | } 76 | 77 | 78 | 79 | static AstNode generateAst(AstNode parent, BnfCom.Operators operators) { 80 | AstProgram root = (AstProgram) transformAst(parent, operators); 81 | 82 | root.checkConst(); 83 | 84 | return root; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/ast/tree/AstFuncExpr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.lfkdsk.justel.ast.tree; 10 | 11 | import com.lfkdsk.justel.ast.base.AstList; 12 | import com.lfkdsk.justel.ast.base.AstNode; 13 | import com.lfkdsk.justel.ast.function.ExtendFunctionExpr; 14 | import com.lfkdsk.justel.context.JustContext; 15 | import com.lfkdsk.justel.exception.UnSupportMethodException; 16 | import com.lfkdsk.justel.utils.GeneratedId; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * function( expr , expr , expr) 22 | * 23 | * @author liufengkai 24 | * Created by liufengkai on 2017/7/27. 25 | */ 26 | public class AstFuncExpr extends AstList { 27 | 28 | public AstFuncExpr(List children) { 29 | super(children, AstNode.FUNCTION_EXPR); 30 | } 31 | 32 | /** 33 | * has func expr 34 | * 35 | * @param child this child 36 | * @return is AstFuncExpr 37 | */ 38 | public static boolean isAstFuncExpr(AstNode child) { 39 | return child.childCount() >= 2 && 40 | child.child(1) instanceof AstFuncArguments; 41 | } 42 | 43 | public AstNode funcName() { 44 | return this.child(0); 45 | } 46 | 47 | public AstFuncArguments funcArgs() { 48 | return (AstFuncArguments) this.child(1); 49 | } 50 | 51 | @Override 52 | public Object eval(JustContext env) { 53 | String funcName = funcName().toString(); 54 | ExtendFunctionExpr expr = env.getExtendFunc(funcName); 55 | 56 | if (expr != null) { 57 | expr.bindToAstFunc(this); 58 | return expr.eval(env); 59 | } 60 | 61 | return super.eval(env); 62 | } 63 | 64 | @Override 65 | public String compile(JustContext env) { 66 | 67 | // generate code by one time 68 | 69 | // get func obj 70 | ExtendFunctionExpr extendFunc = env.getExtendFunc(funcName().toString()); 71 | 72 | if (extendFunc == null) { 73 | throw new UnSupportMethodException("un support method funcName: " + funcName().toString()); 74 | } 75 | 76 | StringBuilder builder = new StringBuilder(); 77 | 78 | // generate var 79 | String funcVar = "func" + GeneratedId.generateAtomId(); 80 | 81 | // put to env to generate local var 82 | // insert local func obj 83 | env.put(funcVar, extendFunc); 84 | 85 | builder.append(funcVar) 86 | .append(".call") 87 | .append("(") 88 | .append("new Object[]{") 89 | .append(funcArgs().compile(env)) 90 | .append("}") 91 | .append(")"); 92 | 93 | return builder.toString(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/token/NumberToken.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.token; 2 | 3 | /** 4 | * Number Token. 5 | * - Integer 6 | * - Long 7 | * - Float 8 | * - Double 9 | * 10 | * @author liufengkai 11 | * Created by liufengkai on 2017/7/24. 12 | * @see com.lfkdsk.justel.token.Token 13 | * @see com.lfkdsk.justel.lexer.Lexer 14 | * @see com.lfkdsk.justel.literal.NumberLiteral 15 | */ 16 | public class NumberToken extends Token { 17 | 18 | /** 19 | * name => string 20 | * ep: 1000 => "1000" \ 111.22 => "111.22" 21 | */ 22 | private String tokenString; 23 | 24 | /** 25 | * Inner Value 26 | */ 27 | private Number numberValue; 28 | 29 | /** 30 | * Number Token 31 | * 32 | * @param lineNumber location 33 | * @param tag token.tag 34 | * @param tokenString name => string 35 | * @param value number name 36 | */ 37 | public NumberToken(int lineNumber, int tag, 38 | String tokenString, Number value) { 39 | super(lineNumber, tag); 40 | this.tokenString = tokenString; 41 | this.numberValue = value; 42 | } 43 | 44 | public long longValue() { 45 | if (getTag() == Token.LONG) { 46 | return numberValue.longValue(); 47 | } 48 | 49 | return 0; 50 | // throw new TransferNumberException("wrong name check " + 51 | // "| numberValue's Type isn't long Value " + numberValue.toString()); 52 | } 53 | 54 | public int integerValue() { 55 | if (getTag() == Token.INTEGER) { 56 | return numberValue.intValue(); 57 | } 58 | 59 | return 0; 60 | // throw new TransferNumberException("wrong name check " + 61 | // "| numberValue's Type isn't integer Value " + numberValue.toString()); 62 | } 63 | 64 | public float floatValue() { 65 | if (getTag() == Token.FLOAT) { 66 | return numberValue.floatValue(); 67 | } 68 | 69 | return 0; 70 | // throw new TransferNumberException("wrong name check " + 71 | // "| numberValue's Type isn't float Value " + numberValue.toString()); 72 | } 73 | 74 | public double doubleValue() { 75 | if (getTag() == Token.DOUBLE) { 76 | return numberValue.doubleValue(); 77 | } 78 | 79 | return 0; 80 | // throw new TransferNumberException("wrong name check " + 81 | // "| numberValue's Type isn't double Value " + numberValue.toString()); 82 | } 83 | 84 | public Number getNumberValue() { 85 | return numberValue; 86 | } 87 | 88 | @Override 89 | public boolean isNumber() { 90 | return true; 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | return "NumberToken{" + 96 | "tokenString='" + tokenString + '\'' + 97 | ", numberValue=" + numberValue + 98 | ", lineNumber=" + lineNumber + 99 | ", tag=" + tag + 100 | '}'; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/context/JustArrayContext.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.context; 2 | 3 | import com.lfkdsk.justel.ast.function.ExtendFunctionExpr; 4 | import com.lfkdsk.justel.compile.generate.Var; 5 | import com.lfkdsk.justel.utils.collection.ArrayBinder; 6 | 7 | import java.util.*; 8 | 9 | public class JustArrayContext implements JustContext { 10 | 11 | private ArrayBinder indexBinder = new ArrayBinder<>(); 12 | 13 | private List commandList = new LinkedList<>(); 14 | 15 | private Map extFunc = new HashMap<>(); 16 | 17 | private Map astCache = new HashMap<>(); 18 | 19 | @Override 20 | public boolean contain(String name) { 21 | return this.indexBinder.containsKey(name); 22 | } 23 | 24 | @Override 25 | public Object remove(String key) { 26 | return indexBinder.remove(key); 27 | } 28 | 29 | @Override 30 | public Object get(String objName) { 31 | return indexBinder.get(objName); 32 | } 33 | 34 | @Override 35 | public Object put(String key, Object val) { 36 | return indexBinder.put(key, val); 37 | } 38 | 39 | @Override 40 | public Object getCache(Integer astHash) { 41 | return astCache.get(astHash); 42 | } 43 | 44 | @Override 45 | public Object putCache(Integer key, Object val) { 46 | return astCache.put(key, val); 47 | } 48 | 49 | @Override 50 | public ExtendFunctionExpr putExtendFunc(ExtendFunctionExpr expr) { 51 | return extFunc.put(expr.funcName(), expr); 52 | } 53 | 54 | @Override 55 | public ExtendFunctionExpr getExtendFunc(String name) { 56 | return extFunc.get(name); 57 | } 58 | 59 | @Override 60 | public Object command(String command) { 61 | return commandList.add(command); 62 | } 63 | 64 | @Override 65 | public Collection varsKeySet() { 66 | return indexBinder.keySet(); 67 | } 68 | 69 | @Override 70 | public List commandList() { 71 | return commandList; 72 | } 73 | 74 | @Override 75 | public List functions() { 76 | return new ArrayList<>(extFunc.keySet()); 77 | } 78 | 79 | @Override 80 | public boolean clearVars() { 81 | indexBinder.clear(); 82 | commandList.clear(); 83 | astCache.clear(); 84 | 85 | return true; 86 | } 87 | 88 | @Override 89 | public int indexOf(String key) { 90 | return indexBinder.indexOf(key); 91 | } 92 | 93 | @Override 94 | public Object getWith(int index) { 95 | return indexBinder.getWith(index); 96 | } 97 | 98 | @Override 99 | public String generateVarAssignCode(Var var) { 100 | StringBuilder builder = new StringBuilder(); 101 | 102 | String typeDeclare = Var.getTypeDeclare(var.getType()); 103 | 104 | builder.append(typeDeclare).append(" ") 105 | .append(var.getName()).append("=") 106 | .append("((").append(var.getType().getCanonicalName()).append(")") 107 | .append("context.getWith(").append(indexOf(var.getName())).append(")").append(");"); 108 | 109 | return builder.toString(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/lfkdsk/justel/compile/compiler/JustCompilerImpl.java: -------------------------------------------------------------------------------- 1 | package com.lfkdsk.justel.compile.compiler; 2 | 3 | import com.lfkdsk.justel.compile.generate.JavaSource; 4 | import com.lfkdsk.justel.compile.memory.JustMemClassLoader; 5 | import com.lfkdsk.justel.compile.memory.JustMemFileManager; 6 | import com.lfkdsk.justel.exception.CompilerException; 7 | import com.lfkdsk.justel.eval.Expression; 8 | 9 | import javax.tools.*; 10 | import java.util.Collections; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * Just Compiler Implementation 16 | * 17 | * @author liufengkai 18 | * Created by liufengkai on 2017/7/20. 19 | */ 20 | public class JustCompilerImpl implements JustCompiler { 21 | 22 | /** 23 | * Java compiler 24 | */ 25 | private final JavaCompiler compiler; 26 | 27 | /** 28 | * memory class loader 29 | */ 30 | private final JustMemClassLoader memClassLoader; 31 | 32 | /** 33 | * diagnostic report 34 | */ 35 | private final DiagnosticCollector diagnosticsReport; 36 | 37 | /** 38 | * memory manager 39 | */ 40 | private final JustMemFileManager manager; 41 | 42 | /** 43 | * class-qualified-name => Expression 44 | */ 45 | private final Map memCompilerCache; 46 | 47 | public JustCompilerImpl() { 48 | // initial compiler 49 | this.compiler = ToolProvider.getSystemJavaCompiler(); 50 | if (compiler == null) { 51 | throw new IllegalStateException("Can not bind to system java compiler"); 52 | } 53 | this.diagnosticsReport = new DiagnosticCollector<>(); 54 | this.memClassLoader = new JustMemClassLoader(this.getClass().getClassLoader()); 55 | this.manager = new JustMemFileManager(compiler.getStandardFileManager(diagnosticsReport, null, null) 56 | , memClassLoader); 57 | this.memCompilerCache = new HashMap<>(); 58 | } 59 | 60 | @Override 61 | public Expression compile(JavaSource code) { 62 | try { 63 | // found expression in cache. 64 | if (memCompilerCache.containsKey(code.getClassQualifiedName())) { 65 | return memCompilerCache.get(code.getClassQualifiedName()); 66 | } 67 | 68 | JavaFileObject javaFileObject = manager.makeStringSource(code); 69 | 70 | JavaCompiler.CompilationTask compilationTask = 71 | compiler.getTask(null, manager, diagnosticsReport, null, null, 72 | Collections.singletonList(javaFileObject)); 73 | 74 | Boolean result = compilationTask.call(); 75 | if (result == null || !result) { 76 | throw new CompilerException( 77 | "Compilation Failed! " + diagnosticsReport.getDiagnostics().toString()); 78 | } 79 | 80 | Expression expr = 81 | (Expression) loadClass(memClassLoader, code.getClassQualifiedName()).newInstance(); 82 | // add release expr to cache. 83 | memCompilerCache.put(code.getClassQualifiedName(), expr); 84 | 85 | return expr; 86 | } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) { 87 | e.printStackTrace(); 88 | throw new CompilerException(e.getMessage()); 89 | } 90 | } 91 | } 92 | --------------------------------------------------------------------------------