现在完成的是一个词法分析器,那么怎么将它与语法分析相连?
话说,基本上所有的编译器构造相关的文章都是把词法分析丢在语法分析之前,类似这样:
预处理(C语言为代表,Jerry没这一环) -> 词法分析 -> 语法分析 -> 语义分析 -> 中间代码生成和代码优化 ->目标代码
貌似互相独立的过程。然而从某种程度上来说,语法和词法应该“混为一谈”,并且建立语法树与后面的部分又相对分离(只共享数据结构信息)。
为了达到这一目的,就得利用词法分析抽出的接口firstToken,nextToken,eofToken这三个函数。如果采用LR分析法(我采用的语法分析的实现是SLR(1)的),那么流程可以这样:
firstToken:初始化(LR分析预测表),将一个特殊LR项目和对应状态值压入LR分析栈;
每一次nextToken:调用分析函数,将当前读入的符号扔进语法分析模块中处理,它可能被直接压入分析栈(移进项目),或者等待栈顶完成规约后再移进(规约项目);
eofToken:将特殊符号END传入扔进分析函数,然后结束语法分析,得到最终的语法树。
从这个实现来看,语法分析是个急性子,它并不等所有的词法分析结束后再去符号池中从头到尾扫荡一次,而是每当词法分析获取一个符号就进行一次语法分析。
附:贴出所有Jerry语言的语法产生式,不过它们与上文内容无关(#表示注释一行)
# Jerry语言
Jerry -> BasicBlock <END>
# 基本块
# 严格地说, 基本块这样定义是不正确的, 不过在没有恼人的跳转语句( 包括goto 和 switch-case )的情况下, 可以这么搞
BasicBlock -> ε
BasicBlock -> Sentence BasicBlock
# 语句
Sentence -> <EOS>
Sentence -> IfElseBranch
Sentence -> WhileLoop
Sentence -> Declaration
Sentence -> <IO> Variable <EOS>
Sentence -> Assignment <EOS>
Sentence -> <BREAK> <EOS>
Sentence -> <LBRACE> BasicBlock <RBRACE>
# if-else 分支
IfElseBranch -> <IF> <LPARENT> Assignment <RPARENT> BasicBlock ElseBlock
ElseBlock -> <ELSE> BasicBlock
ElseBlock -> ε
# while 循环
WhileLoop -> <WHILE> <LPARENT> Assignment <RPARENT> BasicBlock
# 声明
# 初始化尚不支持数组
Declaration -> <TYPE> VariableRegister <EOS>
VariableRegister -> VariableRegister <COMMA> Variable Initialization
VariableRegister -> Variable Initialization
Initialization -> <ASSIGN> Assignment
Initialization -> ε
# 下面的产生式都是运算相关的劳什子
# 优先级高的运算, 要优先规约, 从产生式编写的角度来看, 它们在更靠后更"深"的地方
# 赋值 右结合所以递归定义的方式与其他的节点都不一样. 又因为等号优先级最低, 所以作为最"根部"的语法节点类型
Assignment -> Condition <ASSIGN> Assignment
Assignment -> Condition
# 条件 比较运算和逻辑运算符的结晶
Condition -> Condition <OR> ConjunctiveCondition
Condition -> ConjunctiveCondition
ConjunctiveCondition -> NegativeCondition
ConjunctiveCondition -> ConjunctiveCondition <AND> NegativeCondition
NegativeCondition -> <NOT> Comparison
NegativeCondition -> Comparison
# 比较运算
Comparison –> Comparison <COMPARATOR> Expression
Comparison -> Expression
# 表达式
Expression -> Expression <OP_MUL_DIV> Term
Expression -> Term
# 项
Term –> UnaryFactor
Term -> Term <OP_PLS_MNS> UnaryFactor
# 一元因子, 可能有正负号
UnaryFactor -> SimpleFactor
UnaryFactor -> <OP_PLS_MNS> SimpleFactor
# 简单因子
SimpleFactor -> <INTEGER>
SimpleFactor -> <REAL>
SimpleFactor -> Variable
SimpleFactor -> <LPARENT> Assignment <RPARENT>
# 变量( 包括数组下标等信息 )
Variable -> <IDENT> Dimensions
Dimensions -> <LBRACKET> Assignment <RBRACKET> Dimensions
Dimensions -> ε
分享到:
相关推荐
1. **词法分析**:这是语法分析的前奏,由词法分析器(lexer 或 tokenizer)完成,将源代码分解成一个个符号(token),这些符号代表了语言的基本构造,如关键字、标识符、运算符等。 2. **上下文无关文法(Context...
#### 第一章:小程序前奏 ##### 第一节:认识小程序 - **概念**:微信小程序是一种无需下载安装即可使用的轻量级应用程序,通过微信平台提供服务。 - **特点**:实现“即用即走”,用户只需通过微信扫一扫或搜索即可...
#### 一、爬虫前奏 在开始编写Python网络爬虫之前,有几个关键概念和准备工作需要了解。 1. **基础知识准备**:掌握Python基础语法是进行网络爬虫开发的前提条件。熟悉字符串处理、正则表达式、文件操作等基本技能...
- **FireMonkey (FMX)**:虽然Delphi 2010并未直接包含FireMonkey,但它是后续版本引入的重要跨平台UI框架的前奏。书中可能会提及这一点,作为未来发展方向的展望。 - **Delphi Prism集成**:Delphi 2010集成了...
相对于汇编语言,C语言具有更简洁的语法和更高的可读性,使得程序设计更为高效。在51单片机上使用C语言进行开发,可以充分利用其结构化特性,降低程序维护难度,同时利用丰富的库函数加速开发进程。 这个实战精讲...
### 第1章:Java开发前奏 #### 1.1 Java虚拟机及Java的跨平台原理 - **Java虚拟机(JVM)**:Java虚拟机是一个抽象的计算机模型,它负责执行Java字节码。字节码是一种中间语言,由Java编译器编译而成,可以在任何支持...