LR(1)文法为什么不能解析表达文法c++

&>&编译原理LR(1)文法分析器
编译原理LR(1)文法分析器
上传大小:9KB
C语言实现的编译原理LR(1)文法分析器,VC++6.0开发
综合评分:3.9(9位用户评分)
下载个数:
{%username%}回复{%com_username%}{%time%}\
/*点击出现回复框*/
$(".respond_btn").on("click", function (e) {
$(this).parents(".rightLi").children(".respond_box").show();
e.stopPropagation();
$(".cancel_res").on("click", function (e) {
$(this).parents(".res_b").siblings(".res_area").val("");
$(this).parents(".respond_box").hide();
e.stopPropagation();
/*删除评论*/
$(".del_comment_c").on("click", function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_invalid/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parents(".conLi").remove();
alert(data.msg);
$(".res_btn").click(function (e) {
var q = $("#form1").serializeArray();
console.log(q);
var res_area_r = $.trim($(".res_area_r").val());
if (res_area_r == '') {
$(".res_text").css({color: "red"});
$.post("/index.php/comment/do_comment_reply/", q,
function (data) {
if (data.succ == 1) {
var $target,
evt = e || window.
$target = $(evt.target || evt.srcElement);
var $dd = $target.parents('dd');
var $wrapReply = $dd.find('.respond_box');
console.log($wrapReply);
var mess = $(".res_area_r").val();
var str = str.replace(/{%header%}/g, data.header)
.replace(/{%href%}/g, 'http://' + window.location.host + '/user/' + data.username)
.replace(/{%username%}/g, data.username)
.replace(/{%com_username%}/g, _username)
.replace(/{%time%}/g, data.time)
.replace(/{%id%}/g, data.id)
.replace(/{%mess%}/g, mess);
$dd.after(str);
$(".respond_box").hide();
$(".res_area_r").val("");
$(".res_area").val("");
$wrapReply.hide();
alert(data.msg);
}, "json");
/*删除回复*/
$(".rightLi").on("click",'.del_comment_r', function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_comment_del/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parent().parent().parent().parent().parent().remove();
$(e.target).parents('.res_list').remove()
alert(data.msg);
//填充回复
function KeyP(v) {
$(".res_area_r").val($.trim($(".res_area").val()));
评论共有4条
对我的课程设计有点帮助,可以参考一下。谢谢
还不错,不过这个是给定文法的,不是我要找的
可用于原理学习和编程参考
非常好,思路很清晰,符合我的要求,谢谢!
审核通过送C币
10个C/ C++小游戏项目实战
创建者:ydpawx
6套慕课网算法视频教程
创建者:love
VS2010趣味编程视频教程
创建者:ouyongke
上传者其他资源上传者专辑
Best Practices for Performance
Multi Window Android PPT
laoluo资料
org.eclipse.e4.ui.workbench_0.11.0.v758.ja
APUE2nd edition
课程资源热门标签
VIP会员动态
CSDN下载频道资源及相关规则调整公告V11.10
下载频道用户反馈专区
下载频道积分规则调整V1710.18
spring mvc+mybatis+mysql+maven+bootstrap 整合实现增删查改简单实例.zip
资源所需积分/C币
当前拥有积分
当前拥有C币
为了良好体验,不建议使用迅雷下载
编译原理LR(1)文法分析器
会员到期时间:
剩余下载个数:
剩余C币:593
剩余积分:0
为了良好体验,不建议使用迅雷下载
积分不足!
资源所需积分/C币
当前拥有积分
您可以选择
程序员的必选
绿色安全资源
资源所需积分/C币
当前拥有积分
当前拥有C币
(仅够下载10个资源)
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
您的积分不足,将扣除 10 C币
为了良好体验,不建议使用迅雷下载
你当前的下载分为234。
你还不是VIP会员
开通VIP会员权限,免积分下载
你下载资源过于频繁,请输入验证码
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
若举报审核通过,可奖励20下载分
被举报人:
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
编译原理LR(1)文法分析器本程序实现一个分析C语言的词法分析+语法分析。
1.文法简略,没有实现的部分,可以在此文法的基础上进行扩充,本程序的采用自顶向下的LL(1)文法。
2.可以自动实现求First 集和 Follow 集。
3.处终结符外(有些硬编码的成分),终结符的文法可以自定义,也就是说读者可以自定义文法。
4.为方便理解,C语言的文法描述写成中文。
5.程序将词法分析和语法分析结合起来,词法分析的结果作为语法分析的输入。
6.最终结果在控制台显示的有:词法分析、First集、Follow集、Select集,在preciateResult.txt 中写入了语法分析结果,在preciateTable.txt 中写入了预测分析表。
7.文法的词素之间必须有空格分开。
项目结构如下:
文法如下:
wenfa.txt:
&函数定义& -& &修饰词闭包& &类型& &变量& ( &参数声明& ) { &函数块& }
&修饰词闭包& -& &修饰词& &修饰词闭包& | $
&修饰词& -& describe
&类型& -& type &取地址&
&取地址& -& &星号闭包&
&星号闭包& -& &星号& &星号闭包& | $
&星号& -& *
&变量& -& &标志符& &数组下标&
&标志符& -& id
&数组下标& -& [ &因式& ] | $
&因式& -& ( &表达式& ) | &变量& | &数字&
&数字& -& digit
&表达式& -& &因子& &项&
&因子& -& &因式& &因式递归&
&因式递归& -& * &因式& &因式递归& | / &因式& &因式递归& | $
&项& -& + &因子& &项& | - &因子& &项& | $
&参数声明& -& &声明& &声明闭包& | $
&声明& -& &修饰词闭包& &类型& &变量& &赋初值&
&赋初值& -& = &右值& | $
&右值& -& &表达式& | { &多个数据& }
&多个数据& -& &数字& &数字闭包&
&数字闭包& -& , &数字& &数字闭包& | $
&声明闭包& -& , &声明& &声明闭包& | $
&函数块& -& &声明语句闭包& &函数块闭包&
&声明语句闭包& -& &声明语句& &声明语句闭包& | $
&声明语句& -& &声明& ;
&函数块闭包& -& &赋值函数& &函数块闭包& | &for循环& &函数块闭包& | &条件语句& &函数块闭包& | &函数返回& &函数块闭包& | $
&赋值函数& -& &变量& &赋值或函数调用&
&赋值或函数调用& -& = &右值& ; | ( &参数列表& ) ;
&参数列表& -& &参数& &参数闭包&
&参数闭包& -& , &参数& &参数闭包& | $
&参数& -& &标志符& | &数字& | &字符串&
&字符串& -& string
&for循环& -& for ( &赋值函数& &逻辑表达式& ; &后缀表达式& ) { &函数块& }
&逻辑表达式& -& &表达式& &逻辑运算符& &表达式&
&逻辑运算符& -& & | & | == | !=
&后缀表达式& -& &变量& &后缀运算符&
&后缀运算符& -& ++ | --
&条件语句& -& if ( &逻辑表达式& ) { &函数块& } &否则语句&
&否则语句& -& else { &函数块& } | $
&函数返回& -& return &因式& ;
词法分析头文件:
LexAnalysis.h
//LexAnalysis.h
#ifndef _LEXANALYSIS_H
#define _LEXANALYSIS_H
#define AUTO 1
#define BREAK 2
#define CASE 3
#define CHAR 4
#define CONST 5
#define CONTINUE 6
#define DEFAULT 7
#define DO 8
#define DOUBLE 9
#define ELSE 10
#define ENUM 11
#define EXTERN 12
#define FLOAT 13
#define FOR 14
#define GOTO 15
#define IF 16
#define INT 17
#define LONG 18
#define REGISTER 19
#define RETURN 20
#define SHORT 21
#define SIGNED 22
#define SIZEOF 23
#define STATIC 24
#define STRUCT 25
#define SWITCH 26
#define TYPEDEF 27
#define UNION 28
#define UNSIGNED 29
#define VOID 30
#define VOLATILE 31
#define WHILE 32
#define KEY_DESC &关键字&
#define IDENTIFER 40
#define IDENTIFER_DESC &标志符&
#define INT_VAL 51 //整形常量
#define CHAR_VAL 52 //字符常量
#define FLOAT_VAL 53 //浮点数常量
#define STRING_VAL 54 //双精度浮点数常量
#define MACRO_VAL 55 //宏常量
#define CONSTANT_DESC &常量&
#define NOT 61
#define BYTE_AND 62 //&
#define COMPLEMENT 63 // ~
#define BYTE_XOR
#define MUL 65 // *
#define DIV 66// /
#define MOD 67 // %
#define ADD 68 // +
#define SUB 69 // -
#define LES_THAN 70 // &
#define GRT_THAN 71 // &
#define ASG 72 // =
#define ARROW 73 // -&
#define SELF_ADD 74 // ++
#define SELF_SUB 75 // --
#define LEFT_MOVE 76 // &&
#define RIGHT_MOVE 77 // &&
#define LES_EQUAL 78 // &=
#define GRT_EQUAL 79 // &=
#define EQUAL 80 // ==
#define NOT_EQUAL 81 // !=
#define AND 82 // &&
#define OR 83 // ||
#define COMPLETE_ADD 84 // +=
#define COMPLETE_SUB 85 // -=
#define COMPLETE_MUL 86 // *=
#define COMPLETE_DIV 87 // /=
#define COMPLETE_BYTE_XOR 88 // ^=
#define COMPLETE_BYTE_AND 89 // &=
#define COMPLETE_COMPLEMENT 90 // ~=
#define COMPLETE_MOD 91 //%=
#define BYTE_OR 92 // |
#define OPE_DESC &运算符&
#define LEFT_BRA 100 // (
#define RIGHT_BRA 101 // )
#define LEFT_INDEX 102 // [
#define RIGHT_INDEX 103 // ]
#define L_BOUNDER 104 //
#define R_BOUNDER 105 // }
#define POINTER 106 // .
#define JING 107 // #
#define UNDER_LINE 108 // _
#define COMMA 109 // ,
#define SEMI 110 // ;
#define SIN_QUE 111 // '
#define DOU_QUE 112 // &
#define CLE_OPE_DESC &限界符&
#define NOTE1 120 // &/**/&注释
#define NOTE2 121 // &//&注释
#define NOTE_DESC &注释&
#define HEADER 130 //头文件
#define HEADER_DESC &头文件&
//错误类型
#define FLOAT_ERROR &float表示错误&
#define FLOAT_ERROR_NUM 1
#define DOUBLE_ERROR &double表示错误&
#define DOUBLE_ERROR_NUM 2
#define NOTE_ERROR &注释没有结束符&
#define NOTE_ERROR_NUM 3
#define STRING_ERROR &字符串常量没有结束符&
#define STRING_ERROR_NUM 4
#define CHARCONST_ERROR &字符常量没有结束符&
#define CHARCONST_ERROR_NUM 5
#define CHAR_ERROR &非法字符&
#define CHAR_ERROR_NUM 6
#define LEFT_BRA_ERROR &'('没有对应项&
#define LEFT_BRA_ERROR_NUM 7
#define RIGHT_BRA_ERROR &')'没有对应项&
#define RIGHT_BRA_ERROR_NUM 8
#define LEFT_INDEX_ERROR &'['没有对应项&
#define LEFT_INDEX_ERROR_NUM 9
#define RIGHT_INDEX_ERROR &']'没有对应项&
#define RIGHT_INDEX_ERROR_NUM 10
#define L_BOUNDER_ERROR &'{'没有对应项&
#define L_BOUNDER_ERROR_NUM 11
#define R_BOUNDER_ERROR &'}'没有对应项&
#define R_BOUNDER_ERROR_NUM 12
#define PRE_PROCESS_ERROR &预处理错误& //头文件或者宏定义错误
#define PRE_PROCESS_ERROR_NUM
#define _NULL &无&
#define DESCRIBE 4000
#define TYPE 4001
#define STRING 4002
#define DIGIT 4003
struct NormalNode
char content[30];//内容
char describe[30];//描述
//入口地址
//所在行数
NormalNode *//下一个节点
void initKeyMapping();
void initOperMapping();
void initLimitMapping();
void initNode();
void createNewNode(char * content,char *descirbe,int type,int addr,int line);
void createNewError(char * content,char *descirbe,int type,int line);
int createNewIden(char * content,char *descirbe,int type,int addr,int line);
void printNodeLink();
void printErrorLink();
void printIdentLink();
int mystrlen(char * word);
void preProcess(char * word,int line);
void close();
int seekKey(char * word);
void scanner();
void BraMappingError();
语法分析头文件:
SynAnalysis.h
//SynAnalysis.h
#ifndef _SYNANALYSIS_H
#define _SYNANALYSIS_H
#define GRAMMAR_ARROW 2000 //-&
#define GRAMMAR_OR 2001 // |
#define GRAMMAR_NULL 2002 //空值
#define GRAMMAR_SPECIAL 2003 //特殊符号#
#define GRAMMAR_BASE 2010 //动态生成的基值
#define Stack_Size 5000
typedef struct
int elem[Stack_Size];
void initGrammer();
int seekCodeNum(char * word);
void ceshi();
void First();
void Follow();
void Select();
void MTable();
void Analysis();
词法分析Cpp文件:(与先前写过的一片博客相类似,改了部分)
LexAnalysis.cpp
//LexAnalysis.cpp
#include &iostream&
#include &fstream&
#include &stdio.h&
#include &stdlib.h&
#include &string.h&
#include &vector&
#include &iomanip&
#include &LexAnalysis.h&
int leftSmall = 0;//左小括号
int rightSmall = 0;//右小括号
int leftMiddle = 0;//左中括号
int rightMiddle = 0;//右中括号
int leftBig = 0;//左大括号
int rightBig = 0;//右大括号
int lineBra[6][1000] = {0};//括号和行数的对应关系,第一维代表左右6种括号
int static_iden_number = 0;//模拟标志符的地址,自增
//Token节点
NormalNode * normalH//首结点
//错误节点
struct ErrorNode
char content[30];//错误内容
char describe[30];//错误描述
//所在行数
ErrorNode *//下一个节点
ErrorNode * errorH//首节点
//标志符节点
struct IdentiferNode
char content[30];//内容
char describe[30];//描述
//入口地址
//所在行数
IdentiferNode *//下一个节点
IdentiferNode * idenH//首节点
vector&pair&const char *,int& & keyM
vector&pair&const char *,int& & operM
vector&pair&const char *,int& & limitM
//初始化C语言的关键字的集合
void initKeyMapping()
keyMap.clear();
keyMap.push_back(make_pair(&auto&,AUTO));
keyMap.push_back(make_pair(&break&,BREAK));
keyMap.push_back(make_pair(&case&,CASE));
keyMap.push_back(make_pair(&char&,CHAR));
keyMap.push_back(make_pair(&const&,CONST));
keyMap.push_back(make_pair(&continue&,CONTINUE));
keyMap.push_back(make_pair(&default&,DEFAULT));
keyMap.push_back(make_pair(&do&,DO));
keyMap.push_back(make_pair(&double&,DOUBLE));
keyMap.push_back(make_pair(&else&,ELSE));
keyMap.push_back(make_pair(&enum&,ENUM));
keyMap.push_back(make_pair(&extern&,EXTERN));
keyMap.push_back(make_pair(&float&,FLOAT));
keyMap.push_back(make_pair(&for&,FOR));
keyMap.push_back(make_pair(&goto&,GOTO));
keyMap.push_back(make_pair(&if&,IF));
keyMap.push_back(make_pair(&int&,INT));
keyMap.push_back(make_pair(&long&,LONG));
keyMap.push_back(make_pair(&register&,REGISTER));
keyMap.push_back(make_pair(&return&,RETURN));
keyMap.push_back(make_pair(&short&,SHORT));
keyMap.push_back(make_pair(&signed&,SIGNED));
keyMap.push_back(make_pair(&sizeof&,SIZEOF));
keyMap.push_back(make_pair(&static&,STATIC));
keyMap.push_back(make_pair(&struct&,STRUCT));
keyMap.push_back(make_pair(&switch&,SWITCH));
keyMap.push_back(make_pair(&typedef&,TYPEDEF));
keyMap.push_back(make_pair(&union&,UNION));
keyMap.push_back(make_pair(&unsigned&,UNSIGNED));
keyMap.push_back(make_pair(&void&,VOID));
keyMap.push_back(make_pair(&volatile&,VOLATILE));
keyMap.push_back(make_pair(&while&,WHILE));
keyMap.push_back(make_pair(&describe&,DESCRIBE));
keyMap.push_back(make_pair(&type&,TYPE));
keyMap.push_back(make_pair(&string&,STRING));
keyMap.push_back(make_pair(&digit&,DIGIT));
void initOperMapping()
operMap.clear();
operMap.push_back(make_pair(&!&,NOT));
operMap.push_back(make_pair(&&&,BYTE_AND));
operMap.push_back(make_pair(&~&,COMPLEMENT));
operMap.push_back(make_pair(&^&,BYTE_XOR));
operMap.push_back(make_pair(&*&,MUL));
operMap.push_back(make_pair(&/&,DIV));
operMap.push_back(make_pair(&%&,MOD));
operMap.push_back(make_pair(&+&,ADD));
operMap.push_back(make_pair(&-&,SUB));
operMap.push_back(make_pair(&&&,LES_THAN));
operMap.push_back(make_pair(&&&,GRT_THAN));
operMap.push_back(make_pair(&=&,ASG));
operMap.push_back(make_pair(&-&&,ARROW));
operMap.push_back(make_pair(&++&,SELF_ADD));
operMap.push_back(make_pair(&--&,SELF_SUB));
operMap.push_back(make_pair(&&&&,LEFT_MOVE));
operMap.push_back(make_pair(&&&&,RIGHT_MOVE));
operMap.push_back(make_pair(&&=&,LES_EQUAL));
operMap.push_back(make_pair(&&=&,GRT_EQUAL));
operMap.push_back(make_pair(&==&,EQUAL));
operMap.push_back(make_pair(&!=&,NOT_EQUAL));
operMap.push_back(make_pair(&&&&,AND));
operMap.push_back(make_pair(&||&,OR));
operMap.push_back(make_pair(&+=&,COMPLETE_ADD));
operMap.push_back(make_pair(&-=&,COMPLETE_SUB));
operMap.push_back(make_pair(&*=&,COMPLETE_MUL));
operMap.push_back(make_pair(&/=&,COMPLETE_DIV));
operMap.push_back(make_pair(&^=&,COMPLETE_BYTE_XOR));
operMap.push_back(make_pair(&&=&,COMPLETE_BYTE_AND));
operMap.push_back(make_pair(&~=&,COMPLETE_COMPLEMENT));
operMap.push_back(make_pair(&%=&,COMPLETE_MOD));
operMap.push_back(make_pair(&|&,BYTE_OR));
void initLimitMapping()
limitMap.clear();
limitMap.push_back(make_pair(&(&,LEFT_BRA));
limitMap.push_back(make_pair(&)&,RIGHT_BRA));
limitMap.push_back(make_pair(&[&,LEFT_INDEX));
limitMap.push_back(make_pair(&]&,RIGHT_INDEX));
limitMap.push_back(make_pair(&{&,L_BOUNDER));
limitMap.push_back(make_pair(&}&,R_BOUNDER));
limitMap.push_back(make_pair(&.&,POINTER));
limitMap.push_back(make_pair(&#&,JING));
limitMap.push_back(make_pair(&_&,UNDER_LINE));
limitMap.push_back(make_pair(&,&,COMMA));
limitMap.push_back(make_pair(&;&,SEMI));
limitMap.push_back(make_pair(&'&,SIN_QUE));
limitMap.push_back(make_pair(&\&&,DOU_QUE));
void initNode()
normalHead = new NormalNode();
strcpy(normalHead-&content,&&);
strcpy(normalHead-&describe,&&);
normalHead-&type = -1;
normalHead-&addr = -1;
normalHead-&line = -1;
normalHead-&next = NULL;
errorHead = new ErrorNode();
strcpy(errorHead-&content,&&);
strcpy(errorHead-&describe,&&);
errorHead-&line = -1;
errorHead-&next = NULL;
idenHead = new IdentiferNode();
strcpy(idenHead-&content,&&);
strcpy(idenHead-&describe,&&);
idenHead-&type = -1;
idenHead-&addr = -1;
idenHead-&line = -1;
idenHead-&next = NULL;
void createNewNode(char * content,char *descirbe,int type,int addr,int line)
NormalNode * p = normalH
NormalNode * temp = new NormalNode();
while(p-&next!=NULL)
strcpy(temp-&content,content);
strcpy(temp-&describe,descirbe);
temp-&type =
temp-&addr =
temp-&line =
temp-&next = NULL;
void createNewError(char * content,char *descirbe,int type,int line)
ErrorNode * p = errorH
ErrorNode * temp = new ErrorNode();
strcpy(temp-&content,content);
strcpy(temp-&describe,descirbe);
temp-&type =
temp-&line =
temp-&next = NULL;
while(p-&next!=NULL)
//返回值是新的标志符的入口地址
int createNewIden(char * content,char *descirbe,int type,int addr,int line)
IdentiferNode * p = idenH
IdentiferNode * temp = new IdentiferNode();
int flag = 0;
int addr_temp = -2;
while(p-&next!=NULL)
if(strcmp(content,p-&next-&content) == 0)
addr_temp = p-&next-&
if(flag == 0)
addr_temp = ++static_iden_//用自增来模拟入口地址
strcpy(temp-&content,content);
strcpy(temp-&describe,descirbe);
temp-&type =
temp-&addr = addr_
temp-&line =
temp-&next = NULL;
return addr_
void printNodeLink()
NormalNode * p = normalH
cout&&&************************************分析表******************************&&&endl&&
cout&&setw(30)&&&内容&&&setw(10)&&&描述&&&&\t&&&&种别码&&&&\t&&&&地址&&&&\t&&&&行号&&&
while(p!=NULL)
if(p-&type == IDENTIFER)
cout&&setw(30)&&p-&content&&setw(10)&&p-&describe&&&\t&&&p-&type&&&\t&&&p-&addr&&&\t&&&p-&line&&
cout&&setw(30)&&p-&content&&setw(10)&&p-&describe&&&\t&&&p-&type&&&\t&&&&\t&&&p-&line&&
cout&&endl&&
错误种类:
1.float表示错误
2.double表示错误
3.注释没有结束符
4.字符串常量没有结束符
5.字符常量没有结束符
6.非法字符
7.'('没有对应项
8.预处理错误
void printErrorLink()
ErrorNode * p = errorH
cout&&&************************************错误表******************************&&&endl&&
cout&&setw(10)&&&内容&&&setw(30)&&&描述&&&&\t&&&&类型&&&&\t&&&&行号&&&
while(p!=NULL)
cout&&setw(10)&&p-&content&&setw(30)&&p-&describe&&&\t&&&p-&type&&&\t&&&p-&line&&
cout&&endl&&
//标志符表,有重复部分,暂不考虑
void printIdentLink()
IdentiferNode * p = idenH
cout&&&************************************标志符表******************************&&&endl&&
cout&&setw(30)&&&内容&&&setw(10)&&&描述&&&&\t&&&&种别码&&&&\t&&&&地址&&&&\t&&&&行号&&&
while(p!=NULL)
cout&&setw(30)&&p-&content&&setw(10)&&p-&describe&&&\t&&&p-&type&&&\t&&&p-&addr&&&\t&&&p-&line&&
cout&&endl&&
int mystrlen(char * word)
if(*word == '\0')
return 1+mystrlen(word+1);
//预处理,处理头文件和宏定义
void preProcess(char * word,int line)
const char * include_temp = &include&;
const char * define_temp = &define&;
char * p_include,*p_
int flag = 0;
p_include = strstr(word,include_temp);
if(p_include!=NULL)
for(i=7;;)
if(*(p_include+i) == ' ' || *(p_include+i) == '\t')
createNewNode(p_include+i,HEADER_DESC,HEADER,-1,line);
p_define = strstr(word,define_temp);
if(p_define!=NULL)
for(i=7;;)
if(*(p_define+i) == ' ' || *(p_define+i) == '\t')
createNewNode(p_define+i,CONSTANT_DESC,MACRO_VAL,-1,line);
if(flag == 0)
createNewError(word,PRE_PROCESS_ERROR,PRE_PROCESS_ERROR_NUM,line);
void close()
//delete idenH
//delete errorH
//delete normalH
int seekKey(char * word)
for(int i=0; i&keyMap.size(); i++)
if(strcmp(word,keyMap[i].first) == 0)
return i+1;
return IDENTIFER;
void scanner()
char filename[30];
char array[30];//单词长度上限是30
int line = 1;//行数
printf(&请输入要进行语法分析的C语言程序:\n&);
scanf(&%s&,filename);
infile = fopen(filename,&r&);
while(!infile)
printf(&打开文件失败!\n&);
ch = fgetc(infile);
while(ch!=EOF)
//以字母或者下划线开头,处理关键字或者标识符
if((ch&='A' && ch&='Z') || (ch&='a' && ch&='z') || ch == '_')
while((ch&='A' && ch&='Z')||(ch&='a' && ch&='z')||(ch&='0' && ch&='9') || ch == '_')
array[i++] =
ch = fgetc(infile);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
int seekTemp = seekKey(word);
if(seekTemp!=IDENTIFER)
createNewNode(word,KEY_DESC,seekTemp,-1,line);
int addr_tmp = createNewIden(word,IDENTIFER_DESC,seekTemp,-1,line);
createNewNode(word,IDENTIFER_DESC,seekTemp,addr_tmp,line);
fseek(infile,-1L,SEEK_CUR);//向后回退一位
//以数字开头,处理数字
else if(ch &='0' && ch&='9')
int flag = 0;
int flag2 = 0;
//处理整数
while(ch &='0' && ch&='9')
array[i++] =
ch = fgetc(infile);
//处理float
if(ch == '.')
flag2 = 1;
array[i++] =
ch = fgetc(infile);
if(ch&='0' && ch&='9')
while(ch&='0' && ch&='9')
array[i++] =
ch = fgetc(infile);
//处理Double
if(ch == 'E' || ch == 'e')
array[i++] =
ch = fgetc(infile);
if(ch == '+' || ch == '-')
array[i++] =
ch = fgetc(infile);
if(ch &='0' && ch&='9')
array[i++] =
ch = fgetc(infile);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
if(flag == 1)
createNewError(word,FLOAT_ERROR,FLOAT_ERROR_NUM,line);
else if(flag == 2)
createNewError(word,DOUBLE_ERROR,DOUBLE_ERROR_NUM,line);
if(flag2 == 0)
createNewNode(word,CONSTANT_DESC,INT_VAL,-1,line);
createNewNode(word,CONSTANT_DESC,FLOAT_VAL,-1,line);
fseek(infile,-1L,SEEK_CUR);//向后回退一位
//以&/&开头
else if(ch == '/')
ch = fgetc(infile);
//处理运算符&/=&
if(ch == '=')
createNewNode(&/=&,OPE_DESC,COMPLETE_DIV,-1,line);
//处理&/**/&型注释
else if(ch == '*')
fgetc(infile);
while(ch != '*')
if(ch == '\n')
ch = fgetc(infile);
if(ch == EOF)
createNewError(_NULL,NOTE_ERROR,NOTE_ERROR_NUM,line);
ch = fgetc(infile);
if(ch == '/')
if(ch == EOF)
createNewError(_NULL,NOTE_ERROR,NOTE_ERROR_NUM,line);
createNewNode(_NULL,NOTE_DESC,NOTE1,-1,line);
//处理&//&型注释
else if(ch == '/')
while(ch!='\n')
ch = fgetc(infile);
if(ch == EOF)
createNewNode(_NULL,NOTE_DESC,NOTE2,-1,line);
createNewNode(_NULL,NOTE_DESC,NOTE2,-1,line);
if(ch == EOF)
//处理除号
createNewNode(&/&,OPE_DESC,DIV,-1,line);
//处理常量字符串
else if(ch == '&')
createNewNode(&\&&,CLE_OPE_DESC,DOU_QUE,-1,line);
ch = fgetc(infile);
while(ch!='&')
array[i++] =
if(ch == '\n')
ch = fgetc(infile);
if(ch == EOF)
createNewError(_NULL,STRING_ERROR,STRING_ERROR_NUM,line);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
createNewNode(word,CONSTANT_DESC,STRING_VAL,-1,line);
createNewNode(&\&&,CLE_OPE_DESC,DOU_QUE,-1,line);
//处理常量字符
else if(ch == '\'')
createNewNode(&\'&,CLE_OPE_DESC,SIN_QUE,-1,line);
ch = fgetc(infile);
while(ch!='\'')
array[i++] =
if(ch == '\n')
ch = fgetc(infile);
if(ch == EOF)
createNewError(_NULL,CHARCONST_ERROR,CHARCONST_ERROR_NUM,line);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
createNewNode(word,CONSTANT_DESC,CHAR_VAL,-1,line);
createNewNode(&\'&,CLE_OPE_DESC,SIN_QUE,-1,line);
else if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
if(ch == '\n')
if(ch == EOF)
//处理头文件和宏常量(预处理)
else if(ch == '#')
while(ch!='\n' && ch!=EOF)
array[i++] =
ch = fgetc(infile);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
preProcess(word,line);
fseek(infile,-1L,SEEK_CUR);//向后回退一位
//处理-开头的运算符
else if(ch == '-')
array[i++] =
ch = fgetc(infile);
if(ch &='0' && ch&='9')
int flag = 0;
int flag2 = 0;
//处理整数
while(ch&='0' && ch&='9')
array[i++] =
ch = fgetc(infile);
//处理float
if(ch == '.')
flag2 = 1;
array[i++] =
ch = fgetc(infile);
if(ch&='0' && ch&='9')
while(ch&='0' && ch&='9')
array[i++] =
ch = fgetc(infile);
//处理Double
if(ch == 'E' || ch == 'e')
array[i++] =
ch = fgetc(infile);
if(ch == '+' || ch == '-')
array[i++] =
ch = fgetc(infile);
if(ch &='0' && ch&='9')
array[i++] =
ch = fgetc(infile);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
if(flag == 1)
createNewError(word,FLOAT_ERROR,FLOAT_ERROR_NUM,line);
else if(flag == 2)
createNewError(word,DOUBLE_ERROR,DOUBLE_ERROR_NUM,line);
if(flag2 == 0)
createNewNode(word,CONSTANT_DESC,INT_VAL,-1,line);
createNewNode(word,CONSTANT_DESC,FLOAT_VAL,-1,line);
fseek(infile,-1L,SEEK_CUR);//向后回退一位
else if(ch == '&')
createNewNode(&-&&,OPE_DESC,ARROW,-1,line);
else if(ch == '-')
createNewNode(&--&,OPE_DESC,SELF_SUB,-1,line);
else if(ch == '=')
createNewNode(&--&,OPE_DESC,SELF_SUB,-1,line);
createNewNode(&-&,OPE_DESC,SUB,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理+开头的运算符
else if(ch == '+')
ch = fgetc(infile);
if(ch == '+')
createNewNode(&++&,OPE_DESC,SELF_ADD,-1,line);
else if(ch == '=')
createNewNode(&+=&,OPE_DESC,COMPLETE_ADD,-1,line);
createNewNode(&+&,OPE_DESC,ADD,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理*开头的运算符
else if(ch == '*')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&*=&,OPE_DESC,COMPLETE_MUL,-1,line);
createNewNode(&*&,OPE_DESC,MUL,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理按^开头的运算符
else if(ch == '^')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&^=&,OPE_DESC,COMPLETE_BYTE_XOR,-1,line);
createNewNode(&^&,OPE_DESC,BYTE_XOR,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理%开头的运算符
else if(ch == '%')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&%=&,OPE_DESC,COMPLETE_MOD,-1,line);
createNewNode(&%&,OPE_DESC,MOD,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理&开头的运算符
else if(ch == '&')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&&=&,OPE_DESC,COMPLETE_BYTE_AND,-1,line);
else if(ch == '&')
createNewNode(&&&&,OPE_DESC,AND,-1,line);
createNewNode(&&&,OPE_DESC,BYTE_AND,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理~开头的运算符
else if(ch == '~')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&~=&,OPE_DESC,COMPLETE_COMPLEMENT,-1,line);
createNewNode(&~&,OPE_DESC,COMPLEMENT,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理!开头的运算符
else if(ch == '!')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&!=&,OPE_DESC,NOT_EQUAL,-1,line);
createNewNode(&!&,OPE_DESC,NOT,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理&开头的运算符
else if(ch == '&')
ch = fgetc(infile);
if(ch == '&')
createNewNode(&&&&,OPE_DESC,LEFT_MOVE,-1,line);
else if(ch == '=')
createNewNode(&&=&,OPE_DESC,LES_EQUAL,-1,line);
createNewNode(&&&,OPE_DESC,LES_THAN,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理&开头的运算符
else if(ch == '&')
ch = fgetc(infile);
if(ch == '&')
createNewNode(&&&&,OPE_DESC,RIGHT_MOVE,-1,line);
else if(ch == '=')
createNewNode(&&=&,OPE_DESC,GRT_EQUAL,-1,line);
createNewNode(&&&,OPE_DESC,GRT_THAN,-1,line);
fseek(infile,-1L,SEEK_CUR);
//处理|开头的运算符
else if(ch == '|')
ch = fgetc(infile);
if(ch == '|')
createNewNode(&||&,OPE_DESC,OR,-1,line);
createNewNode(&|&,OPE_DESC,BYTE_OR,-1,line);
fseek(infile,-1L,SEEK_CUR);
else if(ch == '=')
ch = fgetc(infile);
if(ch == '=')
createNewNode(&==&,OPE_DESC,EQUAL,-1,line);
createNewNode(&=&,OPE_DESC,ASG,-1,line);
fseek(infile,-1L,SEEK_CUR);
else if(ch == '(')
leftSmall++;
lineBra[0][leftSmall] =
createNewNode(&(&,CLE_OPE_DESC,LEFT_BRA,-1,line);
else if(ch == ')')
rightSmall++;
lineBra[1][rightSmall] =
createNewNode(&)&,CLE_OPE_DESC,RIGHT_BRA,-1,line);
else if(ch == '[')
leftMiddle++;
lineBra[2][leftMiddle] =
createNewNode(&[&,CLE_OPE_DESC,LEFT_INDEX,-1,line);
else if(ch == ']')
rightMiddle++;
lineBra[3][rightMiddle] =
createNewNode(&]&,CLE_OPE_DESC,RIGHT_INDEX,-1,line);
else if(ch == '{')
leftBig++;
lineBra[4][leftBig] =
createNewNode(&{&,CLE_OPE_DESC,L_BOUNDER,-1,line);
else if(ch == '}')
rightBig++;
lineBra[5][rightBig] =
createNewNode(&}&,CLE_OPE_DESC,R_BOUNDER,-1,line);
else if(ch == '.')
createNewNode(&.&,CLE_OPE_DESC,POINTER,-1,line);
else if(ch == ',')
createNewNode(&,&,CLE_OPE_DESC,COMMA,-1,line);
else if(ch == ';')
createNewNode(&;&,CLE_OPE_DESC,SEMI,-1,line);
char temp[2];
temp[1] = '\0';
createNewError(temp,CHAR_ERROR,CHAR_ERROR_NUM,line);
ch = fgetc(infile);
void BraMappingError()
if(leftSmall != rightSmall)
int i = (leftSmall&rightSmall) ? (leftSmall-rightSmall) : (rightSmall - leftSmall);
flag = (leftSmall&rightSmall) ? true :
while(i--)
createNewError(_NULL,LEFT_BRA_ERROR,LEFT_BRA_ERROR_NUM,lineBra[0][i+1]);
while(i--)
createNewError(_NULL,RIGHT_BRA_ERROR,RIGHT_BRA_ERROR_NUM,lineBra[1][i+1]);
if(leftMiddle != rightMiddle)
int i = (leftMiddle&rightMiddle) ? (leftMiddle-rightMiddle) : (rightMiddle - leftMiddle);
bool flag = (leftMiddle&rightMiddle) ? true :
while(i--)
createNewError(_NULL,LEFT_INDEX_ERROR,LEFT_INDEX_ERROR_NUM,lineBra[2][i+1]);
while(i--)
createNewError(_NULL,RIGHT_INDEX_ERROR,RIGHT_INDEX_ERROR_NUM,lineBra[3][i+1]);
if(leftBig != rightBig)
int i = (leftBig&rightBig) ? (leftBig-rightBig) : (rightBig - leftSmall);
bool flag = (leftBig&rightBig) ? true :
while(i--)
createNewError(_NULL,L_BOUNDER_ERROR,L_BOUNDER_ERROR_NUM,lineBra[4][i+1]);
while(i--)
createNewError(_NULL,R_BOUNDER_ERROR,R_BOUNDER_ERROR_NUM,lineBra[5][i+1]);
语法分析Cpp代码:
//SynAnalysis.cpp
#include &iostream&
#include &stdio.h&
#include &stdlib.h&
#include &string.h&
#include &conio.h&
#include &fstream&
#include &vector&
#include &conio.h&
#include &LexAnalysis.h&
#include &SynAnalysis.h&
#define Max_Proc 500
#define Max_Length 500
#define Max_NonTer 60
#define Max_Ter 60
#define Max_Length2 100
int procNum = 0;
//proc的维数都是从1开始的
int proc[Max_Proc][Max_Length];//产生式的数组,里边存储了终结符或者非终结符对应的编号
int first[Max_Proc][Max_Length];
int follow[Max_Proc][Max_Length];
int select[Max_Proc][Max_Length];
int M[Max_NonTer][Max_Ter][Max_Length2];
int connectFirst[Max_Length];//将某些First集结合起来的集合
int firstVisit[Max_Proc];//记录某非终结符的First集是否已经求过
int followVisit[Max_Proc];//记录某非终结符的Follow集是否已经求过
int empty[Max_Proc];//可推出空的非终结符的编号
int emptyRecu[Max_Proc];//在求可推出空的非终结符的编号集时使用的防治递归的集合
int followRecu[Max_Proc];//在求Follow集时使用的防治递归的集合
//extern的部分代表可能出现的终结符和其编号
extern vector&pair&const char *,int& & keyM
extern vector&pair&const char *,int& & operM
extern vector&pair&const char *,int& & limitM
extern NormalNode * normalH//首结点
vector&pair&const char *,int& & nonTerM//非终结符映射表,不可重复的
vector&pair&const char *,int& & terM//终结符映射表,不可重复的
vector&pair&const char *,int& & specialM//文法中的特殊符号映射表,包括-& | $(空)
void initSpecialMapping()
specialMap.clear();
specialMap.push_back(make_pair(&-&&,GRAMMAR_ARROW));
specialMap.push_back(make_pair(&|&,GRAMMAR_OR));
specialMap.push_back(make_pair(&$&,GRAMMAR_NULL));
specialMap.push_back(make_pair(&#&,GRAMMAR_SPECIAL));
const char * searchMapping(int num)
if(num == IDENTIFER)
return &id&;
//处理文法中的特殊符号
for(int i = 0; i&specialMap.size(); i++)
if(specialMap[i].second == num)
return specialMap[i].
//处理非终结符
for(int i=0; i&nonTerMap.size(); i++)
if(nonTerMap[i].second == num)
return nonTerMap[i].
//处理终结符
for(int i=0; i&terMap.size(); i++)
if(terMap[i].second == num)
return terMap[i].
//动态生成非终结符,在基点的基础上,确保不和终结符冲突
int dynamicNonTer(char *word)
int i = 0;
int dynamicN
for(i=0; i&nonTerMap.size(); i++)
if(strcmp(word,nonTerMap[i].first) == 0)
return nonTerMap[i].
if(i == nonTerMap.size())
if(i == 0)
dynamicNum = GRAMMAR_BASE;
nonTerMap.push_back(make_pair(word,dynamicNum));
dynamicNum = nonTerMap[nonTerMap.size()-1].second + 1;
nonTerMap.push_back(make_pair(word,dynamicNum));
return dynamicN
//判断某个标号是不是非终结符的标号,1代表是,0代表否
int inNonTer(int n)
for(int i=0; i&nonTerMap.size(); i++)
if(nonTerMap[i].second == n)
//判断某个标号是不是终结符的标号,1代表是,0代表否
int inTer(int n)
for(int i=0; i&terMap.size(); i++)
if(terMap[i].second == n)
//判断某个标号在不在此时的empty集中,1代表是,0代表否
int inEmpty(int n)
//当前Empty集的长度
int emptyLength = 0;
for(emptyLength = 0;; emptyLength++)
if(empty[emptyLength] == -1)
for(int i = 0; i&emptyL i++)
if(empty[i] == n)
//判断某个标号在不在此时的emptyRecu集中,1代表是,0代表否
int inEmptyRecu(int n)
//当前Empty集的长度
int emptyLength = 0;
for(emptyLength = 0;; emptyLength++)
if(emptyRecu[emptyLength] == -1)
for(int i = 0; i&emptyL i++)
if(emptyRecu[i] == n)
//判断某个标号在不在此时的followRecu集中,1代表是,0代表否
int inFollowRecu(int n)
int followLength = 0;
for(followLength = 0;; followLength++)
if(followRecu[followLength] == -1)
for(int i = 0; i&followL i++)
if(followRecu[i] == n)
//判断某个标号是不是在产生式的右边
int inProcRight(int n,int * p)
//注意这里默认是从3开始
for(int i=3;; i++)
if(p[i] == -1)
if(p[i] == n)
int seekCodeNum(char * word)
//处理文法中的特殊符号
for(int i = 0; i&specialMap.size(); i++)
if(strcmp(word,specialMap[i].first) == 0)
return specialMap[i].
//先搜索终结符映射表中有没有此终结符
for(int i=0; i&terMap.size(); i++)
if(strcmp(word,terMap[i].first) == 0)
return terMap[i].
for(int i = 0; i&keyMap.size(); i++)
if(strcmp(word,keyMap[i].first) == 0)
terMap.push_back(make_pair(word,keyMap[i].second));
return keyMap[i].
for(int i = 0; i&operMap.size(); i++)
if(strcmp(word,operMap[i].first) == 0)
terMap.push_back(make_pair(word,operMap[i].second));
return operMap[i].
for(int i = 0; i&limitMap.size(); i++)
if(strcmp(word,limitMap[i].first) == 0)
terMap.push_back(make_pair(word,limitMap[i].second));
return limitMap[i].
if(strcmp(word,&id&)==0)
//处理标志符
terMap.push_back(make_pair(word,IDENTIFER));
return IDENTIFER;
//处理关键字、运算符、限界符表,即非终结符
return dynamicNonTer(word);
//分割& | &文法
void splitProc(int p[][Max_Length],int &line,int orNum)
if(p[line][1] == -1 || orNum == 0)
int head = p[line][1];
int push = p[line][2];
int length = 0;
int right,
int lineTrue = line + orN
for(length = 3;;length++)
if(p[line][length] == -1)
for(left = length,right =left&=2;)
if(p[line][left] == GRAMMAR_OR || left == 2)
p[line + orNum][1] =
p[line + orNum][2] =
for(int i=left+1;i&=i++)
p[line+orNum][i-left+2] = p[line][i];
p[line+orNum][right-left+3] = -1;
right = left = left-1;
line = lineT
void initGrammer()
char array[30];
int line = 1;
int count = 0;
int orNum = 0;
infile = fopen(&wenfa.txt&,&r&);
if(!infile)
printf(&文法打开失败!\n&);
initSpecialMapping();
nonTerMap.clear();
terMap.clear();
memset(proc,-1,sizeof(proc));
memset(first,-1,sizeof(first));
memset(follow,-1,sizeof(follow));
memset(select,-1,sizeof(select));
memset(connectFirst,-1,sizeof(connectFirst));
memset(firstVisit,0,sizeof(firstVisit));//非终结符的first集还未求过
memset(followVisit,0,sizeof(followVisit));//非终结符的follow集还未求过
memset(empty,-1,sizeof(empty));
memset(emptyRecu,-1,sizeof(emptyRecu));
memset(followRecu,-1,sizeof(followRecu));
memset(M,-1,sizeof(M));
ch = fgetc(infile);
while(ch!=EOF)
while(ch == ' ' || ch == '\t')
ch = fgetc(infile);
while(ch!=' ' && ch!= '\n' && ch!=EOF)
array[i++] =
ch = fgetc(infile);
while(ch == ' ' || ch == '\t')
ch = fgetc(infile);
word = new char[i+1];
memcpy(word,array,i);
word[i] = '\0';
codeNum = 0;
codeNum = seekCodeNum(word);
if(codeNum!=0)
if(codeNum == GRAMMAR_OR)
proc[line][count] = codeN
//原本需要回退一个字符,由于是冗余字符,不回退
if(ch == '\n')
splitProc(proc,line,orNum);//将& | &文法进行拆分
count = 0;
orNum = 0;
ch = fgetc(infile);
procNum = line - 1;
printf(&************************************C语言文法******************************\n\n&);
for(int i=1; i& i++)
for(int j=1; j&Max_L j++)
if(proc[i][j]!=-1)
printf(&%s &,searchMapping(proc[i][j]));
printf(&\n&);
printf(&\n************************************文法终结符******************************\n\n&);
for(int i=0; i&terMap.size(); i++)
printf(&%s &,terMap[i].first);
printf(&\n&);
printf(&\n************************************文法非终结符******************************\n\n&);
for(int i=0; i&nonTerMap.size(); i++)
printf(&%s &,nonTerMap[i].first);
printf(&\n&);
//将s集合合并至d集合中,type = 1代表包括空($),type = 2代表不包括空
void merge(int *d,int *s,int type)
int flag = 0;
for(int i = 0;; i++)
if(s[i] == -1)
int j = 0;
for(j = 0;; j++)
if(d[j] == -1)
if(d[j] == s[i])
if(flag == 1)
if(type == 1)
d[j] = s[i];
if(s[i] != GRAMMAR_NULL)
d[j] = s[i];
d[j + 1] = -1;
void nullSet(int currentNum)
int temp[2];
for(int j = 1; j&=procN j++)
//如果右边的第一个是该字符,并且长度只有1
if(proc[j][3] == currentNum && proc[j][4] == -1)
temp[0] = proc[j][1];
temp[1] = -1;
merge(empty,temp,1);
nullSet(proc[j][1]);
//判断该非终结符是否能推出空,但终结符也可能传入,但没关系
int reduNull(int currentNon)
int temp[2];
int result = 1;
int mark = 0;
temp[0] = currentN
temp[1] = -1;
merge(emptyRecu,temp,1);//先将此符号并入防递归集合中
if(inEmpty(currentNon) == 1)
for(int j = 1; j&=procN j++)
if(proc[j][1] == currentNon)
int rightLength = 0;
//先求出右部的长度
for(rightLength = 3;; rightLength++)
if(proc[j][rightLength] == -1)
rightLength--;
//如果长度为1,并且已经求过
if(rightLength - 2 == 1 && inEmpty(proc[j][rightLength]))
//如果长度为1,并且是终结符
else if(rightLength -2 == 1 && inTer(proc[j][rightLength]))
//如果长度超过了2
for(int k=3; k&=rightL k++)
if(inEmptyRecu(proc[j][k]))
if(mark == 1)
for(int k=3; k&=rightL k++)
result*= reduNull(proc[j][k]);
temp[0] = proc[j][k];
temp[1] = -1;
merge(emptyRecu,temp,1);//先将此符号并入防递归集合中
if(result == 0)
else if(result == 1)
//求first集,传入的参数是在非终结符集合中的序号
void firstSet(int i)
int k = 0;
int currentNon = nonTerMap[i].//当前的非终结符标号
//依次遍历全部产生式
for(int j = 1; j&=procN j++) //j代表第几个产生式
//找到该非终结符的产生式
if(currentNon == proc[j][1])//注意从1开始
//当右边的第一个是终结符或者空的时候
if(inTer(proc[j][3]) == 1 || proc[j][3] == GRAMMAR_NULL)
//并入当前非终结符的first集中
int temp[2];
temp[0] = proc[j][3];
temp[1] = -1;//其实是模拟字符串操作的手段
merge(first[i],temp,1);
//当右边的第一个是非终结符的时候
else if(inNonTer(proc[j][3]) == 1)
//如果遇到左递归形式的,直接放过?
if(proc[j][3] == currentNon)
//记录下右边第一个非终结符的位置
for(k=0;; k++)
if(nonTerMap[k].second == proc[j][3])
//当右边第一个非终结符还未访问过的时候
if(firstVisit[k] == 0)
firstSet(k);
firstVisit[k] = 1;
merge(first[i],first[k],2);//如果first[k]此时有空值的话,暂时不把空值并入first[i]中
int rightLength = 0;
//先求出右部的长度
for(rightLength = 3;; rightLength++)
if(proc[j][rightLength] == -1)
//到目前为止,只求出了右边的第一个(还不包括空的部分),For循环处理之后的
for(k = 3; k&rightL k++)
emptyRecu[0] = -1;//相当于初始化这个防递归集合
//如果右部的当前字符能推出空并且还不是最后一个字符,就将之后的一个字符并入First集中
if(reduNull(proc[j][k]) == 1 && k&rightLength -1)
int u = 0;
for(u=0;; u++)
//注意是记录下一个符号的位置
if(nonTerMap[u].second == proc[j][k+1])
if(firstVisit[u] == 0)
firstSet(u);
firstVisit[u] = 1;
merge(first[i],first[u],2);
//到达最后一个字符,并且产生式右部都能推出空,将$并入First集中
else if(reduNull(proc[j][k]) == 1 && k == rightLength -1)
int temp[2];
temp[0] = GRAMMAR_NULL;
temp[1] = -1;//其实是模拟字符串操作的手段
merge(first[i],temp,1);
firstVisit[i] = 1;
void First()
//先求出能直接推出空的非终结符集合
nullSet(GRAMMAR_NULL);
printf(&\n&);
for(int i=0; i&nonTerMap.size(); i++)
firstSet(i);
printf(&\n************************************First集******************************\n\n&);
for(int i=0; i&nonTerMap.size(); i++)
printf(&First[%s] = &,nonTerMap[i].first);
for(int j=0;; j++)
if(first[i][j] == -1)
printf(&%s &,searchMapping(first[i][j]));
printf(&\n&);
//将First结合起来的函数
void connectFirstSet(int *p)
int i = 0;
int flag = 0;
int temp[2];
//如果P的长度为1
if(p[1] == -1)
if(p[0] == GRAMMAR_NULL)
connectFirst[0] = GRAMMAR_NULL;
connectFirst[1] = -1;
for(i=0; i&nonTerMap.size(); i++)
if(nonTerMap[i].second == p[0])
merge(connectFirst,first[i],1);
//也可能是终结符
if(flag == 0)
for(i=0; i&terMap.size(); i++)
if(terMap[i].second == p[0])
temp[0] = terMap[i].
temp[1] = -1;
merge(connectFirst,temp,2);//终结符的First集就是其本身
//如果p的长度大于1
for(i=0; i&nonTerMap.size(); i++)
if(nonTerMap[i].second == p[0])
merge(connectFirst,first[i],2);
//也可能是终结符
if(flag == 0)
for(i=0; i&terMap.size(); i++)
if(terMap[i].second == p[0])
temp[0] = terMap[i].
temp[1] = -1;
merge(connectFirst,temp,2);//终结符的First集就是其本身
int length = 0;
for(length = 0;; length++)
if(p[length] == -1)
for(int k=0; k& k++)
emptyRecu[0] = -1;//相当于初始化这个防递归集合
//如果右部的当前字符能推出空并且还不是最后一个字符,就将之后的一个字符并入First集中
if(reduNull(p[k]) == 1 && k&length -1)
int u = 0;
for(u=0; u&nonTerMap.size(); u++)
//注意是记录下一个符号的位置
if(nonTerMap[u].second == p[k+1])
merge(connectFirst,first[u],2);
//也可能是终结符
if(flag == 0)
for(u=0; u&terMap.size(); u++)
//注意是记录下一个符号的位置
if(terMap[u].second == p[k+1])
temp[0] = terMap[i].
temp[1] = -1;
merge(connectFirst,temp,2);
//到达最后一个字符,并且产生式右部都能推出空,将$并入First集中
else if(reduNull(p[k]) == 1 && k == length -1)
temp[0] = GRAMMAR_NULL;
temp[1] = -1;//其实是模拟字符串操作的手段
merge(connectFirst,temp,1);
void followSet(int i)
int currentNon = nonTerMap[i].//当前的非终结符标号
int temp[2];
int result = 1;
temp[0] = currentN
temp[1] = -1;
merge(followRecu,temp,1);//将当前标号加入防递归集合中
//如果当前符号就是开始符号,把特殊符号加入其Follow集中
if(proc[1][1] == currentNon)
temp[0] = GRAMMAR_SPECIAL;//这个也是要处理的
temp[1] = -1;
merge(follow[i],temp,1);
for(int j = 1; j&=procN j++) //j代表第几个产生式
//如果该非终结符在某个产生式的右部存在
if(inProcRight(currentNon,proc[j]) == 1)
int rightLength = 1;
int k = 0;//k为该非终结符在产生式右部的序号
int flag = 0;
int leftNum = proc[j][1];//产生式的左边
int h = 0;
int kArray[Max_Length2];
memset(kArray,-1,sizeof(kArray));
for(h = 0; h & nonTerMap.size(); h++)
if(nonTerMap[h].second == leftNum)
for(rightLength = 1;; rightLength++)
if(currentNon == proc[j][rightLength+2])
kArray[k++] = rightL
if(proc[j][rightLength+2] == -1)
rightLength--;
for(int y=0;; y++)
if(kArray[y] == -1)
//如果该非终结符在右部产生式的最后
if(kArray[y] == rightLength)
if(inFollowRecu(leftNum) == 1)
merge(follow[i],follow[h],1);
if(followVisit[h] == 0)
followSet(h);
followVisit[h] = 1;
merge(follow[i],follow[h],1);
//如果不在最后
int n = 0;
result = 1;//这是关键的,曾在这里失误过
for(n=kArray[y]+1; n&=rightL n++)
emptyRecu[0] = -1;
result *= reduNull(proc[j][n+2]);
if(result == 1)
if(inFollowRecu(leftNum) == 1)
merge(follow[i],follow[h],1);
if(followVisit[h] == 0)
followSet(h);
followVisit[h] = 1;
merge(follow[i],follow[h],1);
int temp2[Max_Length];
memset(temp2,-1,sizeof(temp2));
for(n=kArray[y]+1; n&=rightL n++)
temp2[n-kArray[y]-1] = proc[j][n+2];
temp2[rightLength-kArray[y]] = -1;
connectFirst[0] = -1;//应该重新初始化一下
connectFirstSet(temp2);
merge(follow[i],connectFirst,2);
followVisit[i] = 1;
//求所有非终结符的Follow集
void Follow()
for(int i=0; i&nonTerMap.size(); i++)
followRecu[0] = -1;
followSet(i);
printf(&\n************************************Follow集******************************\n\n&);
for(int i=0; i&nonTerMap.size(); i++)
printf(&Follow[%s] = &,nonTerMap[i].first);
for(int j=0;; j++)
if(follow[i][j] == -1)
printf(&%s &,searchMapping(follow[i][j]));
printf(&\n&);
//求已经分解的产生式对应的Select集,注意Select集中不能含有空($),因而Type=2
void Select()
for(int i = 1; i&=procN i++) //j代表第几个产生式
int leftNum = proc[i][1];//产生式的左边
int h = 0;
int result = 1;
for(h = 0; h & nonTerMap.size(); h++)
if(nonTerMap[h].second == leftNum)
int rightLength = 1;
for(rightLength = 1;; rightLength++)
if(proc[i][rightLength+2] == -1)
rightLength--;
//如果右部推出式的长度为1并且是空,select[i-1] = follow[左边]
if(rightLength == 1 && proc[i][rightLength + 2] == GRAMMAR_NULL)
merge(select[i-1],follow[h],2);
//如果右部不是空的时候,select[i-1] = first[右部全部]
//如果右部能够推出空,select[i-1] = first[右部全部] ^ follow[左边]
int temp2[Max_Length];
int n = 0;
memset(temp2,-1,sizeof(temp2));
for(n=1; n&=rightL n++)
temp2[n-1] = proc[i][n+2];
temp2[rightLength] = -1;
connectFirst[0] = -1;//应该重新初始化一下
connectFirstSet(temp2);
merge(select[i-1],connectFirst,2);
for(n=1; n&=rightL n++)
emptyRecu[0] = -1;
result *= reduNull(proc[i][n+2]);
//如果右部能推出空,将follow[左边]并入select[i-1]中
if(result == 1)
merge(select[i-1],follow[h],2);
printf(&\n************************************Select集******************************\n\n&);
for(int i=0; i&procN i++)
printf(&Select[%d] = &,i+1);
for(int j=0;; j++)
if(select[i][j] == -1)
printf(&%s &,searchMapping(select[i][j]));
printf(&\n&);
//输出预测分析表
void MTable()
outfile.open(&preciateTable.txt&,ios::out);
for(int i=0; i&procN i++)
int m = 0;//非终结符的序号
for(int t=0; t&nonTerMap.size(); t++)
if(nonTerMap[t].second == proc[i+1][1])
for(int j=0;; j++)
if(select[i][j] == -1)
for(int k=0; k&terMap.size(); k++)
if(terMap[k].second == select[i][j])
int n = 0;
for(n=1; n&=Max_Length2; n++)
M[m][k][n-1] = proc[i+1][n];
if(proc[i+1][n] == -1)
//printf(&\n*********************************预测分析表******************************\n\n&);
outfile&&endl&&&*********************************预测分析表******************************&&&
for(int i=0; i&nonTerMap.size(); i++)
for(int j=0; j&terMap.size(); j++)
outfile&&&M[&&&nonTerMap[i].first&&&][&&&terMap[j].first&&&] = &;
//printf(&M[%s][%s] = &,nonTerMap[i].first,terMap[j].first);
for(int k=0;; k++)
if(M[i][j][k] == -1)
outfile&&searchMapping(M[i][j][k]);
//printf(&%s &,searchMapping(M[i][j][k]));
//printf(&\n&);
outfile&&endl&&
//printf(&\n\n&);
outfile.close();
void InitStack(SeqStack *S)
/*初始化顺序栈*/
S-&top = -1;
int Push(SeqStack *S,int x)
if(S-&top ==Stack_Size-1)
S-&elem[S-&top]=x;
int Pop(SeqStack *S)
if(S-&top==-1)
int GetTop(SeqStack *S,int *x)
/*取栈顶元素*/
if(S-&top==-1)
*x=S-&elem[S-&top];
void ShowStack1(SeqStack *S)
/*显示栈的字符,先输出栈底元素*/
for(i=S-& i&=0; i--)
//printf(&%s &,searchMapping(S-&elem[i]));
resultfile&&searchMapping(S-&elem[i])&&& &;
void ShowStack2(SeqStack *S)
/*显示栈的字符,先输出栈顶元素*/
for(i=S-& i&=0; i--)
//printf(&%s &,searchMapping(S-&elem[i]));
resultfile&&searchMapping(S-&elem[i])&&& &;
//分析源程序
void Analysis()
//分析结果输出
resultfile.open(&preciateResult.txt&,ios::out);
SeqStack s1,s2;
int c1,c2;
int i = 0;
int reserve[Stack_Size];//符号栈反向入栈
NormalNode * p = normalH
int s1Length = 0;
memset(reserve,-1,sizeof(reserve));
InitStack(&s1);
/*初始化符号栈和输入串*/
InitStack(&s2);
Push(&s1,GRAMMAR_SPECIAL);
Push(&s1,proc[1][1]);
Push(&s2,GRAMMAR_SPECIAL);
while(p!=NULL)
if(p-&type == AUTO || p-&type == CONST || p-&type == UNSIGNED || p-&type == SIGNED
|| p-&type ==STATIC || p-&type == VOLATILE )
reserve[i++] =
//Push(&s2,DESCRIBE);
else if(p-&type == INT_VAL)
reserve[i++] =
//Push(&s2,DIGIT);
else if(p-&type == CHAR || p-&type == DOUBLE || p-&type == FLOAT || p-&type == INT ||
p-&type == LONG || p-&type == SHORT || p-&type == VOID)
reserve[i++] =
//Push(&s2,TYPE);
else if(p-&type == STRING_VAL)
reserve[i++] =
//Push(&s2,STRING);
else if(p-&type == DOU_QUE || p-&type == SIN_QUE)
reserve[i++] =
//Push(&s2,p-&type);
//求左边栈的长度
for(s1Length = 0;; s1Length++)
if(reserve[s1Length] == -1)
//反向入栈
for(i = s1L i&0; i--)
Push(&s2,reserve[i-1]);
for(i=0;; i++)
//getch();
int flag = 0;
//printf(&第%d步:\n&,i+1);
/*输出该步的相应信息*/
resultfile&&&第&&&i + 1&&&步&&&
//printf(&符号栈:&);
resultfile&&&符号栈:&;
ShowStack1(&s1);
//printf(&\n&);
resultfile&&
//printf(&输入栈:&);
resultfile&&&输入栈:&;
ShowStack2(&s2);
//printf(&\n&);
resultfile&&
GetTop(&s1,&c1);
/*取栈顶元素,记为c1,c2*/
GetTop(&s2,&c2);
if(c1 == GRAMMAR_SPECIAL && c2 == GRAMMAR_SPECIAL)
/*当符号栈和输入栈都剩余#时,分析成功*/
//printf(&成功!\n&);
resultfile&&&成功!&&&
if(c1 == GRAMMAR_SPECIAL && c2!= GRAMMAR_SPECIAL)
/*当符号栈剩余#,而输入串未结束时,分析失败 */
//printf(&失败!\n&);
resultfile&&&失败!&&&
if(c1 == c2)/*符号栈的栈顶元素和输入串的栈顶元素相同时,同时弹出*/
else /*查预测分析表*/
//记录下非终结符的位置
for(h1=0; h1&nonTerMap.size(); h1++)
if(nonTerMap[h1].second == c1)
//记录下终结符的位置
for(h2=0; h2&terMap.size(); h2++)
if(terMap[h2].second == c2)
if(M[h1][h2][0] == -1)
//printf(&Error\n&);
resultfile&&&Error&&&
//如果错误的话,直接终止分析
int length = 0;
//记录下推导式的长度
for(length = 0;; length++)
if(M[h1][h2][length] == -1)
//如果不是空的话,反向入栈
if(M[h1][h2][2] != GRAMMAR_NULL)
for(int k = length-1; k&=2; k--)
Push(&s1,M[h1][h2][k]);
if(flag == 1)
//printf(&匹配!\n&);
resultfile&&&匹配!&&&
resultfile&&&所用推出式:&;
//printf(&所用推出式:&);
int w = 0;
//记录下推导式的长度
for(w = 0;; w++)
if(M[h1][h2][w] == -1)
//printf(&%s &,searchMapping(M[h1][h2][w]));
resultfile&&searchMapping(M[h1][h2][w]);
//printf(&\n\n&);
resultfile&&endl&&
resultfile.close();
//main.cpp
#include &iostream&
#include &fstream&
#include &stdio.h&
#include &stdlib.h&
#include &string.h&
#include &iomanip&
#include &LexAnalysis.h&
#include &SynAnalysis.h&
int main()
//词法分析部分
initKeyMapping();
initOperMapping();
initLimitMapping();
initNode();
scanner();
BraMappingError();
printNodeLink();
printErrorLink();
printIdentLink();
//语法分析部分
initGrammer();
Analysis();
测试程序(被分析的C代码):
int main()
int i = 7;
int j = 9;
int c[20] =
{2,10,10,19,3,4,5,5,34,6,54,52,34,55,68,10,90,78,56,20};
for (i=0;i&20;i++)
for(j=i+1;j&20;j--)
if(j == 19)
printf(&Hello world&);
分析结果:
************************************C语言文法******************************
&函数定义& -& &修饰词闭包& &类型& &变量& ( &参数声明& ) { &函数块& }
&修饰词闭包& -& &修饰词& &修饰词闭包&
&修饰词闭包& -& $
&修饰词& -& describe
&类型& -& type &取地址&
&取地址& -& &星号闭包&
&星号闭包& -& &星号& &星号闭包&
&星号闭包& -& $
&星号& -& *
&变量& -& &标志符& &数组下标&
&标志符& -& id
&数组下标& -& [ &因式& ]
&数组下标& -& $
&因式& -& ( &表达式& )
&因式& -& &变量&
&因式& -& &数字&
&数字& -& digit
&表达式& -& &因子& &项&
&因子& -& &因式& &因式递归&
&因式递归& -& * &因式& &因式递归&
&因式递归& -& / &因式& &因式递归&
&因式递归& -& $
&项& -& + &因子& &项&
&项& -& - &因子& &项&
&参数声明& -& &声明& &声明闭包&
&参数声明& -& $
&声明& -& &修饰词闭包& &类型& &变量& &赋初值&
&赋初值& -& = &右值&
&赋初值& -& $
&右值& -& &表达式&
&右值& -& { &多个数据& }
&多个数据& -& &数字& &数字闭包&
&数字闭包& -& , &数字& &数字闭包&
&数字闭包& -& $
&声明闭包& -& , &声明& &声明闭包&
&声明闭包& -& $
&函数块& -& &声明语句闭包& &函数块闭包&
&声明语句闭包& -& &声明语句& &声明语句闭包&
&声明语句闭包& -& $
&声明语句& -& &声明& ;
&函数块闭包& -& &赋值函数& &函数块闭包&
&函数块闭包& -& &for循环& &函数块闭包&
&函数块闭包& -& &条件语句& &函数块闭包&
&函数块闭包& -& &函数返回& &函数块闭包&
&函数块闭包& -& $
&赋值函数& -& &变量& &赋值或函数调用&
&赋值或函数调用& -& = &右值& ;
&赋值或函数调用& -& ( &参数列表& ) ;
&参数列表& -& &参数& &参数闭包&
&参数闭包& -& , &参数& &参数闭包&
&参数闭包& -& $
&参数& -& &标志符&
&参数& -& &数字&
&参数& -& &字符串&
&字符串& -& string
&for循环& -& for ( &赋值函数& &逻辑表达式& ; &后缀表达式& ) { &函数块& }
&逻辑表达式& -& &表达式& &逻辑运算符& &表达式&
&逻辑运算符& -& &
&逻辑运算符& -& &
&逻辑运算符& -& ==
&逻辑运算符& -& !=
&后缀表达式& -& &变量& &后缀运算符&
&后缀运算符& -& ++
&后缀运算符& -& --
&条件语句& -& if ( &逻辑表达式& ) { &函数块& } &否则语句&
&否则语句& -& else { &函数块& }
&否则语句& -& $
&函数返回& -& return &因式& ;
************************************文法终结符******************************
( ) { } describe type * id [ ] digit / + - = , ; string for & & == != ++ -- if e
lse return
************************************文法非终结符******************************
&函数定义& &修饰词闭包& &类型& &变量& &参数声明& &函数块& &修饰词& &取地址& &星
号闭包& &星号& &标志符& &数组下标& &因式& &表达式& &数字& &因子& &项& &因式递归&
&声明& &声明闭包& &赋初值& &右值& &多个数据& &数字闭包& &声明语句闭包& &函数块
闭包& &声明语句& &赋值函数& &for循环& &条件语句& &函数返回& &赋值或函数调用& &参
数列表& &参数& &参数闭包& &字符串& &逻辑表达式& &后缀表达式& &逻辑运算符& &后缀
运算符& &否则语句&
************************************First集******************************
First[&函数定义&] = describe type
First[&修饰词闭包&] = describe $
First[&类型&] = type
First[&变量&] = id
First[&参数声明&] = describe type $
First[&函数块&] = describe type id for if return $
First[&修饰词&] = describe
First[&取地址&] = * $
First[&星号闭包&] = * $
First[&星号&] = *
First[&标志符&] = id
First[&数组下标&] = [ $
First[&因式&] = ( id digit
First[&表达式&] = ( id digit
First[&数字&] = digit
First[&因子&] = ( id digit
First[&项&] = + - $
First[&因式递归&] = * / $
First[&声明&] = describe type
First[&声明闭包&] = , $
First[&赋初值&] = = $
First[&右值&] = ( id digit {
First[&多个数据&] = digit
First[&数字闭包&] = , $
First[&声明语句闭包&] = describe type $
First[&函数块闭包&] = id for if return $
First[&声明语句&] = describe type
First[&赋值函数&] = id
First[&for循环&] = for
First[&条件语句&] = if
First[&函数返回&] = return
First[&赋值或函数调用&] = = (
First[&参数列表&] = id digit string
First[&参数&] = id digit string
First[&参数闭包&] = , $
First[&字符串&] = string
First[&逻辑表达式&] = ( id digit
First[&后缀表达式&] = id
First[&逻辑运算符&] = & & == !=
First[&后缀运算符&] = ++ --
First[&否则语句&] = else $
************************************Follow集******************************
Follow[&函数定义&] = #
Follow[&修饰词闭包&] = type
Follow[&类型&] = id
Follow[&变量&] = ( ] ) , ; & & == != + - * / = ++ --
Follow[&参数声明&] = )
Follow[&函数块&] = }
Follow[&修饰词&] = type describe
Follow[&取地址&] = id
Follow[&星号闭包&] = id
Follow[&星号&] = id *
Follow[&标志符&] = ( ] ) , ; & & == != + - * / = ++ -- [
Follow[&数组下标&] = ( ] ) , ; & & == != + - * / = ++ --
Follow[&因式&] = ] ) , ; & & == != + - * /
Follow[&表达式&] = ) , ; & & == !=
Follow[&数字&] = ] ) , ; & & == != + - * / }
Follow[&因子&] = ) , ; & & == != + -
Follow[&项&] = ) , ; & & == !=
Follow[&因式递归&] = ) , ; & & == != + -
Follow[&声明&] = ) , ;
Follow[&声明闭包&] = )
Follow[&赋初值&] = ) , ;
Follow[&右值&] = ) , ;
Follow[&多个数据&] = }
Follow[&数字闭包&] = }
Follow[&声明语句闭包&] = } id for if return
Follow[&函数块闭包&] = }
Follow[&声明语句&] = } id for if return describe type
Follow[&赋值函数&] = } id for if return ( digit
Follow[&for循环&] = } id for if return
Follow[&条件语句&] = } id for if return
Follow[&函数返回&] = } id for if return
Follow[&赋值或函数调用&] = } id for if return ( digit
Follow[&参数列表&] = )
Follow[&参数&] = ) ,
Follow[&参数闭包&] = )
Follow[&字符串&] = ) ,
Follow[&逻辑表达式&] = ; )
Follow[&后缀表达式&] = )
Follow[&逻辑运算符&] = ( id digit
Follow[&后缀运算符&] = )
Follow[&否则语句&] = } id for if return
************************************Select集******************************
Select[1] = describe type
Select[2] = describe
Select[3] = type
Select[4] = describe
Select[5] = type
Select[6] = * id
Select[7] = *
Select[8] = id
Select[9] = *
Select[10] = id
Select[11] = id
Select[12] = [
Select[13] = ( ] ) , ; & & == != + - * / = ++ --
Select[14] = (
Select[15] = id
Select[16] = digit
Select[17] = digit
Select[18] = ( id digit
Select[19] = ( id digit
Select[20] = *
Select[21] = /
Select[22] = ) , ; & & == != + -
Select[23] = +
Select[24] = -
Select[25] = ) , ; & & == !=
Select[26] = describe type
Select[27] = )
Select[28] = describe type
Select[29] = =
Select[30] = ) , ;
Select[31] = ( id digit
Select[32] = {
Select[33] = digit
Select[34] = ,
Select[35] = }
Select[36] = ,
Select[37] = )
Select[38] = describe type id for if return }
Select[39] = describe type
Select[40] = } id for if return
Select[41] = describe type
Select[42] = id
Select[43] = for
Select[44] = if
Select[45] = return
Select[46] = }
Select[47] = id
Select[48] = =
Select[49] = (
Select[50] = id digit string
Select[51] = ,
Select[52] = )
Select[53] = id
Select[54] = digit
Select[55] = string
Select[56] = string
Select[57] = for
Select[58] = ( id digit
Select[59] = &
Select[60] = &
Select[61] = ==
Select[62] = !=
Select[63] = id
Select[64] = ++
Select[65] = --
Select[66] = if
Select[67] = else
Select[68] = } id for if return
Select[69] = return
Process returned 0 (0x0)
execution time : 4.317 s
Press any key to continue.
输出文件内容:
preciateTable.txt(预测分析表):
*********************************预测分析表******************************
M[&函数定义&][(] =
M[&函数定义&][)] =
M[&函数定义&][{] =
M[&函数定义&][}] =
M[&函数定义&][describe] = &函数定义&-&&修饰词闭包&&类型&&变量&(&参数声明&){&函数块&}
M[&函数定义&][type] = &函数定义&-&&修饰词闭包&&类型&&变量&(&参数声明&){&函数块&}
M[&函数定义&][*] =
M[&函数定义&][id] =
M[&函数定义&][[] =
M[&函数定义&][]] =
M[&函数定义&][digit] =
M[&函数定义&][/] =
M[&函数定义&][+] =
M[&函数定义&][-] =
M[&函数定义&][=] =
M[&函数定义&][,] =
M[&函数定义&][;] =
M[&函数定义&][string] =
M[&函数定义&][for] =
M[&函数定义&][&] =
M[&函数定义&][&] =
M[&函数定义&][==] =
M[&函数定义&][!=] =
M[&函数定义&][++] =
M[&函数定义&][--] =
M[&函数定义&][if] =
M[&函数定义&][else] =
M[&函数定义&][return] =
M[&修饰词闭包&][(] =
M[&修饰词闭包&][)] =
M[&修饰词闭包&][{] =
M[&修饰词闭包&][}] =
M[&修饰词闭包&][describe] = &修饰词闭包&-&&修饰词&&修饰词闭包&
M[&修饰词闭包&][type] = &修饰词闭包&-&$
M[&修饰词闭包&][*] =
M[&修饰词闭包&][id] =
M[&修饰词闭包&][[] =
M[&修饰词闭包&][]] =
M[&修饰词闭包&][digit] =
M[&修饰词闭包&][/] =
M[&修饰词闭包&][+] =
M[&修饰词闭包&][-] =
M[&修饰词闭包&][=] =
M[&修饰词闭包&][,] =
M[&修饰词闭包&][;] =
M[&修饰词闭包&][string] =
M[&修饰词闭包&][for] =
M[&修饰词闭包&][&] =
M[&修饰词闭包&][&] =
M[&修饰词闭包&][==] =
M[&修饰词闭包&][!=] =
M[&修饰词闭包&][++] =
M[&修饰词闭包&][--] =
M[&修饰词闭包&][if] =
M[&修饰词闭包&][else] =
M[&修饰词闭包&][return] =
M[&类型&][(] =
M[&类型&][)] =
M[&类型&][{] =
M[&类型&][}] =
M[&类型&][describe] =
M[&类型&][type] = &类型&-&type&取地址&
M[&类型&][*] =
M[&类型&][id] =
M[&类型&][[] =
M[&类型&][]] =
M[&类型&][digit] =
M[&类型&][/] =
M[&类型&][+] =
M[&类型&][-] =
M[&类型&][=] =
M[&类型&][,] =
M[&类型&][;] =
M[&类型&][string] =
M[&类型&][for] =
M[&类型&][&] =
M[&类型&][&] =
M[&类型&][==] =
M[&类型&][!=] =
M[&类型&][++] =
M[&类型&][--] =
M[&类型&][if] =
M[&类型&][else] =
M[&类型&][return] =
M[&变量&][(] =
M[&变量&][)] =
M[&变量&][{] =
M[&变量&][}] =
M[&变量&][describe] =
M[&变量&][type] =
M[&变量&][*] =
M[&变量&][id] = &变量&-&&标志符&&数组下标&
M[&变量&][[] =
M[&变量&][]] =
M[&变量&][digit] =
M[&变量&][/] =
M[&变量&][+] =
M[&变量&][-] =
M[&变量&][=] =
M[&变量&][,] =
M[&变量&][;] =
M[&变量&][string] =
M[&变量&][for] =
M[&变量&][&] =
M[&变量&][&] =
M[&变量&][==] =
M[&变量&][!=] =
M[&变量&][++] =
M[&变量&][--] =
M[&变量&][if] =
M[&变量&][else] =
M[&变量&][return] =
M[&参数声明&][(] =
M[&参数声明&][)] = &参数声明&-&$
M[&参数声明&][{] =
M[&参数声明&][}] =
M[&参数声明&][describe] = &参数声明&-&&声明&&声明闭包&
M[&参数声明&][type] = &参数声明&-&&声明&&声明闭包&
M[&参数声明&][*] =
M[&参数声明&][id] =
M[&参数声明&][[] =
M[&参数声明&][]] =
M[&参数声明&][digit] =
M[&参数声明&][/] =
M[&参数声明&][+] =
M[&参数声明&][-] =
M[&参数声明&][=] =
M[&参数声明&][,] =
M[&参数声明&][;] =
M[&参数声明&][string] =
M[&参数声明&][for] =
M[&参数声明&][&] =
M[&参数声明&][&] =
M[&参数声明&][==] =
M[&参数声明&][!=] =
M[&参数声明&][++] =
M[&参数声明&][--] =
M[&参数声明&][if] =
M[&参数声明&][else] =
M[&参数声明&][return] =
M[&函数块&][(] =
M[&函数块&][)] =
M[&函数块&][{] =
M[&函数块&][}] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&函数块&][describe] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&函数块&][type] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&函数块&][*] =
M[&函数块&][id] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&函数块&][[] =
M[&函数块&][]] =
M[&函数块&][digit] =
M[&函数块&][/] =
M[&函数块&][+] =
M[&函数块&][-] =
M[&函数块&][=] =
M[&函数块&][,] =
M[&函数块&][;] =
M[&函数块&][string] =
M[&函数块&][for] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&函数块&][&] =
M[&函数块&][&] =
M[&函数块&][==] =
M[&函数块&][!=] =
M[&函数块&][++] =
M[&函数块&][--] =
M[&函数块&][if] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&函数块&][else] =
M[&函数块&][return] = &函数块&-&&声明语句闭包&&函数块闭包&
M[&修饰词&][(] =
M[&修饰词&][)] =
M[&修饰词&][{] =
M[&修饰词&][}] =
M[&修饰词&][describe] = &修饰词&-&describe
M[&修饰词&][type] =
M[&修饰词&][*] =
M[&修饰词&][id] =
M[&修饰词&][[] =
M[&修饰词&][]] =
M[&修饰词&][digit] =
M[&修饰词&][/] =
M[&修饰词&][+] =
M[&修饰词&][-] =
M[&修饰词&][=] =
M[&修饰词&][,] =
M[&修饰词&][;] =
M[&修饰词&][string] =
M[&修饰词&][for] =
M[&修饰词&][&] =
M[&修饰词&][&] =
M[&修饰词&][==] =
M[&修饰词&][!=] =
M[&修饰词&][++] =
M[&修饰词&][--] =
M[&修饰词&][if] =
M[&修饰词&][else] =
M[&修饰词&][return] =
M[&取地址&][(] =
M[&取地址&][)] =
M[&取地址&][{] =
M[&取地址&][}] =
M[&取地址&][describe] =
M[&取地址&][type] =
M[&取地址&][*] = &取地址&-&&星号闭包&
M[&取地址&][id] = &取地址&-&&星号闭包&
M[&取地址&][[] =
M[&取地址&][]] =
M[&取地址&][digit] =
M[&取地址&][/] =
M[&取地址&][+] =
M[&取地址&][-] =
M[&取地址&][=] =
M[&取地址&][,] =
M[&取地址&][;] =
M[&取地址&][string] =
M[&取地址&][for] =
M[&取地址&][&] =
M[&取地址&][&] =
M[&取地址&][==] =
M[&取地址&][!=] =
M[&取地址&][++] =
M[&取地址&][--] =
M[&取地址&][if] =
M[&取地址&][else] =
M[&取地址&][return] =
M[&星号闭包&][(] =
M[&星号闭包&][)] =
M[&星号闭包&][{] =
M[&星号闭包&][}] =
M[&星号闭包&][describe] =
M[&星号闭包&][type] =
M[&星号闭包&][*] = &星号闭包&-&&星号&&星号闭包&
M[&星号闭包&][id] = &星号闭包&-&$
M[&星号闭包&][[] =
M[&星号闭包&][]] =
M[&星号闭包&][digit] =
M[&星号闭包&][/] =
M[&星号闭包&][+] =
M[&星号闭包&][-] =
M[&星号闭包&][=] =
M[&星号闭包&][,] =
M[&星号闭包&][;] =
M[&星号闭包&][string] =
M[&星号闭包&][for] =
M[&星号闭包&][&] =
M[&星号闭包&][&] =
M[&星号闭包&][==] =
M[&星号闭包&][!=] =
M[&星号闭包&][++] =
M[&星号闭包&][--] =
M[&星号闭包&][if] =
M[&星号闭包&][else] =
M[&星号闭包&][return] =
M[&星号&][(] =
M[&星号&][)] =
M[&星号&][{] =
M[&星号&][}] =
M[&星号&][describe] =
M[&星号&][type] =
M[&星号&][*] = &星号&-&*
M[&星号&][id] =
M[&星号&][[] =
M[&星号&][]] =
M[&星号&][digit] =
M[&星号&][/] =
M[&星号&][+] =
M[&星号&][-] =
M[&星号&][=] =
M[&星号&][,] =
M[&星号&][;] =
M[&星号&][string] =
M[&星号&][for] =
M[&星号&][&] =
M[&星号&][&] =
M[&星号&][==] =
M[&星号&][!=] =
M[&星号&][++] =
M[&星号&][--] =
M[&星号&][if] =
M[&星号&][else] =
M[&星号&][return] =
M[&标志符&][(] =
M[&标志符&][)] =
M[&标志符&][{] =
M[&标志符&][}] =
M[&标志符&][describe] =
M[&标志符&][type] =
M[&标志符&][*] =
M[&标志符&][id] = &标志符&-&id
M[&标志符&][[] =
M[&标志符&][]] =
M[&标志符&][digit] =
M[&标志符&][/] =
M[&标志符&][+] =
M[&标志符&][-] =
M[&标志符&][=] =
M[&标志符&][,] =
M[&标志符&][;] =
M[&标志符&][string] =
M[&标志符&][for] =
M[&标志符&][&] =
M[&标志符&][&] =
M[&标志符&][==] =
M[&标志符&][!=] =
M[&标志符&][++] =
M[&标志符&][--] =
M[&标志符&][if] =
M[&标志符&][else] =
M[&标志符&][return] =
M[&数组下标&][(] = &数组下标&-&$
M[&数组下标&][)] = &数组下标&-&$
M[&数组下标&][{] =
M[&数组下标&][}] =
M[&数组下标&][describe] =
M[&数组下标&][type] =
M[&数组下标&][*] = &数组下标&-&$
M[&数组下标&][id] =
M[&数组下标&][[] = &数组下标&-&[&因式&]
M[&数组下标&][]] = &数组下标&-&$
M[&数组下标&][digit] =
M[&数组下标&][/] = &数组下标&-&$
M[&数组下标&][+] = &数组下标&-&$
M[&数组下标&][-] = &数组下标&-&$
M[&数组下标&][=] = &数组下标&-&$
M[&数组下标&][,] = &数组下标&-&$
M[&数组下标&][;] = &数组下标&-&$
M[&数组下标&][string] =
M[&数组下标&][for] =
M[&数组下标&][&] = &数组下标&-&$
M[&数组下标&][&] = &数组下标&-&$
M[&数组下标&][==] = &数组下标&-&$
M[&数组下标&][!=] = &数组下标&-&$
M[&数组下标&][++] = &数组下标&-&$
M[&数组下标&][--] = &数组下标&-&$
M[&数组下标&][if] =
M[&数组下标&][else] =
M[&数组下标&][return] =
M[&因式&][(] = &因式&-&(&表达式&)
M[&因式&][)] =
M[&因式&][{] =
M[&因式&][}] =
M[&因式&][describe] =
M[&因式&][type] =
M[&因式&][*] =
M[&因式&][id] = &因式&-&&变量&
M[&因式&][[] =
M[&因式&][]] =
M[&因式&][digit] = &因式&-&&数字&
M[&因式&][/] =
M[&因式&][+] =
M[&因式&][-] =
M[&因式&][=] =
M[&因式&][,] =
M[&因式&][;] =
M[&因式&][string] =
M[&因式&][for] =
M[&因式&][&] =
M[&因式&][&] =
M[&因式&][==] =
M[&因式&][!=] =
M[&因式&][++] =
M[&因式&][--] =
M[&因式&][if] =
M[&因式&][else] =
M[&因式&][return] =
M[&表达式&][(] = &表达式&-&&因子&&项&
M[&表达式&][)] =
M[&表达式&][{] =
M[&表达式&][}] =
M[&表达式&][describe] =
M[&表达式&][type] =
M[&表达式&][*] =
M[&表达式&][id] = &表达式&-&&因子&&项&
M[&表达式&][[] =
M[&表达式&][]] =
M[&表达式&][digit] = &表达式&-&&因子&&项&
M[&表达式&][/] =
M[&表达式&][+] =
M[&表达式&][-] =
M[&表达式&][=] =
M[&表达式&][,] =
M[&表达式&][;] =
M[&表达式&][string] =
M[&表达式&][for] =
M[&表达式&][&] =
M[&表达式&][&] =
M[&表达式&][==] =
M[&表达式&][!=] =
M[&表达式&][++] =
M[&表达式&][--] =
M[&表达式&][if] =
M[&表达式&][else] =
M[&表达式&][return] =
M[&数字&][(] =
M[&数字&][)] =
M[&数字&][{] =
M[&数字&][}] =
M[&数字&][describe] =
M[&数字&][type] =
M[&数字&][*] =
M[&数字&][id] =
M[&数字&][[] =
M[&数字&][]] =
M[&数字&][digit] = &数字&-&digit
M[&数字&][/] =
M[&数字&][+] =
M[&数字&][-] =
M[&数字&][=] =
M[&数字&][,] =
M[&数字&][;] =
M[&数字&][string] =
M[&数字&][for] =
M[&数字&][&] =
M[&数字&][&] =
M[&数字&][==] =
M[&数字&][!=] =
M[&数字&][++] =
M[&数字&][--] =
M[&数字&][if] =
M[&数字&][else] =
M[&数字&][return] =
M[&因子&][(] = &因子&-&&因式&&因式递归&
M[&因子&][)] =
M[&因子&][{] =
M[&因子&][}] =
M[&因子&][describe] =
M[&因子&][type] =
M[&因子&][*] =
M[&因子&][id] = &因子&-&&因式&&因式递归&
M[&因子&][[] =
M[&因子&][]] =
M[&因子&][digit] = &因子&-&&因式&&因式递归&
M[&因子&][/] =
M[&因子&][+] =
M[&因子&][-] =
M[&因子&][=] =
M[&因子&][,] =
M[&因子&][;] =
M[&因子&][string] =
M[&因子&][for] =
M[&因子&][&] =
M[&因子&][&] =
M[&因子&][==] =
M[&因子&][!=] =
M[&因子&][++] =
M[&因子&][--] =
M[&因子&][if] =
M[&因子&][else] =
M[&因子&][return] =
M[&项&][(] =
M[&项&][)] = &项&-&$
M[&项&][{] =
M[&项&][}] =
M[&项&][describe] =
M[&项&][type] =
M[&项&][*] =
M[&项&][id] =
M[&项&][[] =
M[&项&][]] =
M[&项&][digit] =
M[&项&][/] =
M[&项&][+] = &项&-&+&因子&&项&
M[&项&][-] = &项&-&-&因子&&项&
M[&项&][=] =
M[&项&][,] = &项&-&$
M[&项&][;] = &项&-&$
M[&项&][string] =
M[&项&][for] =
M[&项&][&] = &项&-&$
M[&项&][&] = &项&-&$
M[&项&][==] = &项&-&$
M[&项&][!=] = &项&-&$
M[&项&][++] =
M[&项&][--] =
M[&项&][if] =
M[&项&][else] =
M[&项&][return] =
M[&因式递归&][(] =
M[&因式递归&][)] = &因式递归&-&$
M[&因式递归&][{] =
M[&因式递归&][}] =
M[&因式递归&][describe] =
M[&因式递归&][type] =
M[&因式递归&][*] = &因式递归&-&*&因式&&因式递归&
M[&因式递归&][id] =
M[&因式递归&][[] =
M[&因式递归&][]] =
M[&因式递归&][digit] =
M[&因式递归&][/] = &因式递归&-&/&因式&&因式递归&
M[&因式递归&][+] = &因式递归&-&$
M[&因式递归&][-] = &因式递归&-&$
M[&因式递归&][=] =
M[&因式递归&][,] = &因式递归&-&$
M[&因式递归&][;] = &因式递归&-&$
M[&因式递归&][string] =
M[&因式递归&][for] =
M[&因式递归&][&] = &因式递归&-&$
M[&因式递归&][&] = &因式递归&-&$
M[&因式递归&][==] = &因式递归&-&$
M[&因式递归&][!=] = &因式递归&-&$
M[&因式递归&][++] =
M[&因式递归&][--] =
M[&因式递归&][if] =
M[&因式递归&][else] =
M[&因式递归&][return] =
M[&声明&][(] =
M[&声明&][)] =
M[&声明&][{] =
M[&声明&][}] =
M[&声明&][describe] = &声明&-&&修饰词闭包&&类型&&变量&&赋初值&
M[&声明&][type] = &声明&-&&修饰词闭包&&类型&&变量&&赋初值&
M[&声明&][*] =
M[&声明&][id] =
M[&声明&][[] =
M[&声明&][]] =
M[&声明&]

我要回帖

更多关于 java 开源文法解析 的文章

 

随机推荐