实验2.4-学习YACC并构造简单语法分析程序

合集下载

语法分析程序自动产生器yacc的使用方法

语法分析程序自动产生器yacc的使用方法

语法分析程序自动产生器yacc的使用方法2.l yacc概述形式语言都有严格定义的语法结构,我们对它们进行处理时首先要分析其语法结构。

yace 是一个语法分析程序的自动产生器,严格地说Lex也是一个形式语言的语法分析程序的自动产生器。

不过Lex所能处理的语言仅限于正规语言,而高级语言的词法结构恰好可用正规式表示,因此Lex只是一个词法分析程序的产生器。

yace可以处理能用LALR(1)文法表示的上下文无关语言。

而且我们将会看到yace具有一定的解决语法的二义性的功能。

yacc的用途很广,但主要用于程序设计语言的编译程序的自动构造上。

例如可移植的C 语言的编译程序就是用yacc来写的。

还有许多数据库查询语言是用yacc实现的。

因此,yacc 又叫做“编译程序的编译程序("A Compiler ComPiler")。

yacc的工作示意图如下;图2.1 yacc示意图在图2.1中,“yacc源程序”是用户用yacc提供的一种类似BNF的语言写的要处理的语言的语法描述。

yacc会自动地将这个源程序转换成用LR方法进行语法分析的语法分析程序yyparse,同Lex一样,yacc的宿主语言也是C,因此yyParse是一个C语言的程序,用户在主程序中通过调用yyparse进行语法分析。

语法分析必须建立在词法分析的基础之上,所以生成的语法分析程序还需要有一个词法分析程序与它配合工作。

yyparse要求这个词法分析程序的名字为yylex。

用户写yylex时可以借助于Lex。

因为Lex产生的词法分析程序的名字正好是yylex,所以Lex与yacc配合使用是很方便的,这将在2.5的2.5.3中详细介绍,请注意词法分析程序也是可以包含在yacc 源程序中的。

在yacc源程序中除了语法规则外,还要包括当这些语法规则被识别出来时,即用它们进行归约时要完成的语义动作,语义动作是用C语言写的程序段。

语法分析的输出可能是一棵语法树,或生成的目标代码,或者就是关于输入串是否符合语法的信息。

语法分析器实验报告

语法分析器实验报告

语法分析器实验报告一、实验内容编写一个语法分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

利用编程语言实现语法分析程序,并对简单语言进行语法分析。

1.待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>::=begin<语句串>end⑵<语句串>::=<语句>{;<语句>}⑶<语句>::=<赋值语句>⑷<赋值语句>::=ID:=<表达式>⑸<表达式>::=<项>{+<项> | -<项>}⑹<项>::=<因子>{*<因子> | /<因子>⑺<因子>::=ID | NUM | (<表达式>)2.实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。

例如:输入begin a:=9; x:=2*3; b:=a+x end #输出success!输入x:=a+b*c end #输出error测试以上输入的分析,并完成实验报告。

二、实验设计和实现语法分析程序的算法思想:(1)主程序示意图如图1-1所示。

图1-1 语法分析主程序示意图(2)递归下降分析程序示意图如图1-2所示。

(3)语句串分析过程示意图如图1-3所示。

图1-3 语句串分析示意图图1-2 递归下降分析程序示意图(4)statement 语句分析程序流程如图1-4、1-5、1-6、1-7所示。

图1-4 statement语句分析函数示意图图1-5 expression表达式分析函数示意图图1-7 factor分析过程示意图程序首先定义全局变量,指针,数组:char prog[100],token[8],ch;char *rwtab[6]={"begin","if","then","while","do","end"};//关键字int syn,kk,p,m,n,sum;//p是缓冲区prog的指针,m是token的指针然后声明下面几个函数来实现:void scaner();//词法分析算法void lrparser();//递归下降分析void yucu();//语句串分析void statement();//表达式分析void expression();//表达式运算分析void term();//运算符分析void factor(); //因子分析最后:主函数调用scaner函数和lrprarser函数进行语法分析。

语法法分析实验报告

语法法分析实验报告

一、实验目的1. 理解语法分析的基本概念和原理。

2. 掌握语法分析器的构建方法。

3. 培养实际操作能力,提高编程水平。

二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm三、实验内容1. 语法分析概述2. 词法分析3. 语法分析4. 实验实现四、实验步骤1. 语法分析概述(1)了解语法分析的定义、作用和意义。

(2)掌握语法分析的基本原理和流程。

2. 词法分析(1)编写词法分析器代码,将源代码分解成单词序列。

(2)实现词法分析器的各个功能,如:识别标识符、关键字、运算符等。

3. 语法分析(1)设计语法分析器,将单词序列转换为抽象语法树(AST)。

(2)实现语法分析器的各个功能,如:识别表达式、语句、函数等。

4. 实验实现(1)创建Python项目,导入相关库。

(2)编写词法分析器代码,实现单词序列的分解。

(3)编写语法分析器代码,实现抽象语法树的构建。

(4)测试语法分析器,验证其正确性。

五、实验结果与分析1. 词法分析结果实验中,我们成功地将源代码分解成单词序列,包括标识符、关键字、运算符等。

词法分析器的输出结果如下:```identifier: akeyword: intoperator: +identifier: boperator: =integer: 5```2. 语法分析结果通过语法分析器,我们将单词序列转换成抽象语法树。

以下是一个示例的抽象语法树:```Program├── Declaration│ ├── Type│ │ ├── Identifier│ │ └── Integer│ └── Identifier│ └── a└── Statement├── Expression│ ├── Identifier│ └── a└── Operator└── =└── Expression├── Identifier└── b└── Integer└── 5```从实验结果可以看出,我们的语法分析器能够正确地将源代码转换为抽象语法树。

编译原理_实验二_语法分析_递归下降分析器设计_实验报告

编译原理_实验二_语法分析_递归下降分析器设计_实验报告

递归下降分析器设计一、实验/实习过程内容:利用JavaCC生成一个MiniC的语法分析器;要求:1. 用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。

2. 具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示3. 如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树具体实施步骤如下:1.把MiniC转换为文法如下<程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉〈语句串〉|〈语句〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|==|!=2.消除语句中的回溯与左递归3.在eclipse环境下完成JavaCC的插件安装后,写一个JavaCC文法规范文件(扩展名为jj)4.完成的功能包括词法分析,语法分析二、代码:options {JDK_VERSION = "1.5";}PARSER_BEGIN(eg1)public class eg1 {public static void main(String args[]) throws ParseException { eg1 parser = new eg1(System.in);parser.start();}}PARSER_END(eg1)SKIP :{" "| "\r"| "\t"| "\n"}TOKEN : /* OPERATORS */{< PLUS: "+" >| < MINUS: "-" >| < MULTIPLY: "*" >| < DIVIDE: "/" >}TOKEN :{<BIGGER:">"> |<SMALLER:"<"> |<NOTVOLUTION:"!="> |<SMALLEREQDD:"<="> |<BIGGEREE:">=" > |<DOUBLE:"==">TOKEN: //关键字{<MAIN:"main"> |<VOID:"void"> |<IF:"if"> |<INT:"int"> | <WHILE:"while"> |<CHAR:"char"> | <VOLUTION:"="> }TOKEN : //定义整型数{< INTEGER: ["0" - "9"]( <DIGIT> )+ >| < #DIGIT: ["0" - "9"] >}TOKEN : //数字{<NUMBER:(<DIGIT>)+ | (<DIGIT>)+"."| (<DIGIT>)+"."(<DIGIT>)+| "."(<DIGIT>)+>}TOKEN : //标记{<COMMA:","> | <SEMICOLON:";"> | <COLON:":"> | <LEFTPARENTHESES:"("> |<RIGHTPARENTHESES:")"> | <LEFTBRACE:"{"> | <RIGHTBRACE:"}"> }TOKEN : //标识符{<IDENTIFIER:<LETTER> |<LETTER>(<LETTER> | <DIGIT> )* >|<#LETTER:["a"-"z", "A"-"Z"]>}void start():{}{<MAIN> <LEFTPARENTHESES> <RIGHTPARENTHESES> block() }void block():{}{<LEFTBRACE> string() <RIGHTBRACE>}void string():{}{yuju() (string())?}void yuju():{}{fuzhiyuju() | tiaojianyuju() | xunhuanyuju()}void fuzhiyuju():{}{<IDENTIFIER> <VOLUTION> biaodashi() <SEMICOLON>}void tiaojianyuju():{}{<IF> tiaojian() block()}void xunhuanyuju():{}<WHILE> tiaojian() block()}void tiaojian():{}{<LEFTPARENTHESES> biaodashi() guanxifu() biaodashi()<RIGHTPARENTHESES>}void biaodashi():{}{( <LEFTPARENTHESES> biaodashi() <RIGHTPARENTHESES> biaodashi2()) |(<IDENTIFIER> biaodashi2() ) | ( <NUMBER> biaodashi2() )}void biaodashi2():{}{(yunsuanfu() biaodashi() biaodashi2() )?}void yunsuanfu():{}{< PLUS > | < MINUS > |< MULTIPLY> | < DIVIDE >}void guanxifu() :{}{<BIGGER> | <SMALLER> | <NOTVOLUTION><SMALLEREQDD> | <BIGGEREE> | <DOUBLE>}三、实验/实习总结本次实习,我使用javacc完成了包括词法分析,语法分析(输出语法树),能够读文件的功能,总的来说比较满意,通过本次实习掌握了javacc基本的使用。

编译原理实践11—语法分析程序的自动生成工具YACC

编译原理实践11—语法分析程序的自动生成工具YACC

YACC源程序—语法规则部分
•语法规则部分是整个YACC源程序的主体,它是由一组 产生式及相应的语义动作组成。 •规则部分包括修改的BNF格式的文法规则,以及将在识 别出识别出相关的文法规则时被执行的C代码中的动作 (即根据LALR(1)分析算法,在归约中使用)。 •文法规则中使用的元符号惯例如下: 通常,竖线|被用作替换(也可以分别写出替换项),而 用来分隔文法规则的左右两边的箭头符号-〉在YACC中 用冒号表示,最后,必须用分号来结束每个文法规则。
•YACC和LEX有直接的接口,由于YACC与LEX 的特殊功能,这两个姐妹程序成为软件工程的重 要工具,被称为“黄金组合”。
•很多程序设计语言编译程序的设计都使用了 LEX和YACC,比如著名的GNU C语言编译器, PASCAL语言向C语言的转换工具p2c等,就是 用FLEX和BISON实现的
6-语义值类型定义 • 例:
% union{ int ival double dval INTERVAL vval; }
• 引用时候的方式
%token <ival> DREG VREG %token <dval> CONST %type <dval>dexp %type <vval>vexp
以%token开始的行定义的是终结符的类型 以%type开始的行定义是非终结符的类型
exp:exp’+’term{$$=$1+$3;}
含义是:当识别规则exp-〉exp+term时, 左边exp值为右边的exp的值与右边的term 的值之和,其中$$代表规则左部符号exp的 值,$1代表规则右部第一个符号exp的值、 $3表示规则右部第三个符号term的值。

Yacc语法分析器设计步骤

Yacc语法分析器设计步骤

使用Yacc生成语法分析程序1、创建空工程File菜单下选择New:弹出下面对话框:选择Win32 Console Application,同时在Project Name下输入工程名字:ParserByYacc点击Ok按钮,弹出下面对话框:不做任何选择,按照默认“An empty project”,直接点击Finish按钮,弹出下面对话框:直接点击OK按钮,工程创建完毕。

2、使用Yacc生成语法分析程序点击“开始”,在“开始”菜单中选择“运行”,如下图所示在弹出的对话框中敲入cmd,启动DOS窗口使用DOS命令切换到E:\ ParserByYacc将yacc.exe文件拷贝到ParserByYacc工程下:将编写好的TINY.Y文件拷贝到ParserByYacc工程下:运行yacc生成y.tab.c和y.tab.h文件:3、添加文件首先在windows环境下,把设计好的文件GLOBALS.H、MAIN.C、SCAN.C、SCAN.H、PARSE.H、UTIL.C 和UTIL.H拷贝到ParserByYacc工程下:如图所示,选中Project菜单,选择下面Add To Project子菜单下面的Files子菜单:点击后弹出对话框:选中的刚拷贝进来的文件和Yacc生成的文件,点击OK按钮:在左侧的工程文件列表中,可以清楚地看到这些文件:4、生成可执行文件编译生成可执行文件ParserByYacc.exe在本工程的debug目录下:为了验证本语法分析程序的运行结果,把样本程序SAMPLE.TNY拷贝到可执行程序所在的目录下:5、验证运行结果Windows环境下点击“开始”,选中其中的“运行(R)”弹出下面对话框,输入cmd命令:输入上图所示的类似命令,进入可执行程序所在目录。

在当前目录下输入命令:ParserByYacc sample.tny,然后回车,则得到相应的运行结果:。

yacc语法

yacc语法Yacc是一个Unix系统上的自动语法分析工具,它被广泛用于编译器的实现以及其他与语法分析相关的任务。

使用Yacc可以通过自定义语法规则、自动生成语法分析代码,从而减轻开发者的工作量。

本文将围绕Yacc语法展开讲解。

1. 定义语法规则Yacc语法的最基本的元素就是语法规则。

语法规则可以由终结符(nonterminals)和非终结符(terminals)组成。

具体来说,终结符就是由程序中定义的特定单词组成,而非终结符则是一个标识符,它表示一个语法符号的集合。

在Yacc中,语法规则通常被写成这样:`[nonterminal] : options {actions}`其中,`nonterminal`表示非终结符,`options`表示由终结符和非终结符组成的可选项,`actions`则表示在匹配到语法规则时所要执行的动作。

2. 处理符号在Yacc语法中,为了辨别终结符和非终结符,我们使用符号。

符号可以区分终结符和非终结符,并且它们可以用在语法规则和实际输入中。

在Yacc语法中,我们使用`%token`和`%type`命令来声明符号。

具体来说,`%token`命令用于声明终结符,例如:`%token PLUS`而`%type`命令则用于声明非终结符,例如:`%type <ast_node> expression`在这个例子中,我们使用`<ast_node>`指定非终结符的类型。

3. 定义树状结构在Yacc语法中,我们通常需要定义树状结构来帮助我们分析输入。

在Yacc语法中,树状结构被称为抽象语法树(Abstract Syntax Tree, AST)。

为了定义抽象语法树,我们需要使用`$$`符号,它表示正式生成的语法树的节点。

例如,在下面的语法规则中,我们使用`$$`来表示生成的AST节点:```statement : type identifier EQUALS expression { $$ =parse_statement($1, $2, $4); }```在这个例子中,我们通过调用`parse_statement()`函数来生成AST节点。

实验二--语法分析报告程序的设计-

实验二语法分析程序的设计姓名:_ 学号:_ 专业班级一、实验目的通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中预测分析方法。

二、实验内容设计一个文法的预测分析程序,判断特定表达式的正确性。

三、实验要求1、给出文法如下:G[E]E->T|E+T;T->F|T*F;F->i|(E);2、根据该文法构造相应的LL(1)文法及LL(1)分析表,并为该文法设计预测分析程序,利用C语言或C++语言或Java语言实现;3、利用预测分析程序完成下列功能:1)手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束;2)读入文本文件中的表达式;3)调用实验一中的词法分析程序搜索单词;4)把单词送入预测分析程序,判断表达式是否正确(是否是给出文法的语言),若错误,应给出错误信息;5)完成上述功能,有余力的同学可以进一步完成通过程序实现对非LL(1)文法到LL(1 )文法的自动转换(见实验二附加资料1)。

四、实验环境PC微机DOS操作系统或Windows操作系统Turbo C程序集成环境或Visual C++程序集成环境五、实验步骤1、分析文法,将给出的文法转化为LL(1)文法;2、学习预测分析程序的结构,设计合理的预测分析程序;3、编写测试程序,包括表达式的读入和结果的输出;4、测试程序运行效果,测试数据可以参考下列给出的数据。

六、测试数据/***/static String[] gram = { "E->TA", "A->+TA", "A->@", "T->FB", "B->*FB", "B->@","F->P", "F->(E)" };static Strin g[]TollowE = { ")", "#" };输入数据:编辑一个文本文文件 expression.txt ,在文件中输入如下内容:10; 1+2;(1+2)*3+(5+6*7); ((1+2)*3+4; 1+2+3+(*4+5); (a+b)*(c+d); ((ab3+de4)**5)+1;正确结果:(1) 10; 输出: 正确 (2) 1+2; 输出: 正确(3) (1+2)*3+(5+6*7); 输出: 正确(4)((1+2)*3+4 输出: 错误(5) 1+2+3+(*4+5) 输出: 错误 (6) (a+b)*(c+d) 输出: 正确(7) ((ab3+de4)**5)+1 输出: 错误七、源代码import java.util.*;import java.io.*; public class test2 {static String[] key_word = { "main"."if", "the n", "while", "do","int","else" };static Stri ng[] cal_word = { "+"II IIII /II-,,/ ,"<", ">", "{",")", "[", "]", "==""!=" "!""="">=" "<=""+=""-="给定文法 G[E] : E->T|E+T; T->F|T*F; F->i|(E);followEA = {")","#"}; followT = {"+",")","#" }; followTB = {"+",")","#"}; followF = {"*","+",")","#"}; firstE = { "i", "(" }; firstEA = { "+", "@" }; firstT = { "i", "(" }; firstTB = { "*", "@" }; firstF = { "i", "(" };static Stri ng[][] list = {{"", "i",{ "E", "TA", n ull, null, "TA", n ull, null }, { "A", null, "+TA", n ull, null, "@", "@" }, { "T", "FB", null, null, "FB", n ull, null }, { "B", null, "@", "*FB", n ull, "@", "@" }, { "F", "i", null, null, "(E)", n ull, null } }; public static void sca n( Stri ng in file,Stri ngoutfile,StackvString>[] word, Stack<String>[] expression)throws Exception {java.io.File file = new java.io.File(i nfile); Sca nner in put = new Scann er(file);java.io.Pri ntWriter output = new Prin tWriter(outfile); int count = 0;word[cou nt].push("#"); while (in put.hasNext()) {Stri ng tmp = in put .n ext(); int i = 0;while (i < tmp.le ngth()) {if (tmp.charAt(i) <= 9 && tmp.charAt(i) >= '1') {// 检查十进制数字Stri ng num ="";while (tmp.charAt(i) <= 9 &&tmp.charAt(i)>= '0'){num += tmp.charAt(i); i++;if (i == tmp 」en gth()) break;}output.pri ntln ("< " + 1 + ", " + num + ">"); word[co un t].push("i");expressi on[coun t].push( nu m); }if (i + 2 < tmp.le ngth())〃检查十六进制数字if (tmp.charAt(i) == 'O' &&tmp.charAt(i+ 1) == 'x'){i += 2;Stri ng num =""; while ((tmp.charAt(i)<= 9 && tmp.charAt(i) >= '0') ||static String static String static String static String static String static String static String static String static String(tmp.charAt(i)v='f&&tmp.charAt(i) >= 'a')) {num += tmp.charAt(i);i++;if (i == tmp .len gth()) break;}output.pri ntln ("v " + 3 + ", " + num + ">"); word[co unt].push("i");expressi on[coun t].push( nu m);}if (i + 1 < tmp.le ngth())〃检查八进制数字if (tmp.charAt(i) == '0') {i++;Stri ng num ="";while (tmp.charAt(i) <= '7' &&tmp.charAt(i) '0') {num += tmp.charAt(i);i++;if (i == tmp .len gth()) break;}output.pri ntln ("< " + 2 + ", " + num + ">"); word[co unt].push("i");expressi on[coun t].push( nu m);}//检查关键字和变量if (i < tmp.le ngth()) {if (i < tmp.le ngth() && tmp.charAt(i) >= 'a'&& tmp.charAt(i) <= 'z') { Stri ng tmp_word ="";while (tmp.charAt(i) >= 'a' &&tmp.charAt(i)'z') {tmp_word += tmp.charAt(i);i++;if (i == tmp .len gth()) break;}boolea n is_keyword = false;for (int j = 0; j < key_word .len gth; j++) { if(tmp_word.equals(key_word[j])) { output.pri ntln ("< " +key_word[j] + ">= v=实用文档word[co un t].push(key_word[j]);expressio n[co unt].push(key_word[j]); is_keyword =true;break;}}if (!is_keyword) {output.pri ntl n("v " + 0 + ", " + tmp_word+word[co un t].push("i");expressi on[coun t].push(tmp_word);} _}}//检查运算符以及';'if (i < tmp.le ngth()) {if (i + 1 < tmp.le ngth()) {if (tmp.charAt(i + 1) == '=') {for (int j = 0; j < cal_word .len gth; j++) { if tmp.charAt(i)(cal_word[j].equals(""+ tmp.charAt(i + 1))){ output.pri ntln ("v " +cal_word[j] ++ "->");word[co un t].push(cal_word[j]);expressi on[coun t].push("-");if (word[cou nt].peek() == ";"){ word[co un t].pop();word[cou nt].push("#"); count++;word[cou nt].push("#");}i += 2;break;}}}for (int j = 0; j < cal_word .len gth; j++) {if (cal_word[j].equals("" + tmp.charAt(i)))实用文档{ output.pri ntln ("< " + cal_word[j] + ", " +word[co un t].push(cal_word[j]);expressio n[count].push(cal_word[j]); if (word[count].peek() == ";") { word[co unt].pop(); word[cou nt].push("#");coun t++;word[cou nt].push("#");}i++;break;}}}}}in put.close();output.close();}}public static void main(String[] args) throws Exception { Stri ng in file = "D:/expressio n.txt";Stri ng outfile = "D:/result2.txt";StackvStri ng>[] tmpword = new Stack[20]; StackvString>[] expression = new Stack[20]; for(int i = 0; i < tmpword.length; i++) { tmpword[i] =new StackvStri ng>(); expressi on [i] = newStackvStri ng>();testl.scan(infile, outfile, tmpword, expression); int i = 0;while (tmpword[i].size() > 2){Strin g[] tmp = expressio n[ i].toArray( new Stri ng[0]); printArray(tmp);isLL1(tmpword[i]);i++;public static void prin tArray(Stri ng[] s){for (i nt i = 0; i < s.len gth; i++){System.out.pri nt(s[i]);System.out.pri ntl n();}public static void isLL1(Stack<Stri ng> tmpword){ Stri ng[] in put = tmpword.toArray( new Stri ng[0]); int in putCo unt = 0;StackvStri ng> status = new StackvStri ng>(); status.push(input[ in putCo un t++]); status.push("E"); boolea n flag = true;boolea n result = true;while (flag) {if (isVt(status.peek())){if (status.peek().equals(i nput[ in putCo unt])){ status.pop(); in putCo un t++; } else{flag = false; result = false; }else if (status.peek().equals(" '#")){if (status.peek().equals(i nput[ in putCo un t])) flag =false; else{flag = false; result = false; }public static boolea n isVt(Stri ng s) {//for (int i = 1; i < list[0].le ngth - 1; i++) { if (s.equals(list[0][i])) { return true; } } return false;}public static in t[] in dex In List(Stri ng m, String a) { int i= 0, j = 0;for (i nt c = 1; c < list.le ngth; c++) { if (m.equals(list[c][0])) i = c;for (int c = 1; c < list[0].length ; c++) { if (a.equals(list[0][c])) j = c;}retur n new in t[] { i, j };给定文法的LL (1)形式;flag = false; result = false; } }elseif (list[ in dex In List(status.peek(), in put[ in putCo un t])[0]][i ndex In List(status.peek(), input[inputCount])[1]] != null){ in t[] a = in dex In List(status.peek(), in put[ in putCo un t]); if (list[a[0]][a[1]].e ndsWith("@")) status.pop(); else{ status.pop(); for (i nt i = list[a[0]][a[1]].le ngth() - 1; i >= 0; i--){status.push ("” + list[a[0]][a[1]].charAt(i));else{ if (result)System.out.pri ntln( II else正确"); System.out.pri ntl n(II错误"); 判断是否为VtE->TAA->+TA| £T->FBB->*FB| £F->(E) | i实验结果:10;1+2;己氓(l+2)*3+(5+6*7);((l+2)*3+4;l+2+3+(*4+5); (^+b)*(C+d);((at>3+de4)**5)+l;。

用Yacc实现语法分析器-4-编译原理

⽤Yacc实现语法分析器-4-编译原理⽤Yacc实现语法分析器⼀、实验⽬的掌握语法分析器的构造原理,掌握Yacc的编程⽅法。

⼆、实验内容⽤Yacc编写⼀个语法分析程序,使之与词法分析器结合,能够根据语⾔的上下⽂⽆关⽂法,识别输⼊的单词序列是否⽂法的句⼦。

program→blockblock→ { stmts }stmts→ stmt stmts | estmt→ id= expr ;| if ( bool ) stmt| if ( bool) stmt else stmt| while (bool) stmt| do stmt while (bool ) ;| break ;| blockbool →expr < expr| expr <= expr| expr > expr| expr >= expr| exprexpr→expr + term| expr - term| termterm→term * factor| term / factor| factorfactor→ ( expr ) | id| num 三、实验步骤及结果实验环境:unix实验结果:按归约的先后顺序显⽰每次归约时所使⽤的产⽣式。

部分代码:⽤于产⽣flex输⼊的代码View CodeTest.l:[a-zA-Z_][a-zA-Z_0-9]* {return ID;}[0-9]+\.[0-9]+ {return REAL;}[0-9]+ {return NUM;}"||" {return OR;}"&&" {return AND;}"|" {return'|';}"&" {return'&';}"<=" {return LE;}"<" { return'<';}">=" {return GE;}">" {return'>';}"!=" {return NE;}"=" { return'=';}"==" {return EQ;}"\+" {return'+';}"\-" {return'-';}"\*" {return'*';}"\/" {return'/';}"(" {return'(';}")" {return')';}";" {return';';}"{" {return'{';}"}" {return'}';}"[" {return'['; }"]" {return']';}Test.y:rel : expr '<' expr { printf("rel-->expr<expr\n"); }| expr LE expr { printf("rel-->expr<=expr\n"); }| expr GE expr { printf("rel-->expr>=expr\n"); }| expr '>' expr { printf("rel-->expr>expr\n"); }| expr { printf("rel-->expr\n"); };expr : expr '+' term { printf("expr-->expr+term\n"); }| expr '-' term { printf("expr-->expr-term\n"); }| term { printf("expr-->term\n"); };term : term '*' unary { printf("term-->term*unary\n"); }| term '/' unary { printf("term-->term/unary\n"); }| unary { printf("term-->unary\n"); };unary : '!' unary { printf("unary-->!unary\n"); }| '-' unary %prec UMINUS{ printf("unary-->-unary\n"); } | factor { printf("unary-->factor\n"); };factor : '('bool')' { printf("factor-->(bool)\n"); }| loc { printf("factor-->loc\n"); }| NUM { printf("factor-->num\n"); }| REAL { printf("factor-->real\n"); }| TRUE { printf("factor-->true\n"); }| FALSE { printf("factor-->false\n"); }Flex⽣成代码:View CodeTest.l:[a-zA-Z_][a-zA-Z_0-9]* {return ID;}[0-9]+\.[0-9]+ {return REAL;}[0-9]+ {return NUM;}"||" {return OR;}"&&" {return AND;}"|" {return'|';}"&" {return'&';}"<=" {return LE;}"<" { return'<';}">=" {return GE;}">" {return'>';}"!=" {return NE;}"=" { return'=';}"==" {return EQ;}"\+" {return'+';}"\-" {return'-';}"\*" {return'*';}"\/" {return'/';}"(" {return'(';}")" {return')';}";" {return';';}"{" {return'{';}"}" {return'}';}"[" {return'['; }"]" {return']';}Test.y:rel : expr '<' expr { printf("rel-->expr<expr\n"); } | expr LE expr { printf("rel-->expr<=expr\n"); }| expr GE expr { printf("rel-->expr>=expr\n"); } | expr '>' expr { printf("rel-->expr>expr\n"); }| expr { printf("rel-->expr\n"); };expr : expr '+' term { printf("expr-->expr+term\n"); } | expr '-' term { printf("expr-->expr-term\n"); }| term { printf("expr-->term\n"); };term : term '*' unary { printf("term-->term*unary\n"); }| term '/' unary { printf("term-->term/unary\n"); }| unary { printf("term-->unary\n"); };unary : '!' unary { printf("unary-->!unary\n"); }| '-' unary %prec UMINUS{ printf("unary-->-unary\n"); }| factor { printf("unary-->factor\n"); };factor : '('bool')' { printf("factor-->(bool)\n"); }| loc { printf("factor-->loc\n"); }| NUM { printf("factor-->num\n"); }| REAL { printf("factor-->real\n"); }| TRUE { printf("factor-->true\n"); }| FALSE { printf("factor-->false\n"); }Yacc⽣成部分代码:View Code#line 1334 "y.tab.c"yyvsp -= yylen;yyssp -= yylen;YY_STACK_PRINT (yyss, yyssp);*++yyvsp = yyval;/* Now `shift' the result of the reduction. Determine what statethat goes to, based on the state we popped back to and the rulenumber reduced by. */yyn = yyr1[yyn];yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate];elseyystate = yydefgoto[yyn - YYNTOKENS];goto yynewstate;/*------------------------------------.| yyerrlab -- here on detecting error |`------------------------------------*/yyerrlab:/* If not already recovering from an error, report this error. */if (!yyerrstatus){++yynerrs;#if YYERROR_VERBOSEyyn = yypact[yystate];if (YYPACT_NINF < yyn && yyn < YYLAST){YYSIZE_T yysize = 0;int yytype = YYTRANSLATE (yychar);const char* yyprefix;char *yymsg;int yyx;/* Start YYX at -YYN if negative to avoid negative indexes inYYCHECK. */int yyxbegin = yyn < 0 ? -yyn : 0;/* Stay within bounds of both yycheck and yytname. */int yychecklim = YYLAST - yyn;int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;int yycount = 0;yyprefix = ", expecting ";for (yyx = yyxbegin; yyx < yyxend; ++yyx)if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR){yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);yycount += 1;if (yycount == 5){yysize = 0;break;}}yysize += (sizeof ("syntax error, unexpected ")+ yystrlen (yytname[yytype]));yymsg = (char *) YYSTACK_ALLOC (yysize);if (yymsg != 0){char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");yyp = yystpcpy (yyp, yytname[yytype]);if (yycount < 5){yyprefix = ", expecting ";for (yyx = yyxbegin; yyx < yyxend; ++yyx)if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR){yyp = yystpcpy (yyp, yyprefix);yyp = yystpcpy (yyp, yytname[yyx]);yyprefix = " or ";}}yyerror (yymsg);YYSTACK_FREE (yymsg);}elseyyerror ("syntax error; also virtual memory exhausted");}else例如,程序⽚断{i = 2;while (i <=100){sum = sum + i;i = i + 2;}}(注:原本是在windwos环境下编程,最后到unix环境下,发现速度快了,灵活性⾼了,同时⽅便了很多。

编译原理实践yacc(sql查询语句解析)_概述说明

编译原理实践yacc(sql查询语句解析) 概述说明1. 引言1.1 概述本篇文章旨在介绍编译原理实践中使用Yacc工具对SQL查询语句进行解析的过程。

编译原理是计算机科学中的重要研究领域,主要涉及将高级语言转化为低级的机器语言,以便计算机能够理解和执行。

通过使用编译原理中的概念和技术,可以大大简化复杂语法的分析和解析过程,提高程序开发的效率。

1.2 文章结构本文共分为五个部分,每个部分都有其特定的内容和目标:- 引言:介绍本篇文章的背景和目的。

- 编译原理实践yacc:阐述编译原理及介绍Yacc工具在该领域中的应用。

- SQL查询语句解析过程:详细讲解SQL查询语句的基本结构、词法分析过程以及语法分析过程。

- Yacc工具的使用和配置:指导读者如何安装Yacc工具,并演示如何编写Yacc 源文件以及生成解析器代码并进行运行。

- 结论与展望:总结全文内容并提供未来可能的拓展方向。

1.3 目的本文目的在于通过对编译原理和Yacc工具在SQL查询语句解析中的应用进行介绍,帮助读者更好地理解编译原理的相关概念,并掌握使用Yacc工具进行语法分析和解析的方法。

通过实践演示和案例讲解,读者能够学会配置和使用Yacc 工具,并将其应用于自己感兴趣的领域。

以上为“1. 引言”部分内容的详细描述,请结合实际情况进行参考与调整。

2. 编译原理实践yacc2.1 什么是编译原理编译原理是计算机科学领域的一个重要分支,研究如何将高级程序语言转换为机器语言。

它涉及到编程语言的词法分析、语法分析和代码生成等多个方面。

通过编译原理,我们可以了解程序如何被解释和执行,从而能够更好地设计和优化程序。

2.2 Yacc介绍Yacc(Yet Another Compiler Compiler)是一款用于生成语法解析器的工具。

它是由AT&T贝尔实验室的Stephen C. Johnson在20世纪70年代开发的,并成为Unix操作系统环境下广泛使用的编译器工具之一。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验2.4 学习YACC并构造简单语法分析程序
一、实验目的
1. 学习使用辅助软件YACC
2. 理解语法分析程序的构造原理
二、实验内容
构造一个PL/0程序的命令行简易版本程序,要求具有变量和常量定义语句Var和Const,具有基本输入输出语句Read 和Write,包含基本的算术运算+ 、-、*、/ 和( ) 运算,语句以分号(;)结束,整个程序以END结束。

1. 学习YACC语法的使用
具体内容可参考课本附录
2. 使用LEX构造词法分析程序yylex.c
示例代码:
\+ {return '+';}
\* {return '*';}
":=" {return BECOMES;}
\, {return ',';}
\; {return ';';}
V AR|var {return V AR;}
[a-zA-Z][a-zA-Z0-9]* {strcpy(yylval.str,yytext);return IDENT;}
3. 使用YACC构造语法分析程序
构造符合YACC语法的程序PL0.YAC
PL0.YAC示例代码:
%union {
char str[MAXSTRLEN];
int num;
}
%token V AR CONST READ WRITE EXIT BECOMES
%token <num> NUMBER
%token <str> IDENT
%type <num> number
%type <str> ident
%type <num> expression
%left '+' '-'
%left '*' '/'
%left UMINUS
%%
begins : /*empty*/
| begins program
;
program : var_state ';'
| const_state ';'
| statement ';'
| error ';'
{
}
;
var_state : VAR var_list
{}
;
var_list : a_var_list
| var_list ',' a_var_list
{}
;
a_var_list : ident
{ i=position($1);
if (i) printf("Error: variable (%s) already defines \n",$1);
else { if (tx==MAXTABLESIZE)
printf("Error: table full(only%d numbers) ,varible define error \n",MAXTABLESIZE);
else {
strcpy(table[tx].name,$1);
table[tx].kind=V ARLABEL;
printf("variable (%d):%s successfullt defined.\n",tx,$1);
tx++;
}
}
}
;
statement : write_state
| read_state
| value_state
| exit_state ';'
write_state: WRITE '(' write_list ')'
{ if (debug) printf("(write_statement finished)\n");}
;
write_list : a_write
| write_list ',' a_write
;
a_write : expression
{ printf("%d\n",$1);}
%%
#include "lexyy.c"
int yyparse();
main()
{
return yyparse();
}
4. 生成目标代码并运行
1) 生成C语言源程序
在DOS 命令提示符下运行Y ACC.exe
YACC pl0.yac
产生C语言代码pl0.C
2)进入TC集成环境将.C文件编译产生可执行文件.EXE
TC pl0.C
3)在DOS 命令提示符下执行生成的pl0.exe
输入程序示例如下:
Const a =3 ;
Var b,c ;
Read(b);
c := a + b ;
Write(c) ;
END.
三、实验报告
按照语法分析的原理,给出借助Y ACC自动生成语法分析器的过程描述,和生成的语法分析程序是如何运作的。

四、思考题
1)YACC所依据的文法是什么?
2)察看YACC生成的源程序,理解自下而上分析方法的构造原理。

相关文档
最新文档