语法分析器2(递归下降)
语法分析器文档

初使化词法分析器
识别出具有独立意义的最小语法单位
辅助性模块
②重要数据结构
·语法树节点类型
struct ExprNode { //语法树节点类型
enum Token_Type OpCode;
union {
struct {
ExprNode *Left, *Right;
} CaseOperator;
struct {
重复此过程,直到所有A产生式的候选项中均不再有公共前缀。
·构造递归下降子程序的方法:
①构造文法的状态转换图并且简化;
②将转换图转化为EBNF表示;
③从EBNmain.cpp)
#include <stdio.h>
#include "parser.h"
·消除左递归算法
输入:无回路文法G
输出:无左递归的等价文法G’
方法:将非终结符合理排序:A1,A2,…,An,然后运用下述过程:
for i in 2..n
loop for j in 1..i-1
loop用AjQ1|Q2|…|Qk的右部替换每个形如AiAj产生式中的Aj,得到新产生式:
编译原理 语法分析(2)_ LL(1)分析法1

自底向上分析法
LR分析法的概念 LR分析法的概念 LR(0)项目族的构造 LR(0)项目族的构造 SLR分析法 SLR分析法 LALR分析法 LALR分析法
概述
功能:根据文法规则 文法规则, 源程序单词符号串 单词符号串中 功能:根据文法规则,从源程序单词符号串中
识别出语法成分,并进行语法检查。 识别出语法成分,并进行语法检查。
9
【例】文法G[E] 文法G[E] E→ E +T | T 消除左递归 T→ T * F | F F→(E)|i 请用自顶向下的方法分析是否字 分析表 符串i+i*i∈L(G[E])。 符串i+i*i∈L(G[E])。
E→TE’ E’→+TE’|ε T →FT’ T’→*FT’|ε F→(E)|i
编译程序组织结构
表 处 理
前
端 中
源 程 序
词 法 分 析
语 法 分 析
语 义 分 析
间 代 码 生 成
中 后 目 端 间 标 代 代 码 码 优 生 化 成
目 标 程 序
错 误 处 理
第4章 语法分析
自顶向下分析法
递归子程序法(递归下降分析法) 递归子程序法(递归下降分析法) LL(1)分析法 LL(1)分析法
通常把按LL(1)方法完成语法分析任务的程序叫LL(1)分析程序或者LL(1)分析器。 通常把按LL(1)方法完成语法分析任务的程序叫LL(1)分析程序或者LL(1)分析器。 LL(1)方法完成语法分析任务的程序叫LL(1)分析程序或者LL(1)分析器
输入串
一、分析过程
#
此过程有三部分组成: 此过程有三部分组成: 分析表 总控程序) 执行程序 (总控程序) 分析栈) 符号栈 (分析栈)
递归下降 语法

递归下降语法递归下降语法是一种用于解析和分析编程语言的方法。
它是基于文法规则的自顶向下的分析方法,通过递归地向下分解语法规则,将复杂的语法结构拆解为简单的语法单元,从而实现对编程语言的解析和理解。
在递归下降语法中,首先需要定义语法规则。
语法规则是一种形式化的描述,用于定义编程语言的语法结构。
它通常由一系列的产生式组成,每个产生式定义了一个语法规则,包含一个非终结符和若干个终结符或非终结符的组合。
递归下降语法的解析过程是从语法的起始符号开始,通过递归地调用子规则来解析整个语法。
在解析过程中,每个非终结符都对应一个解析函数,用于解析该非终结符的语法规则。
解析函数根据当前的词法单元和语法规则,选择适当的子规则进行解析,并返回解析结果。
递归下降语法的解析过程可以看作是一个树的遍历过程。
解析函数根据当前的词法单元选择相应的子规则进行解析,并递归地调用子规则的解析函数,直到解析完成。
在解析过程中,可以根据需要进行语义分析和错误处理,以保证解析结果的准确性和完整性。
递归下降语法的优点是简单直观,易于理解和实现。
它可以直接反映编程语言的语法结构,便于进行语法分析和解析。
同时,递归下降语法还可以方便地扩展和修改,以适应不同编程语言的需求。
然而,递归下降语法也存在一些限制和问题。
首先,递归下降语法要求文法是LL(k)文法,即左递归、左公因子和回溯都不允许出现。
这限制了递归下降语法的适用范围,使其不能处理一些复杂的语法结构。
其次,递归下降语法容易产生回溯,导致解析效率低下。
为了避免回溯,可以通过引入预测分析表或使用递归下降语法的改进版本,如LL(*)或递归下降预测分析器。
递归下降语法是一种常用的语法分析方法,适用于大多数编程语言的解析和分析。
它以自顶向下的方式解析语法规则,通过递归地调用子规则,将复杂的语法结构拆解为简单的语法单元。
尽管递归下降语法存在一些限制和问题,但在实际应用中仍然具有一定的优势和价值。
递归下降分析实验报告

实习二递归下降分析一、实验目的:根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验预习提示1、递归下降分析法的功能词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。
2、递归下降分析法的前提改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法,3、递归下降分析法实验设计思想及算法为G的每个非终结符号U构造一个递归过程,不妨命名为U。
U的产生式的右边指出这个过程的代码结构:(1)若是终结符号,则和向前看符号对照,若匹配则向前进一个符号;否则出错。
(2)若是非终结符号,则调用与此非终结符对应的过程。
当A的右部有多个产生式时,可用选择结构实现。
具体为:(1)对于每个非终结符号U->u1|u2|…|un处理的方法如下:U( ){ch=当前符号;if(ch可能是u1字的开头) 处理u1的程序部分;else if(ch可能是u2字的开头)处理u2的程序部分;…else error()}(2)对于每个右部u1->x1x2…x n的处理架构如下:处理x1的程序;处理x2的程序;…处理x n的程序;(3)如果右部为空,则不处理。
(4)对于右部中的每个符号x i①如果xi为终结符号:if(xi= = 当前的符号){NextChar();/% NextChar为前进一个字符函数。
%/return;}else 出错处理②如果xi为非终结符号,直接调用相应的过程xi()三、实验要求程序输入/输出示例:对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|-TG|ε(3)T->FS(4)S->*FS|/FS|ε(5)F->(E)|i输出的格式如下:(1)输入一以#结束的符号串(包括+—*/()i#)(2)备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。
编译原理第三章练习题答案

编译原理第三章练习题答案编译原理第三章练习题答案编译原理是计算机科学中的重要学科,它研究的是如何将高级语言代码转化为机器语言的过程。
在编译原理的学习过程中,练习题是不可或缺的一部分,通过完成练习题可以更好地理解和掌握编译原理的知识。
本文将为大家提供编译原理第三章练习题的答案,希望对大家的学习有所帮助。
1. 什么是语法分析?语法分析是编译器中的一个重要模块,它的主要任务是根据给定的语法规则,对输入的源代码进行分析和解释。
语法分析器会根据语法规则构建一个语法树,用于表示源代码的结构和含义。
常用的语法分析方法有递归下降法、LL(1)分析法和LR分析法等。
2. 什么是LL(1)文法?LL(1)文法是一种特殊的上下文无关文法,它具有以下两个特点:(1) 对于任何一个句子,最左推导和最右推导是唯一的。
(2) 在预测分析过程中,只需要向前看一个输入符号就可以确定所采用的产生式。
LL(1)文法是一种常用的文法形式,它适用于递归下降法和LL(1)分析法。
3. 什么是FIRST集合和FOLLOW集合?FIRST集合是指对于一个文法符号,它能够推导出的终结符号的集合。
FOLLOW 集合是指在一个句型中,某个非终结符号的后继终结符号的集合。
计算FIRST集合和FOLLOW集合可以帮助我们进行语法分析,特别是LL(1)分析。
4. 什么是递归下降语法分析法?递归下降语法分析法是一种基于产生式的自顶向下的语法分析方法。
它的基本思想是从文法的开始符号开始,递归地根据产生式进行分析,直到推导出输入符号串或发现错误。
递归下降语法分析法的实现比较简单,但对于某些文法可能会出现回溯现象,影响分析效率。
5. 什么是LR分析法?LR分析法是一种自底向上的语法分析方法,它的基本思想是从输入符号串开始,逐步构建语法树,直到推导出文法的开始符号。
LR分析法具有较好的分析效率和广泛的适用性,常用的LR分析方法有LR(0)、SLR(1)、LR(1)和LALR(1)等。
《递归下降分析法》实验报告

《编译原理》课程实验报告姓名:LZ学号:110地点:机房教师:老师院系:计通专业:计算机char scaner(char*input,int* p);void S(char*input,int* p);void T(char*input,int* p);void T1(char*input,int* p);void error();int sym=0;int main(){int p=0;char input[200]={0};printf("提示:单词只能由( ) a ^ , 组成,且单词必须以$#结尾\n"); printf("请输入你要识别的单词\n");return 0;}char scaner(char*input,int *p){char temp=input[*p];(*p)++;return temp;}void S(char*input,int* p) {if(sym=='a'||sym=='^')sym=scaner(input,p);{S(input,p);T1(input,p);return ;}void T1(char*input,int* p){if(sym==','){sym=scaner(input,p);S(input,p);T1(input,p);}else if(sym!=')')error();}void error(){printf("error!");return ;}三.实验步骤四.总结与回顾通过该实验的操作,我了解了语法分析器的内部工作原理,并掌握自上而下语法分析的要求与特点。
了解了每个函数的功能是识别由该终结符所表示的语法成分,通过在实验中运用一定的编程技巧,掌握对表达式进行处理的一种方法;在实验最后的调试中让我对该实验有了更全面的知识掌握,从中进步了不少。
编译原理之递归下降语法分析程序(实验)
编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤C语⾔编制递归下降分析程序,并对简单语⾔进⾏语法分析。
编制⼀个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
⼆、实验原理每个⾮终结符都对应⼀个⼦程序。
该⼦程序根据下⼀个输⼊符号(SELECT集)来确定按照哪⼀个产⽣式进⾏处理,再根据该产⽣式的右端:每遇到⼀个终结符,则判断当前读⼊的单词是否与该终结符相匹配,若匹配,再读取下⼀个单词继续分析;不匹配,则进⾏出错处理每遇到⼀个⾮终结符,则调⽤相应的⼦程序三、实验要求说明输⼊单词串,以“#”结束,如果是⽂法正确的句⼦,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。
例如:输⼊begin a:=9;b:=2;c:=a+b;b:=a+c end #输出success输⼊a:=9;b:=2;c:=a+b;b:=a+c end #输出‘end' error四、实验步骤1.待分析的语⾔的语法(参考P90)2.将其改为⽂法表⽰,⾄少包含–语句–条件–表达式E -> E+T | TT -> T*F | FF -> (E) | i3. 消除其左递归E -> TE'E' -> +TE' | εT -> FT'T' -> *FT' | εF -> (E) | i4. 提取公共左因⼦5. SELECT集计算SELECT(E->TE) =FIRST(TE')=FIRSI(T)-FIRST(F)U{*}={(, i, *}SELECT(E'->+TE')=FIRST(+TE')={+}SELECT(E'->ε)=follow(E')=follow(E)={#, )}SELECT(T -> FT')=FRIST(FT')=FIRST(F)={(, i}SELECT(T'->*FT')=FRIST(*FT')={*}SELECT(T'->ε)=follow(T')=follow(T)={#, ), +}SELECT(F->(E))=FRIST((E)) ={(}SELECT(F->i)=FRIST(i) ={i}6. LL(1)⽂法判断 其中SELECT(E'->+TE')与SELECT(E'->ε)互不相交,SELECT(T'->*FT')与SELECT(T'->ε)互不相交,SELECT(F->(E))与SELECT(F->i)互不相交,故原⽂法为LL(1)⽂法。
递归下降程序实验报告
一、实验目的1. 理解递归下降分析法的原理和实现方法。
2. 掌握递归下降分析程序的设计和调试。
3. 加深对编译原理中语法分析部分的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。
当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。
2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
语法分析递归下降分析法
语法分析递归下降分析法递归下降分析法是一种常用的语法分析方法,它通过构建递归子程序来解析输入的语法串。
该方法可以分为两个步骤:构建语法树和构建语法分析器。
首先,我们需要构建语法树。
语法树是一个表示语言结构的树形结构,它由各类语法片段(非终结符)和终结符组成。
构建语法树的过程就是根据文法规则从根节点开始递归地扩展子节点,直到达到文法推导出的终结符。
具体来说,我们可以通过以下步骤来构建语法树:1.设计满足语言结构的文法规则。
文法规则定义了语法片段之间的关系和转换规则。
2.将文法规则转换为程序中的递归子程序。
每个递归子程序对应一个语法片段,并按照文法规则递归地扩展子节点。
3.设计词法分析器将输入的语法串分词为单个有效的词法单元。
4.从语法树的根节点开始,根据递归子程序逐步扩展子节点,直到达到终结符。
同时,将每一步的扩展结果记录在语法树中。
接下来,我们需要构建语法分析器。
语法分析器是一个根据语法规则判断输入语法串是否符合语法规则的程序。
它可以通过递归下降分析法来实现。
具体来说,我们可以通过以下步骤来构建语法分析器:1.定义一个语法分析器的函数,作为程序的入口。
2.在语法分析器函数中,根据文法规则调用递归子程序,分析输入的语法串。
3.每个递归子程序对应一个语法片段,它会对输入的语法串进行识别和匹配,并根据文法规则进行扩展。
4.如果递归子程序无法匹配当前的输入,那么意味着输入的语法串不符合文法规则。
5.如果递归子程序成功扩展,并继续匹配下一个输入,则语法分析器会一直进行下去,直到分析完整个语法串。
总结起来,递归下降分析法是一种简单而有效的语法分析方法。
它通过构建递归子程序来解析输入的语法串,并构造出对应的语法树。
虽然递归下降分析法在处理左递归和回溯等问题上存在一定的困难,但它仍然是一种重要的语法分析方法,被广泛应用于编译器和自然语言处理等领域。
编译原理作业集第四章修订版
第四章语法分析—自上而下分析本章要点1. 语法分析器的功能;2. 自上而下分析方法,LL(1)文法3. 递归下降分析程序构造;4. 预测分析表的构造及预测分析过程;5. LL(1)分析中的错误处理。
本章目标理解和掌握语法分析器的功能、自上而下分析所面临的问题、LL(1)分析法、递归下降分析的构造过程、预测分析程序等内容。
本章重点1.语法分析器的功能,自上而下的基本概念2.LL(1)文法的条件及其判别,计算first集和follow集3.递归下降分析方法、预测分析表的构造及其预测过程。
本章难点1. 非终结符的First集合,产生式候选的First集合,非终结符的follow集合的求解;2. 左递归消除;3. 递归下降分析程序的编写;作业题一、单项选择题:1. 高级语言编译程序常用的语法分析方法中,递归下降分析法属于分析法。
a. 自左至右b. 自顶向下c. 自底向上d. 自右向左 2. 上下文无关文法可以用 来描述。
a. 正则表达式b. 正规文法c. 扩展的BNFd. 翻译模式 3. 自上而下分析面临的四个问题中,不包括a. 需消除左递归;b. 存在回朔;c. 虚假匹配;d. 寻找可归约串4. 语法分析器接收以________为单位的输入,并产生有关信息供以后各阶段使用。
a. 表达式;b. 产生式;c. 单词;d. 语句;5. 自上而下分析的主旨是,对任何单词符号串,试图用一切可能的办法,从文法开始符号(根结点)出发,________。
a. 为输入串寻找最右推导;b. 为输入串寻找最左直接子树;c. 为输入串建立最右直接子树;d. 为输入串寻找最左推导;6. 把规则T→F | T*F 表示成扩展的巴克斯范式以后,画出它的语法图应该是 。
图a图b图c图d7. 下列文法中,_______是LL(1)文法。
a. S →aSb|abb. S →ab|Sabc. S →aS|bd. S →aS|a 8. 设有文法G : S→Ap|Bq A→a|cAB→b|dB则,First(Ap)={_______________} a. a,c b. b,d c. p, q d. A, p一.答案:1. b ;2. c ;3. d ;4. c ;5. d ;6. 图a ;二、填空题:1. 语法分析器的工作本质上就是按____________________,识别输入符号串是否为一个句子。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<stdio.h>#include<stdlib.h>#include<iostream>using namespace std;//函数申明//变量长度#define MAX_LENTH 200//表长度#define CON_LEN 30//常量表#define IDE_LEN 30//标识符表#define STR_LEN 30//字符串表//token#define TOKEN_LEN 30//编码#define c_identifier 0#define c_char 1#define c_string 2#define c_constant 3#define c_key_base 40//其他编码在reserver数组中把索引加即可得到char reserve[][20] = { "int", "main", "while", "for", "void", "char", "if","return","do","float" }; char token[TOKEN_LEN] = { ' ' };typedef struct node {int code;int value;}Node;#define NODE_LENTH 120Node n[NODE_LENTH];int ni = 0;/*词法分析相关函数的声明*/int state_machine(char ch, int state);int state_to_code(int prestate);int is_digit(char ch);int is_char(char ch);int is_key(char *);void show_table(char **t);void show_tokens(Node * n, int num);/*语法分析的相关定义*/#define rule_row 6#define rule_col 4//string exp0 = "2*(2*/4)#";int w;int pos = 0;#define end_file 333/*语法分析相关函数的声明*/ void _MAIN();void _E();void _T();void _F();void _P();void _Q();int is_d(int);int is_d(int ch){if (ch == 3 || ch == 4||ch == 2)return 1;elsereturn 0;}void main(){//常数表char*con[CON_LEN];//标识符表char*ide[IDE_LEN];//符号串表char*str[STR_LEN];int i = 0;int state = 1;int prestate;int f_read = 1;int code = 0;char ch = ' ';int ci = 0, cj = 0, ck = 0;FILE*fp = NULL;char filename[] = "source.txt";//fopen_s(&fp, filename, "r");fp = fopen(filename, "r");if (NULL == fp) {cout << "文件没有打开,程序退出" << endl;exit(1);}while (!feof(fp)){ch = fgetc(fp);cout << ch;}cout << endl;rewind(fp);while (!feof(fp)){//printf("%c", fgetc(fp));if (1 == f_read){ch = fgetc(fp);}if ((ch == ' ' || ch == '\n' || ch == '\t') && state == 1) {f_read = 1;continue;}prestate = state;state = state_machine(ch, state);if (state){f_read = 1;token[i++] = ch;}else{f_read = 0;token[i] = '\0';i = 0;state = 1;if (prestate == 2)//变量{int cc = is_key(token);if (0 == cc)//变量{char *ct = (char*)malloc(sizeof(char)*MAX_LENTH + 1);//strcpy_s(ct, sizeof(ct), token);strcpy(ct, token);ct[MAX_LENTH] = '\0';ide[ci++] = ct;if (ci >= IDE_LEN){//printf("变量表溢出!!!!!!\n");//printf("%s__(%d,%d)\n", token, prestate, ci - 1);n[ni].code = prestate;n[ni++].value = ci - 1;cout << "变量表溢出" << endl;}}else//关键字{//printf("%s__(%d,-1)\n", token, cc);n[ni].code = cc;n[ni++].value = -1;}}else if (prestate == 3)//常数{char *ct = (char*)malloc(sizeof(char)*MAX_LENTH + 1);//strcpy_s(ct, sizeof(ct),token);strcpy(ct, token);ct[MAX_LENTH] = '\0';con[cj++] = ct;if (cj >= CON_LEN){//printf("常量表溢出!!!!!!\n");cout << "常量表溢出" << endl;}//printf("%s__(%d,%d)\n", token, prestate, cj - 1);n[ni].code = prestate;n[ni++].value = cj - 1;}else if (prestate == 18)//符号串{char *ct = (char*)malloc(sizeof(char)*MAX_LENTH + 1);//strcpy_s(ct, sizeof(ct), token);strcpy(ct, token);ct[MAX_LENTH] = '\0';str[ck++] = ct;if (ck >= STR_LEN){//printf("符号串表溢出!!!!!!\n");cout << "符号串表溢出" << endl;}//printf("%s__(%d,%d)\n", token, prestate, ck - 1);n[ni].code = prestate;n[ni++].value = ck - 1;}else{//printf("%s__(%d,-1)\n", token, prestate);n[ni].code = prestate;n[ni++].value = -1;}}}/*printf("************变量表(%d)************\n", ci);show_table(ide, ci);printf("************常量表(%d)************\n", cj);show_table(con, cj);printf("************字符串表(%d)************\n", ck);show_table(str, ck);*/n[ni].code = end_file;n[ni++].value = -1;show_tokens(n, ni);//开始语法分析_MAIN();getchar();getchar();}void show_table(char **t, int num){for (int i = 0; i < num; i++){printf("%s\n", t[i]);}}int is_key(char * t){int b = 0;for (int i = 0; i < sizeof(reserve) / sizeof(reserve[0]); i++){ if (0 == strcmp(reserve[i], t)) {//printf("关键字比较%s--%s", reserve[i], t);b = c_key_base + i;//关键字break;}}return b;}int state_to_code(int prestate){//prestate 对应的编码//标识符2//整数3//小数4//( 5//) 6//{ 7//} 8//+ 9//- 10// * 11// / 12// 's' 15// "13" 18//= 19//==20//, 21//; 22//[ 23//] 24//< 25//<= 26//> 27//>= 28int code = 0;if (prestate == 2){code = c_identifier;for (int i = 0; i < sizeof(reserve); i++){if (0 == strcmp(reserve[i], token)) {code = c_key_base + i;//关键字}}}return code;}int state_machine(char ch, int state){//设置状态转换表struct pair{char ch;int state;};struct pair t0[] = { { ' ', 0 } };struct pair t1[] = {{ 'l', 2 }, { 'd', 3 },{ '(', 5 }, { ')', 6 },{ '{', 7 }, { '}', 8 },{ '+', 9 }, { '-', 10 },{ '*', 11 }, { '/', 12 },{ '\'', 13 }, { '\"', 16 },{ '=', 19 }, { ',', 21 },{ ';', 22 }, { '[', 23 },{ ']', 24 }, { '<', 25 },{ '>', 27 },{ ' ', 0 } };struct pair t2[] = { { 'l', 2 }, { 'd', 2 }, { '_', 2 }, { ' ', 0 } };struct pair t3[] = { { 'd', 3 }, { '.', 3 }, { ' ', 0 } };struct pair t4[] = { { 'd', 4 }, { ' ', 0 } };struct pair t5[] = { { ' ', 0 } };struct pair t6[] = { { ' ', 0 } };struct pair t7[] = { { ' ', 0 } };struct pair t8[] = { { ' ', 0 } };struct pair t9[] = { { ' ', 0 } };struct pair t10[] = { { ' ', 0 } };struct pair t11[] = { { ' ', 0 } };struct pair t12[] = { { ' ', 0 } };struct pair t13[] = { { 'l', 14 }, { ' ', 0 } };struct pair t14[] = { { '\'', 15 }, { ' ', 0 } };struct pair t15[] = { { ' ', 0 } };struct pair t16[] = { { 'l', 17 }, { ' ', 0 } };struct pair t17[] = { { 'l', 17 }, { '\"', 18 }, { ' ', 0 } };struct pair t18[] = { { ' ', 0 } };struct pair t19[] = { { '=', 20 }, { ' ', 0 } };struct pair t20[] = { { ' ', 0 } };struct pair t21[] = { { ' ', 0 } };struct pair t22[] = { { ' ', 0 } };struct pair t23[] = { { ' ', 0 } };struct pair t24[] = { { ' ', 0 } };struct pair t25[] = { { '=', 26 }, { ' ', 0 } };struct pair t26[] = { { ' ', 0 } };struct pair t27[] = { { '=', 28 }, { ' ', 0 } };struct pair t28[] = { { ' ', 0 } };struct pair*sl[] = { t0, t1, t2, t3, t4, t5, t6,t7, t8, t9, t10, t11, t12, t13,t14, t15, t16, t17, t18, t19, t20,t21, t22, t23, t24, t25, t26, t27, t28 };struct pair* temp = sl[state];if (1 == is_char(ch)) ch = 'l';else if (1 == is_digit(ch)) ch = 'd';while (temp->state){if (ch == temp->ch) return temp->state;temp++;}return 0;}int is_char(char ch){if ((ch >= 'a' &&ch <= 'z') || (ch <= 'Z' &&ch >= 'A')) return 1;return 0;}int is_digit(char ch){if (ch >= '0' &&ch <= '9') return 1;return 0;}void show_tokens(Node * n, int num){cout << "词法分析后的token序列" << endl;for (int i = 0; i < num; i++){cout << n[i].code << " " << n[i].value << endl;}}/**语法分析的函数实现*/void _MAIN(){w = n[pos++].code;_E();if (w == end_file)cout << "ok" << endl;else{cout << "wrong!" << endl;}}void _E(){_T();if (w == 9 || w == 10){w = n[pos++].code;if (w == end_file) {cout << "wrong!" << endl;system("pause");}_T();}}void _T(){_F();if (w == 11 || w == 12){w = n[pos++].code;if (w == end_file){cout << "wrong!" << endl;system("pause");}_F();}}void _F(){if (1 == is_d(w)){w = n[pos++].code;if (n[pos].code == end_file){if (w == end_file) {cout << "wrong!" << endl;system("pause");}}}else if (w == 5){w = n[pos++].code;//if (n[pos].code == end_file){if (w == end_file) {cout << "wrong!" << endl;system("pause");}}_E();if (w == 6){w = n[pos++].code;if (n[pos].code == end_file){if (w == end_file) {cout << "wrong!" << endl;system("pause");}}}else{cout << "_wrong!" << endl;system("pause");}}else;}。