Javacc的学习

简介:
最近公司会使用DSL描述一个domain service。所以趁这个机会也学习下高深的javacc,以前看到一堆的jj_xxx都很头痛,看代码基本都是跳过。

以前看过velocity, cobar的一下代码,都有使用类似jj_xxx,还有最近公司架构师做的一个anxiety,也使用了jj_xx自定义了一套btrace监控的语法:不需要我们自己写java文件,而是按照他的语法规则,它给我们自动生成btrace script。

还有就是万恶的大学,居然没给我们安排编译原理的课程,导致自己基础太差,理解起来颇为困难。没办法只能是硬着头皮先看一些编译原理的基本内容。
推荐一本书: 《编译原理》, 看完以后基本有了一些概念
  • 文法描述定义, 传说中的BNF
    1. 记号集合,终结符号
    2. 非终结符号
    3. 产生式集合  (这个中文版翻译的产生式还真TM的别扭,先不管)
    1.digi := [0-9]<span style="white-space: normal;"> </span>  

  • 词法分析,读入输入流,结合符号表转化为后端使用的符号流。 
    1. 剔除空白字符
    2. 常数处理
    3. 识别符号和关键词
  • 语法分析,构造语法树。
    1. 自定向下,自底向上。 (javacc采用的是自顶向下)
    2. 超前扫描(lookahead) , 根据非终结符查找对应的生产式,可能会导致匹配失败,需要进行回溯
    3. 预测分析法(递归下降法)。非终结符需要无二义性,可以唯一定义一条生产式,要避免出现左递归。 expr := expr + dis
  • 语法制导和翻译 
  • 代码生成和优化


一个javacc的例子,写的还不错: http://www.iteye.com/topic/359454

在学习之前,一定要先弄会BNF文法描述,感觉有点和离散数学的推导论类似。

BNF的一些语法规则,和正则有着类似的语法:  http://blog.csdn.net/yethyeth/archive/2007/01/23/1491150.aspx

 

  • 在双引号中的字("word")代表着这些字符本身。而double_quote用来代表双引号。
  • 在双引号外的字(有可能有下划线)代表着语法部分。 
  • 尖括号( < > )内包含的为必选项。 
  • 方括号( [ ] )内包含的为可选项。 
  • 大括号( { } )内包含的为可重复0至无数次的项。 
  • 竖线( | )表示在其左右两边任选一项,相当于"OR"的意思。 
  • ::= 是“被定义为”的意思。 
试着分析anxiety的BNF定义,它的语法: 

1.import com.alibaba.service.template.*;  
2.import com.alibaba.turbine.module.screen.TemplateScreen;  
3.import com.alibaba.turbine.service.rundata.RunData;  
4.import com.alibaba.webx.WebxException;  
5.method=com.alibaba.manometer.module.screen.Shuffle.execute(RunData, TemplateContext)  
6.method=java.lang.Long.valueOf(long)  
7.method=java.util.concurrent.ConcurrentLinkedQueue.poll()  

根绝这个目标语法需求,符号表可定义:

1.TOKEN :   
2.{  
3.     <METHOD  : "method">    
4.  |  <IMPORT  : "import">    
5.}  
6.  
7.TOKEN :  
8.{    
9.     <IDENT      : <ALPHA> (<ALPHA>|<NUM>)*>   
10.  |  <ALPHA      : (["a"-"z","A"-"Z"])>  
11.  |  <NUM        : (["0"-"9"])>  
12.  |  <COMMA      : ",">  
13.  |  <SEMICOLON  : ";">  
14.  |  <LPAREN     : "(">  
15.  |  <RPAREN     : ")">    
16.  |  <DOMAIN     : ".">  
17.  |  <ASSIGN     : "=">    
18.  |  <STAR       : "*">    
19.}  

里面的 IDENT代表一个java全限定类名或者方法名,支持数字+字母。理论上java的命名规则是可以支持其他的类似中文,下划线等等,这里先不考虑。

最后定义BNF表达式: 

1.param  ::= ((IDENT ('.' IDENT)* ) (IDENT)?)*       
2.method ::= IDENT ('.' IDENT)*                             
3.clazz  ::= IDENT ('.' IDENT)* (';')*                         
4.statMethod ::= METHOD '=' method '(' param (,param)* ')'  
5.impPack ::= IMPORT '=' clazz  
6.parse ::= (impPack|statMethod)  

param的一个例子: java.util.String str
method的一个例子:  java.lang.Long.valueOf
clazz的一个例子:  com.alibaba.turbine.service.rundata.RunData;

 

 

 


这里的clazz需要考虑 java.util.*的情况,会有个超前扫描的过程:  [ LOOKAHEAD( { getToken(1).kind == STAR && getToken(2).kind == SEMICOLON } ) <STAR> | <SEMICOLON> ]

根据这个表达式,最后的javacc的对应的java函数为:
 
1.parse() : {}  
2.{  
3.    (  
4.        (  
5.           impPack() | statMethod()  
6.        )  
7.    )*  
8.}  
9.impPack() : {}  
10.{  
11.   (  
12.     <IMPORT> clazz()  
13.   )  
14.}  
15.statMethod() : {}  
16.{  
17.   (  
18.        <METHOD><ASSIGN>method()<LPAREN>param()  
19.        (  
20.         <COMMA> param()  
21.        )*  
22.        <RPAREN>  
23.   )  
24.}  
25.method() : {}  
26.{  
27.   (  
28.     <IDENT>  
29.     (  
30.       <DOMAIN><IDENT>  
31.     )*  
32.   )  
33.}  
34.clazz() : {}  
35.{  
36.   (  
37.     <IDENT>  
38.     (           
39.        <DOMAIN>  
40.        (  
41.           <IDENT> | [ LOOKAHEAD( { getToken(1).kind == STAR && getToken(2).kind == SEMICOLON } ) <STAR> | <SEMICOLON> ]  
42.        )  
43.     )*  
44.     (<SEMICOLON>)*  
45.   )  
46.}  
47.String param() : {Token t;StringBuilder sb = new StringBuilder();}  
48.{  
49.    (  
50.     (  
51.      <IDENT>  
52.      (  
53.        <DOMAIN><IDENT>  
54.      )*  
55.     )  
56.     (<IDENT>)?   
57.    )*  
58.}  

最后剩下的就是填充具体的方法实现了。

通过javacc进行编译生成对应的java文件:

 

最后

至于其他的jjdoc(用于编写BNF)和jjTree(构建语法树),后续有时间再学习下,javacc只是一些基本的词法分析+简单语义定义的使用。

相关文章
|
3月前
阿里云产品十二月刊来啦
全新万相2.6系列模型正式发布,通义百聆语音交互模型开源,PAI 模型评测新支持双模型离线竞技功能|产品十二月刊
422 167
阿里云产品十二月刊来啦
|
SQL 分布式计算 测试技术
扩展Spark Catalyst,打造自定义的Spark SQL引擎
在Spark2.2版本中,引入了新的扩展点,使得用户可以在Spark session中自定义自己的parser,analyzer,optimizer以及physical planning stragegy rule。
4859 0
|
3月前
|
人工智能 监控 供应链
企业如何应用数据中台?数据中台系统推荐(2025年12月更新)
在AI与数字化融合背景下,数据中台已成为企业实现数据资产化、驱动业务创新的核心引擎。本文系统解析其核心应用场景与落地路径,对比瓴羊Dataphin、字节Dataleap、奇点云DataSimba等主流产品,从技术亮点、适用场景、资质认证等维度提供选型指南。尤其推荐瓴羊Dataphin,凭借AI驱动、全链路能力与多云兼容性,助力企业高效释放数据价值,赋能数字化转型。
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
用AI精准定位问题代码,调试时间直接砍半!LocAgent:斯坦福开源代码调试神器,多跳推理锁定问题代码
LocAgent是由斯坦福大学、耶鲁大学等顶尖机构联合开发的代码定位框架,通过将代码库转化为图结构并利用大语言模型的多跳推理能力,实现精准的问题代码定位。
1095 1
用AI精准定位问题代码,调试时间直接砍半!LocAgent:斯坦福开源代码调试神器,多跳推理锁定问题代码
|
SQL 缓存 Java
MyBatis最经典的20道面试题,你都会了吗?
MyBatis最经典的20道面试题,你都会了吗?
476 0
|
存储 数据可视化 数据挖掘
使用Matlab绘制简单的二维与三维图形
【10月更文挑战第3天】本文详细介绍了如何在 Matlab 中绘制简单的二维和三维图形,包括曲线图、柱状图、散点图、网格图、表面图、等高线图、多边形填充图、切片图及矢量场等。文章提供了丰富的代码示例,如使用 `plot`、`bar`、`scatter`、`plot3`、`mesh`、`surf`、`contour` 等函数绘制不同类型图形的方法,并介绍了 `rotate3d`、`comet3` 和 `movie` 等工具实现图形的交互和动画效果。通过这些示例,读者可以轻松掌握 Matlab 的绘图技巧,并应用于数据可视化和分析中。
|
前端开发 BI API
钉钉多维表目前没有提供具体的API文档供开发者调用
【2月更文挑战第17天】钉钉多维表目前没有提供具体的API文档供开发者调用
717 4
|
人工智能 自然语言处理 算法
GPT-4无师自通预测蛋白质结构登Nature子刊!LLM全面进军生物学,AlphaFold被偷家?
【9月更文挑战第17天】近日,《自然》子刊发表的一篇论文展示了GPT-4在预测蛋白质结构方面的惊人能力,这一突破不仅揭示了大型语言模型在生物学领域的巨大潜力,还可能影响传统预测工具如AlphaFold的地位。研究人员发现,GPT-4仅通过自然语言处理就能准确预测蛋白质的三维结构,包括常见的氨基酸序列和复杂的α-螺旋结构。实验结果显示,其预测精度与实际结构非常接近。这一成果意味着自然语言处理技术也可应用于生物学研究,但同时也引发了关于其局限性和对现有工具影响的讨论。论文详情见:https://www.nature.com/articles/s41598-024-69021-2
323 8
|
人工智能 架构师 搜索推荐
AI Agent【项目实战】:MetaGPT遇上元编程,重塑复杂多智能体协作的边界
【7月更文挑战第4天】AI Agent【项目实战】:MetaGPT遇上元编程,重塑复杂多智能体协作的边界
AI Agent【项目实战】:MetaGPT遇上元编程,重塑复杂多智能体协作的边界
|
机器学习/深度学习 自然语言处理 搜索推荐
LangChain在个性化内容生成中的实践
【8月更文第3天】随着人工智能技术的发展,个性化内容生成已经成为许多应用的核心竞争力。LangChain 是一种开源框架,旨在简化语言模型的应用开发,尤其是针对自然语言处理任务。本文将探讨 LangChain 如何帮助开发者根据用户的偏好生成定制化的内容,从挑战到实践策略,再到具体的案例分析和技术实现。
1068 1

热门文章

最新文章