分享一个词法分析器源代码

分享一个词法分析器源代码我的一个开源项目 词法分析器和表达式计算引擎 https github com ndxt centit commons tree master centit compiler

大家好,欢迎来到IT知识分享网。

这个项目来自于我的大学课程编译原理的课程设计。一开始的内容只包括一个词法分析器Lexer,可以从一个字符串中读取一个词,并且判断是操作符、变量还是常量。

后来添加了加减乘除四则运算,又逐步添加了逻辑运算,内置函数和外置函数,也从做出的C++版本翻译到现在的java版本,一不小心已经维护了20多年。现在作为公司多个项目中的规则引擎来使用。

词法分析器Lexer

虽然我们可以使用正则表达式来分析字符串,但是如果我们想从一个字符串或者文本文件中一个单词一个单词的分析,词法分析器是最合适的。一个词法分析器需要对应一个词法规则,设计在词法分析器遵循java和sql的词法,两个差别主要在注释方便,构造函数中需要区分。

 public Lexer(String sFormula,int langType){ this.languageType = langType; setFormula(sFormula); }

词法分析器的核心函数是 public String getAWord( ); 它返回的内容可能是:

  • 一个标识符,变量或者内置函数。
  • 一个字符串。
  • 一个操作符。

带变量四则运算 VariableFormula

四则运行包括加减乘除、取模和与或非等等;表达式中的标识符对应的变量可以通过map传递给四则运算,也可以通过一个对象的属性传递。四则运算接口如下:

 public static Object calculate(String szExpress,Object varMap) { ................... }

变量对应的类型可以是任意类型,数字、字符串、日期、数组都可以。因为他们不仅可以传递到四则运行中还可以传递到四则运算的内置函数中。

内置函数 EmbedFunc

为了对四则运行进行扩展,引入了内置函数来丰富表达式的功能。内置函数分以下几类:

  • 数学函数;比如:取整、开平方、对数等等。
  • 字符串处理函数;查找子串、数字大写、补齐等等。
  • 统计函数;求和、计数、统计非空数量等等。
  • 日期函数;当前时间、时间的加减。
  • 条件函数(逻辑函数);if函数和case函数,不同的条件取对应的表达式结果。

测试用例

//简单的四则运算 System.out.println(VariableFormula.calculate("'25.36'*5")); System.out.println(VariableFormula.calculate(".36*5")); System.out.println(VariableFormula.calculate("tonumber('',12)")); System.out.println(VariableFormula.calculate("tonumber(,34)")); System.out.println(VariableFormula.calculate("tonumber('123')")); System.out.println(VariableFormula.calculate("round('.3236',2)")); // 测试字符串运算 // 大写转换、if条件选择、字符串连接 System.out.println(VariableFormula.calculate("strcat(capital(floor(a)),'元'," + "if(byte(a,-1)=0 and byte(a,-2)=0, '整', if(byte(a,-2)=0, strcat(capital(byte(a,-1)),'角')," + " strcat( capital(byte(a,-1)),'角',capital(byte(a,-2)),'分') ) ) )", CollectionsOpt.createHashMap("a",.01f))); // 通过map传递参数 // 模式匹配函数 System.out.println(VariableFormula.calculate( "match('a*d','aadbd')")); // 测试内置函数 -- 随机函数 System.out.println(VariableFormula.calculate("random()")); System.out.println(VariableFormula.calculate("random(100)")); System.out.println(VariableFormula.calculate("random(5, 100)")); System.out.println(VariableFormula.calculate("random('string', 38)")); System.out.println(VariableFormula.calculate("random('string', 'uuid')")); System.out.println(VariableFormula.calculate("hash('hello world')")); System.out.println(VariableFormula.calculate("hash('hello world','sha')")); System.out.println(VariableFormula.calculate("hash('hello world','macsha','nihao')")); // 测试 数据传输,可以通过map 可以直接通过普通pojo对象(系统通过反射获取对应的属性) Map<String, Object> varMap = new HashMap<>(); Map<String, Object> varA = new HashMap<>(); varA.put("aa", new Integer[]{100, 200, 300}); varA.put("ab", 200); Map<String, Object> varB = new HashMap<>(); varB.put("ba", 300); varB.put("bb", 400); varMap.put("a", varA); varMap.put("depart", "你好"); varMap.put("c", null); varMap.put("ideaCode", "T"); System.out.println(f.calculate("a.aa[1]+a.aa[2]")); // 测试自定义函数 拓展 ex 和 pi 为自定义函数 VariableFormula formula = new VariableFormula(); formula.addExtendFunc("ex", (a) -> NumberBaseOpt.castObjectToInteger(a[0]) * NumberBaseOpt.castObjectToInteger(a[0])); formula.addExtendFunc("pi", (a) -> 3.14159); Object r = formula.calcFormula("ex(4) + pi()"); System.out.println(r);

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/97343.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信