打算写一个系列,比较系统的介绍一下一个脚本引擎的设计和实现过程,本来打算使用lex/yacc来举例子,但是由于最近对java语言有了新的认识,故决定使用javacc这个工具来做,这个系列中就是以javacc中的一个比较复杂的例子来进行解说的。
这篇文章是本系列的第一篇,主要说几个概念的定义,有了这些定义,后边就容易理解了。
对一个语言的源文件进行解析,主要是做这样几件事:
- 词法分析
- 语法分析
- 语义分析
当然,每个步骤中都有自己的错误检查机制,这里暂且不表。下边分别对这几个过程进行解说:
词法分析
词法分析过程中,读入的是一个个的字符,返回的是记号(token).记号是语法分析所认识的一种抽象的概念。
语言中的关键字,变量名,数字,操作符,串等都是记号。
int x;
x = 0;
上边这些代码,被词法分析器分析之后,应该生成这样的记号:
<int>,空格,<x>,分号,回车换行,<x>,<=>,<0>,分号
一般而言,在这个过程中,空白字符(空格,tab)都应该被跳过。
词法分析中会用到大量的正则表达式,因为正则表达式的表达能力是非常强大的。在此略微举几个例子,如对数字,变量名的定义,用正则表达式表示如下:
NUMBER ::= [0-9][0-9]*
VAR ::= [a-zA-Z_][a-zA-Z0-9_]*
方括号"[]"表示一个区间,取这个区间中的任意一个字符,"*"表示零次或多次匹配,连字符"-"表示连接此连字符前后的一个区间,如0-9表示从0到9的任意一个字符。所以,NUMBER记号的正则表达式正好可以表示,以0-9中任意一个字符开头,后边跟任意多个0-9之间的数字(含0和9).而VAR的定义正如大部分语言要求的那样,以字母或者下划线开始,后边是任意多个字母或者数字或者下划线。如果需要限定VAR的长度为32位,则可以修改成这样:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->VAR ::= [a-zA-Z_][a-zA-Z0-9_]*{31}
语法分析
语法分析过程中,读入的是词法分析器返回的记号,返回的是规则(rule),这些规则是语义分析所需要的,在语法分析中,一般会使用BNF来表示规则,比如赋值语句是一个合法的语句,则在此处需要定义关于语法的BNF:
assignment ::= INT VAR EQ NUMBER END
INT ::= "int"
VAR ::= [a-zA-Z_][a-zA-Z0-9_]*
EQ = "="
NUMBER ::= [0-9][0-9]*
END ::= ";"
就是说,如果读入了这样一个记号的序列:INT VAR EQ NUMBER END,则这个序列被识别成一个赋值的语句,但是,这个还是一个简单的规则,对于这个语句的意思还是不明确的,也就是说,虽然它可以认识所有的赋值语句,但是没有意义,意义的定义在语义分析部分。
BNF的表达能力也是非常强大的,比如一个四则混合语算的BNF可以定义如下:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->expr ::= term ((+|-) term)*
term ::= factor ((*|/) factor)*
factor ::= number | expr
number ::= [0-9]+
这个BNF可以支持乘除运算优先级高于加减法运算,括号优先级高于乘除法,且可以支持对四则混合运算的任意层次的扩展,比如:
( ( 12 + 3 ) / 6 ) + ( 1/5 + 155 ) 等的正确解析。
语义分析
在语义分析中,我们需要对在语法分析过程中得出的规则进行解释,比如赋值语句,我们需要将起翻译成:将NUMBER这个记号中的‘值’赋给名叫VAR的一个INT型变量。这个过程完成实际的语法解析,使得语言本身对外有意义。语义分析是脚本型的语言的最高级形式,即脚本解析到此为止将被转换成实际的语言内容并交付给宿主语言编译器进行编译并执行。又或者语义分析发现了一个语法分析过程中规约出来的四则运算表达式,那么它会根据语法中的规则对这个表达式进行求值,计算出最终结果来。
在这个系列中我们用到的一个语言叫做SPL(Stupid Programming Language),这是javacc中给它起的名字,我们不妨将其改名为SPL(Simple Programming Language),呵呵。
关于概念就解释到这里,如果你对正则表达式,BNF等概念不是很熟悉,可以先找找资料来学习。好了,第一篇先介绍这么多吧,后边再续。
分享到:
相关推荐
JavaCC(Java Compiler Compiler)是一款强大的词法分析和语法分析工具,主要用于生成Java语言的解析器和词法分析器。这个“javacc-5.0.zip”文件包含了JavaCC的5.0版本,是一个用于处理源代码和其他形式的文本输入...
JavaCC(Java Compiler Compiler)是一款用于构建解析器的工具,尤其适用于那些希望开发编译器、解释器或脚本引擎的程序员。通过JavaCC,用户可以轻松地实现语法分析和词法分析功能,并能自动生成相应的Java代码。 ...
JavaCC,全称为Java Compiler Compiler,是一款强大的、开源的词法分析和语法分析工具,特别适用于构建编译器、解释器或脚本引擎。它是基于LL算法的,允许开发者通过定义文法规则生成解析器。这篇文章旨在详细介绍...
1. **分词模块开发**:利用词表分词技术和前向最大匹配分词算法,设计并实现了一个针对中文信息的分词模块。 2. **语法分析模块**:使用JavaCC工具编写脚本,定义中文语法结构,并生成相应的分析模块。 3. **集成与...
JavaCC将这些规则转换为一个Java源代码文件,该文件实现了一个解析器类,这个类可以读取输入文本并根据规则进行解析。 在实际应用中,JavaCC常用于构建编译器、解释器、查询引擎甚至数据库查询解析器等。它能够生成...
Java表达式解析是编程中的一个重要概念,特别是在设计编译器、解释器或脚本引擎时。这个程序可能是为了理解并执行简单的数学或逻辑表达式,比如`2 + 3 * (4 - 5)`。在Java中实现这样的解析器,我们需要理解表达式...
10. **实践应用**:表达式解析器在许多场景中都很有用,比如命令行解析、SQL查询解析、计算器应用、脚本引擎等。 理解并实现一个表达式解析器是提升编程技能的重要步骤,它涉及到语言理论、编译原理以及对编程语言...
在IT行业中,语言处理器是软件开发中的重要组成部分,特别是在处理自然语言、编译器和...在实际项目中,这样的知识可以应用于各种领域,如开发新的编程语言、创建自定义脚本引擎,甚至是为AI系统构建自然语言理解模块。
这可能需要使用正则表达式或者第三方库如ANTLR或JavaCC来实现代码解析。 5. **文档模板**:为了生成文档,可能需要定义各种模板,使用字符串模板引擎如FreeMarker或Velocity,以动态生成HTML、PDF或其他格式的文档...