编译原理实验二 语法分析程序设计与实现

一、实验目的

任选一种有代表性的语法分析方法,如算符优先法、递归下降法、LL(1)、SLR(1)、LR(1)等,通过设计、编制、调试实现一个典型的语法分析程序,对实验一所得扫描器提供的单词序列进行语法检查和结构分析,实现并进一步掌握常用的语法分析方法。

二、基本实验内容与要求

选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的 BNF 定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。

G2[<算术表达式>]: <算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项> <项> → <因式> |<项><因式> | <项>/<因式> <因式> → <运算对象> | (<算术表达式>)
若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用 E、T、F 和 i 代表,则 G2 可写成:
G2[E]:E → T | E+T | E-T T → F | T
F | T/F F → i | (E)

输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ······
输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。
要求:
1、确定语法分析程序的流程图,同时考虑相应的数据结构,编写一个语法分析源程序。
2、将词法、语法分析合在一起构成一个完整的程序,并调试成功。3、供测试的例子应包括符合语法规则的语句,及分析程序能判别的若干错例。对于所输入的字符串,不论对错,都应有明确的信息输出。

采用SLR1分析方法,首先将给定文法的SLR1分析表手工画出,存入到程序中,然后进行语法分析程序的实现。
在这里插入图片描述

四、源程序

#include <iostream>
#include <string>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <stdio.h>
#include <cassert>
#include <vector>
//#define _CRT_SECURE_NO_WARNINGS
using namespace std;
/*
begin	BEGIN	1
end		END		2
if		IF		3
then	THEN	4
else	ELSE	5
while	WHILE	6
do		DO		7
标识符	ID		8
浮点常数UCON	9
<		LT		10
<=		LE		11
==		EQ		12
<>		NE		13
>		GT		14
>=		GE		15
=		IS		16
+		PL		17
-		MI		18
*		MU		19
/		DI		20
(		LP		21  新增加的左括号
)		RP		22  新增加的右括号
*/


const char* table1[] = {
    " ","begin","end","if","then","else","while","do" };
const char* table2[] = {
    " ","BEGIN","END","IF","THEN","ELSE","WHILE","DO","ID","UCON","LT","LE","EQ","NE","GT","GE","IS","PL","MI","MU","DI","LP","RP" };
char TOKEN[20];//用来依次存放一个单词词文中的各个字符。
char str[50];//存放词法分析后的表达式,将输入的表达式转变成只含有i和运算符的表达式
int len = 0;//词法分析后表达式的长度

//action表   char vt[8] = { '(',')','+','-','*','/','i','#' };
string action[16][8] = {
    {
   "s4","null","null" ,"null" ,"null","null","s5" , "null" },
					{
   "null","null","s6","s7","null","null","null","acc"},
					{
   "null","r3","r3","r3","s8","s9","null","r3"} ,
					{
   "null","r6","r6","r6","r6","r6","null","r6"},
					{
   "s4","null","null","null","null","null","s5","null"},
					{
   "null","r8","r8","r8","r8","r8","null","r8"},
					{
   "s4","null","null","null","null","null","s5","null"},
					{
   "s4","null","null","null","null","null","s5","null"},
					{
   "s4","null","null","null","null","null","s5","null"},
					{
   "s4","null","null","null","null","null","s5","null"},
					{
   "null","s15","s6","s7","null","null","null","null"} ,
					{
   "null","r1","r1","r1","s8","s9","null","r1"},
					{
   "null","r2","r2","r2","s8","s9","null","r2"} ,
					{
   "null","r4","r4","r4","r4","r4","null","r4"} ,
					{
   "null","r5","r5","r5","r5","r5","null","r5"} ,
					{
   "null","r7","r7"
  • 21
    点赞
  • 204
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
【问题描述】 请根据给定的文法设计并实现词法分析程序,从源程序中识别出单词,记录其单词类别和单词值,输入输出及处理要求如下: (1)数据结构和与语法分析程序的接口请自行定义;类别码需按下表格式统一定义; (2)为了方便进行自动评测,输入的被编译源文件统一命名为testfile.txt(注意不要写错文件名);输出的结果文件统一命名为output.txt(注意不要写错文件名),结果文件中每行按如下方式组织: 单词类别码 单词的字符/字符串形式(中间仅用一个空格间隔) 单词的类别码请统一按如下形式定义: 单词名称 类别码 单词名称 类别码 单词名称 类别码 单词名称 类别码 标识符 IDENFR else ELSETK - MINU = ASSIGN 整形常量 INTCON switch SWITCHTK * MULT ; SEMICN 字符常量 CHARCON case CASETK / DIV , COMMA 字符串 STRCON default DEFAULTTK < LSS ( LPARENT const CONSTTK while WHILETK GRE [ LBRACK char CHARTK scanf SCANFTK >= GEQ ] RBRACK void VOIDTK printf PRINTFTK == EQL { LBRACE main MAINTK return RETURNTK != NEQ } RBRACE if IFTK + PLUS : COLON 【输入形式】testfile.txt中的符合文法要求的测试程序。 【输出形式】要求将词法分析结果输出至output.txt中。 【特别提醒】(1)读取的字符串要原样保留着便于输出,特别是数字,这里输出的并不是真正的单词值,其实是读入的字符串,单词值需另行记录。 (2)本次作业只考核对正确程序的处理,但需要为今后可能出现的错误情况预留接口。 (3)在今后的错误处理作业中,需要输出错误的行号,在词法分析的时候注意记录该信息。 (4)单词的类别和单词值以及其他关注的信息,在词法分析阶段获取后,后续的分析阶段会使用,请注意记录;当前要求的输出只是为了便于评测,完成编译器中无需出现这些信息,请设计为方便打开/关闭这些输出的方案。 【文法定义】请到“2020年文法定义(用于查看文法,不计入成绩)”作业中查看文法 【样例输入】 coNst int cONst1 = 001, const2 = -100; const char const3 = '_'; int change1; char change3; int gets1(int var1,int var2){ change1 = var1 + var2; return (change1); } void main(){ printf("Hello World"); printf(gets1(10, 20)); } 【样例输出】 CONSTTK coNst INTTK int IDENFR cONst1 ASSIGN = INTCON 001 COMMA , IDENFR const2 ASSIGN = MINU - INTCON 100 SEMICN ; CONSTTK const CHARTK char IDENFR const3 ASSIGN = CHARCON _ SEMICN ; INTTK int IDENFR change1 SEMICN ; CHARTK char IDENFR change3 SEMICN ; INTTK int IDENFR gets1 LPARENT ( INTTK int IDENFR var1 COMMA , INTTK int IDENFR var2 RPARENT ) LBRACE { IDENFR change1 ASSIGN = IDENFR var1 PLUS + IDENFR var2 SEMICN ; RETURNTK return LPARENT ( IDENFR change1 RPARENT ) SEMICN ; RBRACE } VOIDTK void MAINTK main LPARENT ( RPARENT ) LBRACE { PRINTFTK printf LPARENT ( STRCON Hello World RPARENT ) SEMICN ; PRINT
语法分析编译原理中的重要部分,它的作用是将词法分析阶段得到的词法单元序列转换成抽象语法树(AST)或语法分析树(Parse Tree),以便于后续的语义分析、中间代码生成和目标代码生成等环节的进行。在本次实验中,我们将使用Java语言实现一个简单的语法分析器。 实验要求: 1. 实现自顶向下的递归下降分析器。 2. 支持的文法如下: ``` <program> ::= <stmts_list> <stmts_list> ::= <stmt> | <stmts_list> <stmt> <stmt> ::= <if_stmt> | <while_stmt> | <assign_stmt> <if_stmt> ::= if <condition> then <stmts_list> end <while_stmt> ::= while <condition> do <stmts_list> end <assign_stmt> ::= <id> = <expr> <condition> ::= <expr> <relop> <expr> <expr> ::= <term> | <expr> <addop> <term> <term> ::= <factor> | <term> <mulop> <factor> <factor> ::= <id> | <number> | '(' <expr> ')' <relop> ::= '<' | '>' | '=' | '<=' | '>=' | '<>' <addop> ::= '+' | '-' <mulop> ::= '*' | '/' <id> ::= <letter> | <id> <letter> | <id> <digit> <number> ::= <digit> | <number> <digit> <letter> ::= A | B | ... | Z | a | b | ... | z <digit> ::= 0 | 1 | ... | 9 ``` 注意:文法中的关键字 if、then、end、while、do、and 等均为保留字。 3. 实现语法分析器应具备以下功能: - 能够识别出语法正确的程序,并输出相应的语法分析树或抽象语法树。 - 能够识别出语法错误的程序,并给出相应的错误提示信息。 - 能够处理注释和空格等无意义的字符。 4. 实验提交要求: - 实验报告,包括程序设计实验结果分析。 - 程序源代码。 实验设计思路: 1. 根据给定的文法,设计语法分析器的语法规则和对应的产生式。 2. 编写相应的Java代码,将文法转换为递归下降分析器所需要的形式。 3. 实现从输入的源代码中读取词法单元序列的功能。 4. 实现递归下降分析器的核心算法,对输入的词法单元序列进行语法分析,并构建相应的语法分析树或抽象语法树。 5. 在语法分析过程中,需要处理注释和空格等无意义的字符,以便于正确识别语法错误。 6. 在语法分析过程中,需要对输入的源代码进行错误检查,并给出相应的错误提示信息。 7. 输出语法分析树或抽象语法树,以便于后续的语义分析、中间代码生成和目标代码生成等环节的进行。 实验结果分析: 经过实验测试,我们的语法分析器能够正确地识别出合法的程序,并输出相应的语法分析树或抽象语法树。同时,它也能够正确地识别出语法错误的程序,并给出相应的错误提示信息。总的来说,本次实验取得了较好的实验效果。 实验源代码: 见下方代码框:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值