为什么 antlr 用于模板引擎不是个好主意

原创
2019/12/23 02:05
阅读数 1.2W

    我在发布 jfinal 3.0 的时候认为 antlr 用于 "模板引擎" 并不是个好主意,两年多时间过去了,我的观点更进一步:认为 antlr 在多数 “非模板引擎” 的场景下使用也不是个好主意。

    在发布 jfinal 3.0 的时候谈到 antlr,只言片语信息量太少,引起了部分人的误解,今天就来稍稍展开聊一聊。

一、antlr 生成 Parser 难于调试、难于阅读

    首先现场直观来感受一下 jfinal 手写 Parser 与使用 antlr 生成的 parser 的对比,下面是为 jfinal enjoy 模板引擎手写的 parser:

https://gitee.com/jfinal/jfinal/blob/master/src/main/java/com/jfinal/template/stat/Parser.java

    空行 + 注释 + java 代码一共 278 行,干净利落,人类轻松阅读。更重要的是其用到的 Recursive Descent 算法简洁可靠,功能强大,随手可得。熟悉这个算法原理的同学几个小时就可以手撸一个自己的 Parser 出来。

    再来看一下 antlr 为模板引擎生成的 parse:

https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.java

    空行 + 注释 + java 代码一共 4164 行,这里一定要注意看第 3923 行的 String _serializedATN 变量,这个是其 parser 运行时所依靠的核心,人类完全无法阅读,也根本无法调试。

   这还不算完,生成这个 parser 需要先学习 antlr 的语法定义规则,然后写一个语法定义规则文件,该规则文件描述语法结构:

https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.g4

   要熟练掌握以上这套规则和语法描述,并精准无误地用于具体项目并不容易,学习成本比使用现成的 Recursive Descent 算法做的 Parser要高得多,而且生成出来的东西不可阅读、无法调试。

   那么到这里总该完事了吧?仍然没有,词法分析 lexer 还要再搞一次上面这一类的事情,学习成本再提升一倍:
https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlLexer.g4
https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlLexer.java
  
   特别注意看一下 BeetlLexer.java 第 156 行定义的 String _serializedATN 变量,用 antlr 生成的 lexer 同样是不可读,不可调试的。
 

     那么请问,整完 lexer 这套东西,总该完了吧?还是没有。几套规则定义文件外加两个生成的 java 文件还是跑不起来,必须要引入一个 329KB 的运行时依赖:antlr4-runtime.jar。

     就 parser 这点破事,引入一个 329KB 体量 runtime。要知道 jfinal 用这么大体量连 AOP + ORM + template engine 的事全干完了。我真不知道这个 jar 包里面在做什么?

    上述这些事,在 jfinal enjoy 模板引擎里头手撸一个 parser、lexer 完事了,现成的、成熟的算法拿来即用,parser、lexer 的原理、作用、写法在大学本科阶段是必学的,有些学校还会为此作为一个课程设计的作业。

   当你花时间学习 antlr 这套规则的时候,我早就手工撸完 parser 了。

   这里要说明一下 jfinal enjoy 独创的 DLRD 算法。jfinal enjoy 的 parser 是针对模板文件的特征,基于传统 Recursive Descent Parser 做了改进,做成了 Double Layer Recursive Descent 算法,将指令级的 parser 与表达式级的 parser 划分在两个独立的层次,属于独创。每一层与传统的 Recursive Descent 算法原理类似,对左递归、二义性等问题的处理有所改进。

    即便其他人没有 jfinal enjoy 的算法创新,仅仅使用传统的 Recursive Descent Parser,我前面的表述依然成立。

    罗总很严谨,这段的标题我用了“难于调试”、“难于阅读”,是为了不排除少数天才有这个能力,但对于绝大部分人类来说是不可调试、不可阅读的。

二、antlr 生成的 parser 对变化响应慢

  当你用 antlr 做出来的东西在语法、词法层面需要加点东西或者改点东西的时候,过程如下:
1: 修改语法、词法涉及的规则 .g4 描述文件
2: 运行 antlr 的生成器,重新生成 Parser、Lexer
3: 开始写自己的代码
    首先,注意上面的工作流程,其中前两步都是在用特定规则的描述语言在表示语法、词法,然后 antlr 将其转化成不可读、不可调试的 parser 代码。

    如果用于语法、词法的两个 .g4 规则描述文件写得有 bug,那么生成出来的 parser 就是错误的,你很难从生成的 parser 再回头去找规则描述文件中的错误和原因,因为描述文件是不能被调试的,它不是 java 代码,根本不能运行。

    其次,上面这个工作流程表明,在对词法、语法进行迭代的过程中,你要首先干很多别的事情,然后才可以开始真正写代码,这个重复、麻烦且容易出错的过程会阻碍了模板引擎的改进。

     jfinal enjoy 在迭代的过程中就改过语法,例如后来添加的 #switch 指令,enjoy 不使用 antlr 方案,基本上只需要在 Parser 中添加一个 case 分支就完事了:
   https://gitee.com/jfinal/jfinal/blob/master/src/main/java/com/jfinal/template/stat/Parser.java

    注意看第 218 行代码,根本就不需要学习、折腾 antlr 方案下的那一套东西。
  

三、至于那些用了 antlr 的项目

    首先我并不认为某些比较知名的项目用了 antlr 就证明它是个好方案,我个人的思维习惯之一就是普遍怀疑,哪怕你是权威。只有这样才有可能站在前人的肩膀上做得更好,走得更远。

   其次,antlr 被人们使用,我认为出于如下几个原因:

1: 非计算机专业的人,需要定制一个 DSL

2: 计算机专业,但大学基础没学好,不知道有现成的 parser 算法、源码可用

3: 盲目跟风的人。早期的几个知名模板引擎都用的 ANTLR、jflex、javacc 这一类,后来者跟风模仿

  主流的程序语言,如 java、C#、C++ 都是手写 parser,不可能去用 antlr 这种东西,综上所有信息量,我认为 antlr 在多数 “非模板引擎” 的场景下使用也不是个好主意。

 

    罗总在博客中谈到 “Parser, 根本就不是拿来给人读的, 也不是用来让人直接"细致打磨" 这个我完全不赞同。

   jfinal enjoy 多次新增、改进过语法,例如新增 #switch、#case 指令,再例如修正过空合并安全操作符与其它操作符混合使用时的 bug,这种情况下不可读、不可调试是绝对不行的。 

   如果 antlr 生成的 parser 出现上述类似的 bug,你无法通过调试的办法找到原因,只能硬着头皮去看那几个用文本文件书写的描述规则,该描述文件不能运行、更不能调试。

    java、C++ 这种语言为啥要自己写 parser 不使用 antlr? 新增、修改语法、处理 bug 都必须要可读、可调试

四、回到 jfinal 3.0 发布时新闻中的部分观点

    有了前面的信息量,再回看两年前我发布 jfinal 3.0 时谈到的 antlr 所用的一些词以及观点。我相信 antlr 是可靠、稳固的,但我不相信使用者制定的那套描述文件也是可靠稳固的。进而不相信生成的 parser 代码是可靠的,“飘摇不安” 就指向这里。

   antlr 那套语法描述规则并不比现成的 parser 算法容易,如果你能精准用好那套规则,早就更能用好现成的 parser 源码了,根本用不着 antlr。

 

 

展开阅读全文
打赏
8
2 收藏
分享
加载中
给波总提个小意见, 这篇博文有点文不对题, 因为波总的立论现在已经从 ANTLR 不适合模板引擎开发扩展到了 ANTLR 也不适合非模板引擎开发, 所以应该换成类似 "为什么用 ANTLR 不是个好主意" 这样的标题才符合博文内容.
2019/12/24 04:21
举报
JFinal博主
任何人的认知都是有局限性的,在我的认知之外必然会有使用 antlr 的优秀场景,所以罗总注意我博客第一句话中用的是 "多数" 这个词来做限定,我并没有使用 "所有" 来限定。 恰好我自己做过模板引擎,所以在 antlr 是否适合用于模板引擎这个认知上比一般人可能要高,这个标题是更恰当的选择。
2019/12/24 11:26
举报
一、antlr 生成 Parser 难于调试、难于阅读 antlr本来就是用g4语法定义的,生成的parser本来就是自动生成的,难于调试,这个g4写好了,啥问题也没有,出了打个断点,调试难度并不大,难于阅读,这个也还好说,我个人觉得生成的parser其实自己也是根据算法写,但是人家既然给你自动生成了,那不是省事吗,我觉得阅读难度也没多大呀, 难于调试,难于阅读对我来说都不成立,相反都是根据算法生成的,代码还是基本有可读性
二、antlr 生成的 parser 对变化响应慢 这个有啥慢的,命令行敲一下就好,修改一下g4,其余都是自动生成的,这个怎么就慢了,"修改语法、词法涉及的 .tokens、.interp 文件"这些都是自动生成的好不好?你除了开发时期需要经常改g4,后期都是小改动,没问题呀,不知道你说的慢到底是什么慢
2019/12/23 13:00
举报
JFinal博主
我前面强调了你仔细看我的正文,BeetlParser.java 第 3923 行的 String _serializedATN 变量,你去给我调试一下看看。下面这个描述文件,你给我调试一下看看: https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.g4 我在后面小节中说的对应化响应慢,你看完再评论不迟
2019/12/23 13:06
举报
使用antlr,使用的就是g4,你为啥揪着自动生成的东西不放,那个是ATN相关的东西,自己算出来的,还有专门的ATN标,这个我没深入过,但是antlr的使用,基本就是用G4,自动生成的东西也最好不要改,你揪着这个自动生成的东西,说一大堆不好,你为啥不说说,使用g4定义的方便,而且后期也方便维护呢?
2019/12/23 13:09
举报
JFinal博主
该评论暂时无法显示,详情咨询 QQ 群:912889742
作为一个对质量有要求的软件,自动生成的如果有BUG,调试的责任也是软件作者,而不是ANTLR作者。 就像如果你用了Spring Boot带出来的一大堆组件,做一个系统,出了BUG难道让Spring Boot开发者去给你调BUG? JFinal这个决策没问题,你通篇考虑下就清楚了,几百行无额外依赖的代码,对应依赖十几万代码的ANTLR,哪个从可维护性来说更加合适? 除非ANTLR能生成可读性极佳的代码,就像某些CRUD代码生成器一样,生成完一遍就可以直接抛弃生成器去改代码,不然在工程的角度,开发者就要连带上这十几万行的ANTLR的质量的责任。 你提到 Java 那些复杂的语法,开发者更是要回避用ANTLR去做,如果ANTLR的BUG,比自己写的Parser更难调试。 ANTLR这类工具更多是给两类场景用的,一是方案验证,二是离线编译器,这两者都追求尽快出效果,而对Parser的性能没和质量没有太高的要求。
2019/12/23 13:49
举报
那你如何看groovy3的新写的Parrot Parser用antlr来写?
2019/12/23 13:54
举报
你如何看待,Python/Java/C++/Chrome/Firefox/TypeScript/C# 全部都自己实现的Parser?
2019/12/23 13:56
举报
我举的是反例,你举的是正例,你应该明白区别吧.这就好比你说mx=my是恒定的,你告诉我m等于1,2,3等等都行,但是我告诉你m=0的时候不行
2019/12/23 14:01
举报
我没说不能,只是说哪个更合适,至少如果我是Groovy的开发者,采用ANTLR我会投反对票
2019/12/23 14:08
举报
JFinal博主
回复 @乌龟壳 : Groovy 想成为一门主流、严肃的程序语言,就不该碰 antlr 这种东西
2019/12/24 19:58
举报
回复 @JFinal : 我star两星都不配和你说话,那你jfinal全世界都在用的时候,再来评头论足groovy吧
2019/12/25 09:13
举报
JFinal博主
回复 @李嘉图 : 我确实看不上你做的东西,根本就是无人问津:https://gitee.com/david0624 你不配跟我在这里争论模板引擎该不该用 antlr ,你没有做过模板引擎,而我做过: https://gitee.com/jfinal/enjoy
2019/12/25 10:40
举报
你看你现在就很能扯,我已经说了不配和你说话,你一再强调,但是我告诉你,你配评论groovy,你就当作没看到,你的讨论技巧很丰富吗
2019/12/25 11:04
举报
JFinal博主
回复 @李嘉图 : 你拿不出一点像样的东西,无法体现你的水平,我不跟没水平的人扯七扯八。这就是你写的代码,根本没人理:https://gitee.com/david0624
2019/12/25 12:12
举报
我就引一篇王垠的文章吧,我赞同里面的观点:http://www.yinwang.org/blog-cn/2015/09/19/parser
2019/12/23 13:59
举报
antlr 是dsl,你先搞清楚什么是DSL再说。
2019/12/23 16:20
举报
这种概念性的东西提出来不知道有什么讨论的价值?DSL实体也是那十几万行代码。
2019/12/23 16:53
举报
在工程的角度,就是需要被纳入质量管理的范围,因为如果它出了问题负责人也是自己。如果说它生成代码能比较方便手工改造,类似为CRUD做的那些代码生成器,我认为用ANTLR对质量没有负面作用。但事实上ANTLR生成的代码很难做到手工去改,改点东西就要重新依赖ANTLR,这样就事实上带上了我刚说的那十万行的质量管理负担。
2019/12/23 17:03
举报
就不谈复杂的吧,就说简单的,enjoy就像你说的,简单,事实上jfinal也展示了,他写的Parser也不会比g4多多少行,这种场景,已经很容易取舍了,自己写Parser更优。但是并不是说ANTLR是垃圾什么的,可能他的措辞带有了地图炮的性质。不过说句题外话,我也觉得类似Beetl,让我选择,也是在更适合手写Parser的范畴。
2019/12/23 17:15
举报
你写java,难道不用jdk,jdk不也是几百万行的代码,你运行java程序,难道不需要操作系统,操作系统不需要几千万行的代码?
2019/12/23 13:57
举报
不用jdk你的代码量可能从几万行飙升到几十万行。而JFinal不用ANTLR代码量并没比ANTLR配置多多少,这就是最关键点区别,不是说ANTLR有多差,而是两者权衡哪个方案更优。比如如果让我设计语法,我肯定先用ANTLR去做方案验证,吭哧吭哧写一个月的Parser,ANTLR几小时就出来了
2019/12/23 14:02
举报
看了我的回复没有,还搞不清楚antlr的优势,一个自己写了个非常简单语法解析的enjoy,就开始说antlr不行,非常搞笑。
2019/12/23 16:23
举报
我不是JFinal,我只是支持大部分追求极致优化性能和追求Parser质量的场景,不适宜ANTLR(例如JFinal的模板引擎),但如果要说产出Parser的速度,类似ANTLR这种工具肯定比从头手写要快不少。
2019/12/23 16:57
举报
回复 @乌龟壳 : 你测测beetl和jfinal的benchmakr,看看jfinal自己能手写parser,比beetl快了多少,测测看看,
2019/12/23 18:21
举报
回复 @乌龟壳 : 无论是手写还是使用antlr,本质上都是根据语法解析的方法来做,也就是算法一样,一个是手写,一个是自动生成,两者的差距到底能有多大,为啥手写一定就比自动生成快很多,自动生成的为啥就是不适合高性能场景,这些你测测beetl和enjoy的benmark看看,就明白了 https://gitee.com/xiandafu/template-benchmark
2019/12/23 18:26
举报
回复 @李嘉图 : 语法不同,机制不同怎么比较,如果是整体性的benchmark,JFinal已经在另一篇帖子里让熟悉Beetl的人去提PR了,他自己说他内部测过,enjoy比beetl快。这事情我就懒得做了。只是从逻辑来说,假如ANTLR生成的代码比手写的快,那把手写的哪里低效的改快点就行了,这个和我所谈的主要观点工程质量无关。
2019/12/23 18:32
举报
回复 @乌龟壳 : 他测过,比beetl快,你就信了,可以,我无话可说
2019/12/23 18:38
举报
回复 @李嘉图 : 另外,我主要的观点在于那十几万行vs几百行的维护包袱的问题。性能还是其次的。如果真要写极致高性能 Parser,优化的方向多了去了,多线程、SIMD、JNI、CPU算法本身,一大堆东西。如果要是ANTLR生成,就很难介入这些优化,但手写的话,要做这些优化就比较自由。另外我还是比较喜欢模板引擎离线编译,线上运行的代码是不带模板编译器的,线上不需要动态编译,这时候Parser的性能更不重要了,重要的是编译后的代码运行是否高效。
2019/12/23 18:40
举报
回复 @乌龟壳 : antlr生成语法文件的时候,就是用的默认的模板,换句话说,antlr的功能非常强大,生成parser的时候,可以实现代码上的优化的,并不是完全不可控的
2019/12/23 19:25
举报
回复 @李嘉图 : 好累,我并不想证明ANTLR不强大,而是手写并不会太复杂,如果在工程的角度,为了极致优化和可维护性,我倾向于Parser手写。还是那句话,引入ANTLR在需要打磨的产品上,不值得,省下的写Parser的时间,相比于其十几万行代码量的逻辑的引入,两相权衡我觉得手写更合适。但是并不是说所有场景都不适用ANTLR,也不是说它是垃圾。
2019/12/23 19:31
举报
回复 @乌龟壳 : 恩恩,我现在明白你的意思了,不过我觉得用antlr没啥问题,自己写parser,和手写parser其实差别不大,背后的算法其实都差不多,能用模板生成的东西,其实都是体力活,没必要浪费时间,极致优化的话,用不用antlr我觉得区别不大(不否认有区别),可维护性吧,g4照样很好维护,你喜欢手写没错,那是个人喜好.至于引入antlr,我没代码引入的洁癖,毕竟,使用jdk几百万行代码,运行java程序,需要操作系统,更是上千万行代码,所以,如果要是有洁癖的话,可能自己要裸系统运行代码了.
2019/12/23 21:47
举报
回复 @李嘉图 : 真的好累,我想表达的最核心的地方是,手写几百上千行的parser,相对于几十上百行的g4,但是引入十几万行代码的ANTLR,在架构上,工程上,不值得,不是代码洁癖,不是追求一开始省事,而是长期省事。前面已经回复过你jdk的问题了。
2019/12/23 23:16
举报
真会扣帽子,作者说砍柴不适合用短刀,就是在说短刀本身有问题?你是故意扣帽子呢还是说智商只能理解到这个地步呢?
2019/12/24 14:15
举报
1: 非计算机专业的人 (不是计算机专业还用编码吗)😃

2: 计算机专业,但大学基础没学好,不知道有现成的 parser 算法、源码可用(你大学学得东西现在还记得清吗)😃


3: 盲目跟风的人。早期的几个知名模板引擎都用的 ANTLR、jflex、javacc 这一类,后来者跟风模仿 (跟风,这个没法说)😃
2019/12/23 12:51
举报
JFinal博主
你好好看正文,里面很多信息量我认为你没看到,对比一下使用现成的 Recursive Descent 的 parser : https://gitee.com/jfinal/jfinal/blob/master/src/main/java/com/jfinal/template/stat/Parser.java 。 与用 antlr 生成的 parser: https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.java。 你公正地说一说哪个简单好用,哪个可以调试、阅读
2019/12/23 12:55
举报
你要这样比,当然自己写的,肯定有优势,但是antlr生成的,我不觉得难于调试和阅读,一般还好了,没那么严重,上升到难得概念,我用过,就前期遇到几个问题,后来都是习惯了,不会出大问题
2019/12/23 13:03
举报
明显需要比的是beetl的语法文件(https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.g4)和你的Parser.java,BeetlParser是生成文件,包含了语法解析和一些元信息,确实不容易阅读,但作为Betetl作者,我根本没有维护过,我只维护语法文件就行了 哪个更容易维护,更容易扩展呢。 补充一下,Beetl的语法远远比你的enjoy模板语法复杂。如果咱们俩交换一下,我用antlr写你的enjoy,你自己手写beetl语法解析,那咱么谁做的更好?
2019/12/23 13:18
举报
对呀,自己手写ast,简单的语法还行,复杂的语法,就是antlr生成的parser都很巨大,你自己手写,工作量呢?比如json,语法定义非常简单,轻松写个解析器有啥难度,但是java的语法,你自己手写个解析器,试试,看看工作量有多大
2019/12/23 13:26
举报
JFinal博主
语法复杂情况使用 Recursive Descent 算法时复杂度并不提升多少,这个算法是很机械化的,一层一层往下递归就可以了,这个复杂度还不如你的语法定义文件。我这里是要比较 parser,我不可能将我的 parser 与你的语法描述文件相比较,这两个是不同的东西,比较的前提是同类型。 谈到语法,jfinal enjoy 模板引擎注意是"模板引擎",不是脚本语言,模板引擎搞出一套复杂语法是相当愚蠢的事情,否则人家直接用其它更通用的脚本语言就好了,何必用模板引擎
2019/12/23 14:32
举报
一个简单例子,为什么html里大家都需要用html标签语法,这点beetl能做到,jsp能做到,freemaker能做到,甚至thymleaf能做到,enjoy做不到,在enjoy中出现”#end“有很大的违和感。模板引擎尊重模板,才是是模板引擎第一设计原则,你的enjoy 差的太远了,完成简单功能就在嘚瑟极简,又嘚瑟代码量少,是enjoy愚蠢还是beetl愚蠢,不言而喻
2019/12/23 16:28
举报
JFinal博主
我在这里跟你仔细讨论 antlr,你扯东扯西,避重就轻,现在又开始转移话题扯上 enjoy 的语法风格。为什么你就不肯直面 antlr 的问题呢? 我现在严重怀疑你是不是计算机专业的,根本就没学过编译原理,否则你会很清楚有现成的 parser 可用,并不需要折腾 antlr。
2019/12/23 17:54
举报
回复 @JFinal : 是你在扯东扯西,避重就轻吧?如果你说对的对,为啥有antlr,还有那么多给国内外有名软件在用,扯你语法风格,就是因为你的enjoy足够简单,所以坐进观天了而已。你不需要折腾,但不代表antlr不行,你的几篇博客里都说道antlr不行,难调试,今天我告诉你有调试工具,是不是有打脸的感觉。无知者无畏,但不要秀出来,贻笑大方
2019/12/23 18:25
举报
JFinal博主
回复 @闲大赋 : 我可是一直在提醒你回到 antlr 这个主题,你看看你回复中扯了多少别的事? 还给人乱扣帽子,很明显被我说中要害以后,乱了阵脚,我前面不点出这点是给你留点面子,但你要是一直东拉西扯,我就点一点你
2019/12/23 18:49
举报
回复 @JFinal : 一、antlr 生成 Parser 难于调试、难于阅读 ,我已经多次告诉你了antlr的调试方法,你还不会?你点出啥东西了需要给我留面子,我倒觉得我一直给你留面子让你的jfinal成长。是我扯还是你扯。你还不正面回到,你这个结论到底是对还是错呢,你居然要去pk 工具antlr生成的parser代码,好搞笑,瞎子摸象的感觉
2019/12/24 10:20
举报
JFinal博主
回复 @闲大赋 : 我前面已经重复两次了,你倒是去调试那个 .g4 文件看看,调试生成的那个 BeetlParser.java 看看,你得给出证明,不能随口说一句就自以为是真的。 你前面说让我找出 .g4 的 bug 来证明我的观点,我现在找出来一只 beetl 中 .g4 文件的 try cath 语法的 bug: https://github.com/javamonkey/beetl2.0/commit/7dbdc83e7b56b22f20fbdda52a2f731f95652760。 现在轮到你来证明 .g4 文件可以调试了,来吧
2019/12/24 11:35
举报
回复 @JFinal : g4文件在编写过程中,肯定要反复调试,怎么能上升到antlr问题。莫非写java程序出bug,能上升到Java语言问题。另外,怎么叫轮到我来证明g4可以调试,这个antlr官网就有,下载一个antlrworks,就能搞定。你难道看不懂英文文档了,图总能看懂吧
2019/12/24 11:54
举报
JFinal博主
回复 @闲大赋 : 别转移话题,我没上升到什么antlr的问题,别胡扯。你要的 bug 证明我已经给出来了,现在轮到你来证明 BeetlParser.g4 与 BeetlParser.java 的调试了,别墨迹
2019/12/24 12:00
举报
再告诉你一个antlr功能,他有语法文件debuger,可以运行时候调试语法文件,非常方便编写和调试语法文件,要不然那么多应用领域选择用antlr。不要井底之蛙了
2019/12/23 08:55
举报
JFinal博主
该评论暂时无法显示,详情咨询 QQ 群:912889742
既然antlr作者提供了语法文件调试和相关IDE,必然有用处,我也用它调试过·beetl语法文件,非常好用,跟代码调试差不多。我就知道你嘴硬...... 在判断一个东西,尤其是流行东西之前,先掌握好了再评判,免得让别人笑话。
2019/12/23 12:38
举报
JFinal博主
能不能调试暂且放一放,我在博客里已经十分明确了很多信息,使用现成的 parser 比去学习 antlr 描述规则生成 parser 成本要低得多,要方便得多,最后出来的 parser 简法好用得多,还可以调试。 我想请问你,为啥你非得要用 antlr 呢? 你不要仅仅只告诉我,因为 antlr 牛逼,并且有几个前人的模板引擎也用了
2019/12/23 12:52
举报
不是我不放,是你一开始就说不可调试,我只好反驳你。另外,你还是不懂,可维护性更重要,这点我不说你jfinal框架早期和现在缺少非常多维护性特点。就说antlr本身,语法经常变动,Java,C++都这样爱变动,更多的DSL语言更是经常变化,antlr非常方便适合语法变动。beetl模板语法 变动很多,但我从来不担心语法解析那块会因为手写parser出现不兼容。 而手写,也许就只有你能改动语法,其他人改不了了,调试语法,你的很难把java的断点对应到模板断点。antlr可以。 最后,antlr语法文件可以方便的完成错误提示,比如”xx错误,期望是什么“,非常方便模维护。 antlr能根据语法文件帮你完成语法修补。 如果你看了antlr做的书,你就应该能知道一个好的解析器应该有什么样的功能
2019/12/23 13:06
举报
JFinal博主
这是个价值观的问题,我在这个方向所持有价值观是:消灭问题比解决问题更高明。我不使用 antlr 就无需面对 antlr 的所有问题,无需学习它,无需买它的书。我使用现成的 Recursive Descent 算法节省大量时间,新增语法很方便。你扯的所有 antlr 的事情,在我这里不并存
2019/12/23 13:12
举报
回复 @JFinal : 消灭一个问题(使用antlr),带来了隐藏的问题(假如有天语法变动大了呢,维护怎么办,当然这是个假如)
2019/12/23 15:59
举报
JFinal博主
回复 @李嘉图 : 我在博客正文中已经举过例子了,enjoy 添加新语法新增 #switch 指令,基本只需要添加一个 case 分支,比你用 antrl 那套要好维多了,修改 bug 也类似很方便,因为 enjoy 的 parser 可以调试。你到现在还是没看博客内容
2019/12/23 17:56
举报
是在搞笑吗?如果字节码不容易阅读,就否定Java语言。你贴出了antle生成的文件,你为何不贴出beetl的语法文件?还有竟然说非计算机专业才用antlr~你怎么不上天呢,你的所有技术都有一个毛病,忽略了软件维护性,以前从可维护性批评过你的框架(一个map走天下),你虽然没有表示同意,但你却按照我想发加上了。antlr也是这个道理,语法调整,只需要简单调整语法描述文件就行了。况且,antlr本来目标就是dsl,计算机专业有人用,非计算机专业有人用,这才是它强大地方,不知道你有什么资格贬低,你先搞懂先
2019/12/23 08:48
举报
JFinal博主
你将 java 字节码的可读性与 antlr 语法、词法描述文件、与生成的 parser、lexer 不可读进行类比,是非常牵强和不恰当的。 首先,阅读、调试 Java 字节码这种事是做 JVM 这帮人更该干的事,你在写 java 程序的时候几乎用不着。 这就好比你写了一个 C/C++ 程序,你用不着去阅读、调试其生成的本地机器码。软件领域是分层协作的,不同层的人干不同的事, 最底层做芯片的要面对 CPU 指令集,这个层面对于你写 java 的人来说根本用不着。 其次,java 字节码是为了跨平台、提升性能等等目标,而 antlr 的描述文件是为了生成 parser,而 parser 是为了建立 AST,目标完全不同。 最后,你用描述文件生成的 parser 是可能出 bug 的,出了 bug 你需要源码可阅读、可调试,这是现实需要。 综上,你的类比完全不恰当
2019/12/23 12:22
举报
描述文件生成的 parser 可能出 bug?你举出一个世实际例子放到gitee上吧,这样更有说服性,我怎么倒觉得你是玩不转antlr,这只是一个简单工具而已。 另外,你也知道软件分层协作,那何必诋毁antlr呢
2019/12/23 12:56
举报
JFinal博主
你写 java 代码超过 10 年了吧? 现在你写 java 代码是不是也偶尔有 bug ? 如果一个写了 10 多年 java 的人仍然可能写出 bug,那么对 antlr 描述规则文件的使用出 bug 这不是再自然而然的事情吗? 对那个描述规则文件的使用,并不会比你写 java 代码要简单,你要知道那个描述文件是在描述类似于程序语言的语法规则,语法规则这种东西是很灵活很复杂的,你能保证没 bug? 你仔细看看我对分层的表述,是在说明你的类比论述是不恰当的,何来诋毁 antlr 这一说?你不要没道理就去给我头上安插一些莫须有的标签,别人会看你笑话的。注意摆事实,讲逻辑
2019/12/23 13:03
举报
你没有诋毁antlr?刚才还说难以调试,你不知道antlr有调试工具,能直接把语法文件和输出的语言对应上,非常高级。反而是手写,需要足够的信息才能对应上。 我才是那个讲事实摆道理的人,我要求你找一个你说的bug出来放到gitee上,你却没有
2019/12/23 13:10
举报
JFinal博主
我表达自己的观点这就叫诋毁? 你对诋毁的定义是什么? 我没时间帮你的描述文件找 bug,我在前面已经表述过描述文件出 bug 的逻辑是自然而然的,你到底看到没有? 能发这个博文来澄清 antlr ,你都没仔细看,我可不愿没事找事
2019/12/23 13:16
举报
回复 @JFinal : 你说antlr难以调试,我已经纠正你了。你在无凭无据的情况下又说有bug,这些都还不叫诋毁嘛,你可不用antlr,但你说这些难道不需要负责嘛,如果你私下跟我说我会跟你讨论,但你发了一个新闻,说出来,那我只好好认为是诋毁
2019/12/23 13:22
举报
JFinal博主
我说逻辑、讲思路,讲了出 bug 的可能性。你让我找 antlr 描述文件中的 bug 出来,这个东东不能调试,你来找找看? 这就是你认为的诋毁? 请勿滥用这个词。我前面说了 antlr 生成的 parser 难以调试,描述文件不能运行,更不能调试,我怀疑你所谓的调试只是个状态显示,你到底看没看我的回复? 看了回复你就不可能说出“纠正我”这样的话来。
2019/12/23 14:40
举报
回复 @JFinal : 做技术的要实事求是,你既然说有可能有bug,那就列举一个,要不然,没有空口胡说是你的特点嘛,我看像 调试只是个状态显示。。。你完全没有看我的回复,我很清晰告诉你了,调试能有什么功能,还要我教你俩遍嘛。
2019/12/23 16:36
举报
JFinal博主
我在前面已经说过了,调试可以实时看变量、可以改变量值、可以设置断点,可以单步前进等等,用不着你教。 我说你用的 antlr 的语法描述文件做不到这么去调试,你装着看不懂,装着看不见?
2019/12/23 17:59
举报
回复 @JFinal : 当然可以断掉和单步前进,是不是有被打脸的感觉,我怀疑你都没有了解antlr就下了个可笑的结论,我建议你看看antlr文档再说,是你埋在沙子里不想知道?
2019/12/23 18:28
举报
JFinal博主
回复 @闲大赋 : 打啥脸? 光凭你一张嘴胡说去打人家脸? 你给我调试一下 BeetlParser 中 String _serializedATN 变量,https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.java。 再调试一下 BeetlParser.g4 这个描述文件: https://gitee.com/xiandafu/beetl/blob/master/src/main/java/org/beetl/core/parser/BeetlParser.g4。你证明你能调试以后再打人家脸不迟,光凭你一张嘴胡说只能打你自己的脸
2019/12/23 18:52
举报
回复 @JFinal : 你的智商也有问题了?我都告诉你了,你要比较,那就比较语法文件调试,就好比,你说php好维护,因为比java生成的字节码更容易阅读一样。不要太搞笑了,瞎子摸象,摸错了地方
2019/12/24 10:23
举报
JFinal博主
回复 @闲大赋 : 回复 @闲大赋 : 注意我的观点是 .g4 文件是文本文件,如果这个文件有 bug , 生成出来的 parser 也一定有 bug, 但生成的这个 parser 无法调试,.g4 文件不能运行(更不能调试)。所以 .g4 文件出 bug ,你无法通过像手写 parser 并调试的方式去解决。我已经为你的 beetl .g4 文件抓出一个 bug 来了,你还想嘴硬: https://github.com/javamonkey/beetl2.0/commit/7dbdc83e7b56b22f20fbdda52a2f731f95652760。 现在轮到你来证明 .g4 文件可以调试了,来吧
2019/12/24 11:38
举报
JFinal博主
我从没说过描述文件生成的 parser 可能出 bug,我是在说描述文件 .g4 本身可能出 bug,你自己根本没仔细看我的博客。从 beetl 的 commit 记录就能找到 .g4 文件的 bug,现在看你还怎么嘴硬: https://github.com/javamonkey/beetl2.0/commit/91575de9575b106b8ca17e93ca8b1cf7f17887b0 。 提交记录中的 bug fix 可是你自己写的
2019/12/24 01:01
举报
该评论暂时无法显示,详情咨询 QQ 群:912889742
JFinal博主
你自己写的代码,你自己以往开发 beetl 时找到的 bug ,我已经给你拧出来了,你还让我给你具体指明地方,你还能再搞笑点吗? 你自己不敢面对,让其他人来看看这个 commit 中 .g4 文件中修复 bug 改动的地方,你尽可以闭上眼睛说自己看不到
2019/12/24 12:04
举报
JFinal博主
这里再来一只 beetl 的 .g4 文件有关 try catch 的 bug : https://github.com/javamonkey/beetl2.0/commit/7dbdc83e7b56b22f20fbdda52a2f731f95652760
2019/12/24 12:05
举报
JFinal博主
为了防止你删除 git 库,我已经 fork 了一份,永久保留你这些 .g4 文件出的 bug
2019/12/24 12:06
举报
JFinal博主
此外,我好心抽出时间说说 antlr 的事,这事让你追着 jfinal 不放两年多了。你为何现在又非常急于发散到别的事情上去呢?是不是又要故意回避 antlr 这件事了。 我在博文中清楚地对比了手写 parser 与用 antlr 生成这两种方式,一眼就能看出来手写 parser 更划算。 学习成本更低。难道你在大学本科没学过编译原理? 这门课开篇就是 lexer、parser,还有上机练习、课程设计。如果你学过编译原理,没有理由不知道使用现成的 Recursive Descent 算法做 beetl 要省太多事情了
2019/12/23 12:24
举报
我追你JFinal俩年不放?你在搞笑吧,是你找Beetl麻烦而已,我一直有限度反击。Antlr一来就是面向DSL的,特定领域的,所以模板,脚本,规则都合适,antlr官网有几乎所有流行语言&SQL的parser,这有几个人能做到,方便了太多的人。 我还是不懂你说的省事太多是什么意思,用antlr就很省事,语法变动只需要修改语法文件就行,比如beetl2曾经的一个语法是在注释里可以再次包含beetl脚本的一个语法子集,我很容易写出来,Beetl3 取消了这个功能,仅仅简单取消语法文件。维护性非常方便。 Java语法从JDK7后,Jdk8变化都很大。用语法文件描述很容易做出新的paser。 我还是对你的那句话,从你”一个Map走天下“言论,就知道你是个井底之蛙,只看到软件的一面。这也是你的jfinal为什么很多人瞧不上的原因。 另外居然把计算专业必学的编译原理也拿出来嘚瑟,不怕被人笑话吗
2019/12/23 12:46
举报
JFinal博主
关于追着 jfinal 捣乱两年的事,一点儿也没冤枉你,这里是前几天 jfinal 4.8 发布时你参与的龌龊事,你们 beetl 内的小伙伴还道过歉了: https://gitee.com/gavink/SFinal 这事 @罗格林 可以作证,况且罗总也参与了,事后并表达了歉意。人家罗总比你正直多了
2019/12/23 14:08
举报
我记得很清楚,是jfinal捣乱beetl先,每次发个文章,非要拉上beetl和beetlsql说事情。我虽然认枪打出头鸟,但我也希望不要胡乱说话,比如关于antlr,非常搞笑,显得民科。罗总的话我看了,道歉的是他的语气,但并不是他说的内容,他批评你的Markting内容,他没有道歉,我也很赞成,希望你能虚心接受他的批评。
2019/12/23 16:42
举报
JFinal博主
你太能臆想了,我发文章对 beetl 半个字都没提到过,你又开始扯东扯西。 你在这里贴出我在 jfinal 新版本中发新闻时提过你 beetl 半个字的 url 出来,证明你不是在臆想,这个事一点不难吧?你说我发文拉上 beetl , 你要有证据,被迫害妄想症别再犯
2019/12/23 18:56
举报
回复 @JFinal : 还没有提?你新闻里的”翻页标签“,请问dao工具哪个有这个术语,你含沙射影,自以为小聪明,结果我发现不仅是我,很多人都看出来了。耍点小聪明而已。就像SFinal那样,你为何气急败坏。你用什么方式对付被人,自然会遭到同等待遇。己所不欲勿施于人
2019/12/24 10:28
举报
JFinal博主
回复 @闲大赋 : 我只能说,你被迫害妄想症又犯了。我对标的是 mybatis、hibernate 之类主流的国外的 ORM, 你的项目几乎没人用,我真没正眼看过你的项目
2019/12/24 11:43
举报
SFinal是我写的,我再次强调不要把我牵扯进来,我没有说过JFinal垃圾,也没有否认过你的技术能力,我只是看不惯所谓的 欧拉公式,重定义,首创。 他们说的很对,这是你的风格,让我宽容点,但我想说,这也是我的说话风格,大家互不干涉就好。 再说一次,我从没骂过JFinal不行,更加没有对你进行人身攻击,本来不想留言的,你自己回去看看你对我人身攻击了多少次。 再说一次,不要把我牵扯进来了。
2019/12/23 20:01
举报
JFinal博主
你没怎么看我写的正文,在这说东说西,无限发散,先好好看了再说事。将 antlr 的事说清楚了不迟
2019/12/23 14:41
举报
你写的正文完全不对,我已经反驳你了,都不小了,还信口雌黄,说antlr有bug,没有调试。这不是说清楚问题,而是免费教会你什么是antlr。
2019/12/23 16:39
举报
JFinal博主
我写的正文完全是对的,有理有据,你根本拿不出反驳的依据来,连逻辑都是混乱的,只知道胡乱下结论说人家的正文不对。 你的逻辑在哪里? 我在正文中说的几个事十分明确,你到现在还是东躲西藏,避重就轻,给人乱下结论,毫无逻辑,转移话题
2019/12/23 18:02
举报
JFinal博主
我对 antlr 一丁点兴趣都没有,所以我决不会在 enjoy 模板引擎中使用它,谁让你教 antlr 了? 自做多情,自以为是
2019/12/23 18:05
举报
你若不说antlr,我都懒得回复。一个手写简单parser的去发文批评DSL开发平台
2019/12/24 11:02
举报
JFinal博主
回复 @闲大赋 : 我真不想说 antlr 这事,纯粹是邀回复罗总的疑问,为此他专门写了博客:(今天 oschina 抽风,url 发不出来,你自己看看罗总的博客)
2019/12/24 11:20
举报
4. 如果波总在 3.0 发布的时候先写如今天这篇博客的技术分析, 解释自己为什么没有选择 ANTLR, 同时在新闻中这样表达: "Enjoy 引擎的开发没有选择使用 ANTLR, 因为我认为这样做能更精巧地让我掌控 Parser 的开发演化, 具体技术分析请参见..., " 我相信不会引发其后一系列的风波. 在我心中, 波总也会是一个更加稳重且专业的大牛. 将个人洗好甚至情绪带入产品发布甚至手册, 不是一个专业的态度; 如果波总能接受我在这方面的意见相信对 JFinal 不会有任何坏处.
2019/12/23 04:03
举报
JFinal博主
通过这几天与罗总交流,我得到很多信息量,以后发新版本会考虑周全些,谢谢罗总的建议
2019/12/23 11:46
举报
JFinal博主
我这里再补充一些信息量:beetl 走的是 javascript 语法风格路线,js 的语法是极其灵活复杂的,所以 .g4 出 bug 的概率是很大的,很多 .g4 文件的 bug 现在没有暴露出来,是因为多数用户将 beetl 当成模板引擎使用,而这个场景,常用的语法只有极其有限的几种,如:for、if、${} 等等。 例如,我以前就随手发现过 beetl 语法处理的 bug:if 语句的 body 部分不能与 if 处在同一行 @if(...){...},最后一个大扩号添加 @ 字符也不行: @if(...){...@}。非得要让最后的大括号处在下一行才可以。
2019/12/24 12:31
举报
该评论暂时无法显示,详情咨询 QQ 群:912889742
JFinal博主
算是我误解吧,抱歉 😄
2019/12/23 11:44
举报
该评论暂时无法显示,详情咨询 QQ 群:912889742
JFinal博主
我跟罗总在这里说话,你这是从哪蹦跶出来的? 你自己扯的那些事都说不明白,又来在这里和稀泥?
2019/12/24 11:45
举报
2. 我不赞同波总因为自己有了一个合理的选择, 就否定其他人或项目选择 ANTLR; 尤其不赞同波总在自己产品的新闻发布上使用的措辞. 任何一个产品实现技术都有各自的取舍, Java 选择自己写 Parser, 不等于其否定 Groovy 使用 ANTLR 来写 Parser. Enjoy 选择不适用 ANTLR, 因此就认定其他项目选择 ANTLR 是"飘摇不安"的, 这样的说法我不接受. 波总说 "我相信 antlr 是可靠、稳固的,但我不相信使用者制定的那套描述文件也是可靠稳固的。进而不相信生成的 parser 代码是可靠的", 这段话我可以稍微替换一下: "我相信 Javac 是可靠稳固的, 但我不相信使用者写的 Java 源文件也是可靠稳固的. 进而不相信生成的 class 字节码是可靠的", 请问这个断言是否合理?
2019/12/23 03:48
举报
JFinal博主
罗总最后这个推断这么来表述一下:javac 是可靠的(海量用户、海量场景、超长时间验证过),程序员写的 java 源文件 bug 概率高,但只要 java 源文件的语法是对的不出现编译错误,javac 生成的 class 字节码是在字节码规范这个层面上是正确的,但在程序员利用该java 源文件解决问题的层面上又是错误的,两者并不冲突。 至于我在 3.0 发新闻时的激情表述的背景,我在前两天回复罗总的内容中有过说明,不再重复
2019/12/23 11:43
举报
我其实没有看懂你这个表述, 不过我可以按照表述的形式反推回去这样讲: ANTLR 是可靠的(经过各个大型项目以及长时间验证过), g 文件 bug 概率高, 但只要 g 源文件的语法是对的, 不出现 cc 错误, ANTLR 生成的 Parser 在 parser 规范这个层面上是正确的, 但库开发人员利用该 g 源文件解决问题的层面上又是错误的, 两者并不冲突.
2019/12/23 17:32
举报
JFinal博主
基本是对的,有一点点表述要改一下,我这里直接用我的话再来顺着你的这个例子描述一下。 antlr 是可靠的,但 .g4 文件是用户手写的(这个文件是用来描述语法规则的,语法规则通常十分灵活,一不小心就会有 bug)。只要 .g4 文件符合其规定的书写规则,生成的 parser 在完成 .g4 所约定的事情上是正确的,但如果 .g4 文件所描述的语法逻辑有错误,parser 生成、处理 AST 时也就有错误(parser 是为了生成 AST)
2019/12/24 00:09
举报
JFinal博主
前面争论中 beetl 认为 .g4 文件不会有 bug,让我去给他找 bug 来证明我的逻辑,我上午就在别的使用 antlr 的模板引擎的 commit 记录中找到了,但我不想再得罪更多的作者,我发你私信里头
2019/12/24 00:28
举报
JFinal博主
补充,在 beetl 的 .g4 描述文件中也找到了 bug , github 的现在 url 发不出来,可能是 oschina 临时的bug , 发你私信你了
2019/12/24 01:06
举报
JFinal博主
继续补充详细,如果 java 源代码用于解决业务的逻辑有错误,但符合 java 语言的语法规则,编译出来的 java 字节码在字节码规范层面上是对的,但在解决业务的逻辑层面上是错误的。 注意此时:你仍然可以通过对 java 源码进行调试来解决问题。但在 antlr 那个场景下,生成的 parser 如果有逻辑问题,你无法通过调试那个描述文件来解决,因为它根本无法运行、调试
2019/12/23 12:37
举报
java 源代码编译出来的 class 字节码如果有逻辑层面的错误一定实在 java 源代码级别上解决的; 同样的道理 g 源代码生成的 parser 如果有逻辑问题, 自然也需要在 g 源代码上来解决, g 源码是无法运行调试的, java 源码也无法直接运行调试, 你必须将 java 源码编译之后来运行调试, 同样的道理 g 源码也需要先编译为 parser 源码, 然后继续将 parser 源码编译成可以运行的 class 字节码, 最后通过运行设计好的测试文件来运行调试.
2019/12/23 17:40
举报
JFinal博主
java 源码出现的问题,可以对 java 源码进行调试。但是 antlr 的 .g4 出现 bug 你无法通过运行 .g4 文件,无法调试 .g4 文件,也无法调试 .g4 文件生成的 parser(parser 的内容决定的,前面说过的,不再重复)
2019/12/24 11:48
举报
1. 非常好的技术分析, 我赞同波总在这个地方的推演和选择
2019/12/23 03:38
举报
更多评论
打赏
107 评论
2 收藏
8
分享
返回顶部
顶部