语法分析器(含完整源码)教学文稿
语法分析器
实验一:编写C语言的词法分析器输入文件名:*.c 输出文件名:*.tok【实验内容】实现C语言的词法分析程序。
从输入的C语言源程序中,识别出各个具有独立意义的单词,以二元组(单词的类别,单词的值)的形式输出。
保留字、运算符和分隔符以一字一类的方式编码,所有的标识符作为一类,所有的常量作为一类。
【实验目的】明确词法分析的任务,了解词法分析器的设计与实现。
【实验要求】(1)程序(2)实验报告:C语言的词法正规表达式,状态转换图。
【实验说明】上机两次4小时,第7周检查。
【输入样例】main(){int a,b;a = 10;b = a + 20;}【输出样例】(id,main)((,_)(),_)({,_}(int,_)(id,a)(,,_)(id,b)(;,_)(id,a)(=,_)(const,10)(;,_)(id,b)(=,_)(id,a)(+,_)(const,20)(;,_)(),_)[/watermark]#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#define LEN sizeof(struct Node)#define NULL 0struct Node{char data;struct Node *next; /* 定义动态链表数据结构 */};void output(struct Node*);/*扫描输出函数*/void scaner(); /*词法分析*/void getbc();void getch();void concat();int letter(char ch);int degit(char ch);int reserve();void retract();void back(char *a,char *b);struct Node *head,*p;char ch; /*全局变量*/char *key[]={"float","int","char","if","else","for","while"}; /*关键字表*/ char token[20]; /*字符数组,存放构成单词的符号串*/int main(void){head=(struct Node *)malloc(LEN); /*分配头节点存储空间*/if(!head){printf("error");exit(1);}head->next=NULL;head->data=' ';p=head;printf("When input a \'$\' at the beigining of an line,this programe will be over.\n"); printf("And the programe will output the codes you inputed just now.\n");printf("Please input your codes:\n");while(1){int i=0;char temp[256];/*每行长度不超过256个字符*/gets(temp); /*输入源程序,以行为单位*/if(temp[0]=='$') break;/*当输入的第一个字符为$时表示输入源代码结束*/p->next=(struct Node *)malloc(LEN);if(!(head->next)){printf("error");exit(1);}p=p->next;while(temp[i]!='\0' && i<256) /*将输入的代码以行为单位存入缓冲区*/{p->data=temp[i];p->next=(struct Node *)malloc(LEN);if(!(p->next)){printf("error");exit(1);}p=p->next;i++;}p->data='\n';p->next=NULL; /*尾结点*/}output(head); /*扫描缓冲区,输出结果*/p=head->next;while(p->next!=NULL)scaner(); /*词法分析*/system("pause");return 0;}void output(struct Node *head) /*扫描缓冲区函数*/{if(!head) {printf("error");exit(1);}p=head->next;while(p->next!=NULL){printf("%c",p->data);p=p->next;}printf("\n");}void getbc() /*若ch中是空白字符,则不停调用getch()直到读入的不是空白字符为止*/ {while (ch==' ')getch();}void getch() /*从缓冲区读入一字符*/{ch=p->data;p=p->next;}void concat() /*将ch中的字符连接到token的后面*/{unsigned int i;i=strlen(token);token[i]=ch;token[i+1]='\0';}int letter(char ch) /*判断ch中的是否是字母*/{return isalpha((int)ch);}int digit(char ch) /*判断ch中的是否是数字*/{return isdigit((int)ch);}int reserve() /*判断token中的字符串是否是关键字或是标识符*/{int k;for(k=0;k<6;k++){if(strcmp(key[k],token)==0)return (k+1);}return 0;}void retract() /*指针回退一个字符*/{struct Node *Q;Q=head->next;while(Q->next!=p)Q=Q->next;p=Q;}void back(char *a,char *b) /*返回函数,输出序列*/ {printf("(%s,%s)\n",a,b);}void scaner() /*词法分析函数*/{int c;token[0]=NULL; /*将token清空*/getch();getbc(); /*读入一个单词*/if(letter(ch)) /*处理字符的情况*/{while(letter(ch)||digit(ch)){concat();getch();}retract();c=reserve();if(c!=0)back(token,"_");elseback("id",token);}else if(digit(ch)) /*处理数字的情况*/{while(digit(ch)){concat();getch();}retract();printf("(num,%d)\n",atoi(token));}elseswitch(ch) /*处理特殊符号的情况*/{case'+': back("+","_");break;case'-': back("-","_");break;case'*': back("*","_");break;case'/': back("/","_");break;case'<': getch();if(ch=='=')back("<=","_");retract();back("<","_");break;case'>': getch();if(ch=='=') back(">=","_"); retract();back(">","_");break;case';': back(";","_");break;case'{': back("{","_");break;case'}': back("}","_");break;case'(': back("(","_");break;case')': back(")","_");break;case'=': back("=","_");break;case',': back(",","_");break;case'\n': break;default: printf("error");break;}}照着课件上敲的p.s. 老师的【输出样例】最后一个错了 :)这个是上传的 txt 格式文件 [点击查看][/watermark]另外一个此法分析器#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <malloc.h>#include <ctype.h>#include <conio.h>#define NULL 0FILE *fp;char ch;char *key视频教程'>word[8]={"do","begin","else","end","if","then","var","while"}; char *operatornum[4]={"+","-","*","/"};char *comparison[6]={"<","<=","=",">",">=","<>"};char *interpunction[6]={",",";",":=",".","(",")"};//////////////////////////////////////////////////////////////////////////////////////////bool search(char searchstr[],int wordtype){int i;switch (wordtype){case 1:for(i=0;i<=7;i++){if(strcmp(keyword[i],searchstr)==0)return(true);}case 2:{for(i=0;i<=3;i++){if(strcmp(operatornum[i],searchstr)==0)return(true);}break;}case 3: for(i=0;i<=5;i++){if(strcmp(comparison[i],searchstr)==0)return(true);}case 4: for(i=0;i<=5;i++){if(strcmp(interpunction[i],searchstr)==0)return(true);}}return(false);}///////////////////////////////////////////////////////////////////////////////////////////char letterprocess (char ch)//字母处理函数{int i=-1;char letter[20];while (isalnum(ch)!=0){letter[++i]=ch;ch=fgetc(fp);};letter[i+1]='\0';if (search(letter,1)){printf("<%s,->\n",letter);//strcat(letter,"\n");//fputs('<' letter '>\n',outp);}else{printf("<indentifier,%s>\n",letter);//strcat(letter,"\n");//fputs(letter,outp);}return(ch);}///////////////////////////////////////////////////////////////////////////////////////////char numberprocess(char ch)//数字处理程序{int i=-1;char num[20];while (isdigit(ch)!=0){num[++i]=ch;ch=fgetc(fp);}if(isalpha(ch)!=0){while(isspace(ch)==0){num[++i]=ch;ch=fgetc(fp);}num[i+1]='\0';printf("错误!非法标识符:%s\n",num);goto u;}num[i+1]='\0';printf("<num,%s>\n",num);//strcat(num,"\n");//fputs(num,outp);u: return(ch);}//////////////////////////////////////////////////////////////////////////////////////////////char otherprocess(char ch){int i=-1;char other[20];if (isspace(ch)!=0){ch=fgetc(fp);goto u;}while ((isspace(ch)==0)&&(isalnum(ch)==0)){other[++i]=ch;ch=fgetc(fp);}other[i+1]='\0';if (search(other,2))printf("<relop,%s>\n",other);elseif (search(other,3))printf("<%s,->\n",other);elseif (search(other,4))printf("<%s,->\n",other);elseprintf("错误!非法字符:%s\n",other);u: return (ch);}/////////////////////////////////////////////////////////////////////////////////////////////void main (){char str,c;printf("**********************************词法分析器************************************\n");//outp=fopen("二元式表.txt","w");if ((fp=fopen("源程序.txt","r"))==NULL)printf("源程序无法打开!\n");else{str =fgetc(fp);while (str!=EOF){if (isalpha(str)!=0)str=letterprocess(str);else{if (isdigit(str)!=0)str=numberprocess(str);elsestr=otherprocess(str);}};printf("词法分析结束,谢谢使用!\n");printf("点任意键退出!\n");}c=getch();}本文章来自 21视频教程网词法分析器_C语言程序设计教程原文链接:/html/61641.shtml。
编译原理语法分析报告+代码
编译原理语法分析报告+代码1000字一、语法分析语法分析是编译器的重要部分,它的作用是对源程序进行分析和判断,判断源程序是否符合语法规则,把源程序划分为一个个语法单元,并建立语法树,这里介绍一种常见的语法分析方法——LR(1)分析。
1.LR(1)分析LR(1)分析是一种自底向上的语法分析方法,它是以LR语法分析机为基础的。
LR(1)分析是在扫描整个输入的基础上作出决策的,名字中的1表示当扫描到一个符号时,它会读下一个符号来做决策并且仅仅读一个符号。
2.LR(1)分析器构建构建LR(1)分析器首先需要构建LR(1)自动机,然后对其进行分析,得到一个分析表。
分析表有两个函数:action和goto。
分析表的行是状态,列是终结符或非终结符,如果分析表的项中既包含action又包含goto,那么这个表就是一个LR(1)分析表。
3.核心算法核心算法就是通过分析表进行分析,具体步骤如下:(1)创建一个栈,将一个状态push入栈。
(2)循环扫描输入,每扫描一个符号就执行一个操作,直到栈为空。
(3)在栈的顶部状态上查找action表。
如果输入符号是一个终结符,那么应该执行的动作是shift。
如果输入符号是一个结束符号,那么说明输入已经结束,执行acc(accept)操作。
(4)如果找到了一个shift,就将其作为下一个状态push入栈,并将上次扫描到的符号作为标记push入栈。
(5)否则,在栈的顶部状态上查找goto表。
在状态表中查找新状态,并将其push入栈。
常见的错误处理:(1)在action表中找不到适当的输入:语法错误,报错。
(2)在goto表中找不到适当的输入:一个状态不能在当前符号的词法单元下产生任何变化。
4.算法实现这里提供一个简单的C++代码实现。
1)自动机的结构体声明:struct Automaton {int status; // 状态编号char symbol; // 符号int go_to; // 跳转状态int move_type; // 移动类型Automaton() : status(-1), symbol(0), go_to(-1),move_type(-1) {}};2)分析表结构体声明:struct AnalyzeTable {static const int ROWS = 100; // 分析表行数static const int COLS = 100; // 分析表列数Automaton analyze_table[ROWS][COLS]; // 分析表};3)LR(1)分析器的实现:class LR1Parser {public:LR1Parser(const std::string& grammar_file); // 构造函数~LR1Parser();void parse(const std::string& input_file); // 解析函数private:std::map<char, std::vector<std::string>> productions_; // 产生式std::map<char, std::set<char>> first_; // First集合std::map<char, std::set<char>> follow_; // Follow集合AnalyzeTable analyze_table_; // 分析表};4)分析表构建函数实现:void LR1Parser::build_analyze_table() {// 对于每个项A -> α.Bβ, a,把它添加到一个集合中。
编译原理LL(1)语法分析器java版完整源代码
编译原理LL(1)语法分析器java版完整源代码public class Accept2 {public static StringBuffer stack=new StringBuffer("#E");public static StringBuffer stack2=new StringBuffer("i+i*#");public static void main(String arts[]){//stack2.deleteCharAt(0);System.out.print(accept(stack,stack2));}public static boolean accept(StringBuffer stack,StringBuffer stack2){//判断识别与否boolean result=true;outer:while (true) {System.out.format("%-9s",stack+"");System.out.format("%9s",stack2+"\n");char c1 = stack.charAt(stack.length() - 1);char c2 = stack2.charAt(0);if(c1=='#'&&c2=='#')return true;switch (c1) {case'E':if(!E(c2)) {result=false;break outer;}break;case'P': //P代表E’if(!P(c2)) {result=false;break outer;}break;case'T':if(!T(c2)) {result=false;break outer;}break;case'Q': //Q代表T’if(!Q(c2)) {result=false;break outer;}break;case'F':if(!F(c2)) {result=false;break outer;}break;default: {//终结符的时候if(c2==c1){//System.out.println();}else{return false;}}}if(result=false)break outer;}return result;}public static boolean E(char c) {//语法分析⼦程序 E boolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("PT");}else if(c=='('){stack.deleteCharAt(stack.length()-1);stack.append("PT");else{System.err.println("E 推导时错误!不能匹配!"); result=false;}return result;}public static boolean P(char c){//语法分析⼦程序 P boolean result=true;if(c=='+') {stack.deleteCharAt(stack.length()-1);stack.append("PT+");}else if(c==')') {//stack.append("");System.out.println("P->/");}else if(c=='#') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("P->/");else{System.err.println("P 推导时错误!不能匹配!");result=false;}return result;}public static boolean T(char c) {//语法分析⼦程序 Tboolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("QF");}else if(c=='(') {stack.deleteCharAt(stack.length()-1);stack.append("QF");}else{result=false;System.err.println("T 推导时错误!不能匹配!");}return result;public static boolean Q(char c){//语法分析⼦程序 Q boolean result=true; if(c=='+') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}stack.deleteCharAt(stack.length()-1);stack.append("QF*");}else if(c==')') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}else if(c=='#') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}else{result=false;System.err.println("Q 推导时错误!不能匹配!"); }return result;}public static boolean F(char c) {//语法分析⼦程序 F boolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("i");}else if(c=='(') {stack.deleteCharAt(stack.length()-1);stack.append(")E(");}else{result=false;System.err.println("F 推导时错误!不能匹配!"); }return result;/* public static StringBuffer changeOrder(String s){//左右交换顺序StringBuffer sb=new StringBuffer();for(int i=0;isb.append(s.charAt(s.length()-1-i));}return sb;}*/}#E i+i*i+i##PT i+i*i+i##PQF i+i*i+i##PQi i+i*i+i##PQ +i*i+i#Q->/#P +i*i+i##PT+ +i*i+i##PT i*i+i##PQF i*i+i##PQi i*i+i##PQ *i+i##PQF* *i+i##PQF i+i##PQi i+i##PQ +i#Q->/#P +i##PT+ +i##PT i##PQF i##PQi i##PQ #Q->/#P #P->/True#E i+i*##PT i+i*##PQF i+i*##PQi i+i*##PQ +i*#Q->/#P +i*##PT+ +i*##PT i*##PQF i*##PQi i*##PQ *##PQF* *##PQF #falseF 推导时错误!不能匹配!。
编译原理_语法分析器
编译原理实验报告语法分析器一.实验目的及内容实验目的:编制一个语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析。
实验内容:在上机(一)词法分析的基础上,采用递归子程序法或其他适合的语法分析方法,实现其语法分析程序。
要求编译后能检查出语法错误。
已知待分析的C语言子集的语法,用EBNF表示如下:<程序>→main()<语句块><语句块> →‘{’<语句串>‘}’<语句串> → <语句> {; <语句> };<语句> → <赋值语句> |<条件语句>|<循环语句><赋值语句>→ID=<表达式><条件语句>→if‘(‘条件’)’<语句块><循环语句>→while’(‘<条件>’)‘<语句块><条件> → <表达式><关系运算符> <表达式><表达式> →<项>{+<项>|-<项>}<项> → <因子> {* <因子> |/ <因子>}<因子> →ID|NUM| ‘(’<表达式>‘)’<关系运算符> →<|<=|>|>=|==|!=二、实验原理及基本技术路线图(方框原理图或程序流程图)三、所用仪器、材料(设备名称、型号、规格等或使用软件)1台PC以及VISUAL C++6.0软件四、实验方法、步骤(或:程序代码或操作过程)#include <iostream>#include <string>using namespace std;char prog[80],token[8];char ch;int syn,p,m,n,sum,k=0;char *key[6]={"main","int","char","if","else","while"};void scaner();void lrparser();void yucu();void statement();void expression();void term();void factor();void main(){p=0;cout<<"语法分析"<<endl;cout<<"请输入字符串,以“@”结尾:"<<endl;do {ch = getchar(); prog[p++]=ch;}while(ch!='@');p=0;scaner();lrparser();}void scaner(){sum=m=0;for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' ') ch=prog[p++];if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) {token[m++]=ch; ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,key[n])==0){syn=n+1; break;}}else if(ch>='0'&&ch<='9'){while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=20;}elseswitch(ch){case '<': m=0;token[m++]=ch;ch=prog[p++];if(ch=='<') {syn=33; token[m++]=ch;}else if(ch=='=') {syn=35; token[m++]=ch;}break;case '>': m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=34; token[m++]=ch;}else {syn=32; p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=36;token[m++]=ch;}else{ syn=21;p--;}break;case ':': m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=18; token[m++]=ch;}else {syn=17; p--;}break;case '+': syn=22; token[0]=ch; break;case '-': syn=23; token[0]=ch; break;case '*': syn=24; token[0]=ch; break;case '/': syn=25; token[0]=ch; break;case ';': syn=31; token[0]=ch; break;case '(': syn=26; token[0]=ch; break;case ')': syn=27; token[0]=ch; break;case '@': syn=0; token[0]=ch; break;default : syn=-1;}}void lrparser(){if(syn==1){scaner();yucu();if(syn=6){scaner();if(syn==0 && (k==0))cout<<"\nsuccess\n"<<endl;}else{if(k!=1)cout<<"\nwhile error\n"<<endl;k=1;}}else{cout<<"\nmain error\n"<<endl;k=1;}return;}void yucu(){statement();while(syn==31){scaner();statement();}return;}void statement(){if(syn==10){scaner();if(syn==18){scaner();expression();}else{cout<<"\nscentence error\n"<<endl;k=1;}}return;}void expression(){term();while(syn==22||syn==23){scaner();term();}return;}void term(){factor();while(syn==24||syn==25){scaner();factor();}return;}void factor(){if(syn==10||syn==20)scaner();else if(syn==26){scaner();expression();if(syn==27)scaner();else{cout<<"( error"<<endl;k=1;}}else{cout<<"expression error"<<endl;k=1;}return;}五、实验过程原始记录( 测试数据、图表、计算等)六、实验结果、分析和结论(误差分析与数据处理、成果总结等。
编译原理语法分析器(完美运行版)
学院(系)名称:计算机工程系实验环境:Windows XP实验分析:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分实验程序:#include<iostream>#include<stack>using namespace std;stack<char> symbol;stack<int> state;char sen[50];char sym[12][6]={//符号表{'s','e','e','s','e','e'},{'e','s','e','e','e','a'},{'r','r','s','r','r','r'},{'r','r','r','r','r','r'},{'s','e','e','s','e','e'},{'r','r','r','r','r','r'},{'s','e','e','s','e','e'},{'s','e','e','s','e','e'},{'e','s','e','e','s','e'},{'r','r','s','r','r','r'},{'r','r','r','r','r','r'},{'r','r','r','r','r','r'}};char snum[12][6]={//数字表{5,1,1,4,2,1},{3,6,5,3,2,0},{2,2,7,2,2,2},{4,4,4,4,4,4},{5,1,1,4,2,1},{6,6,6,6,6,6},{5,1,1,4,2,1},{5,1,1,4,2,1},{3,6,5,3,11,4},{1,1,7,1,1,1},{3,3,3,3,3,3},{5,5,5,5,5,5}};int go2[12][3]={//goto表{1,2,3},{0,0,0},{0,0,0},{0,0,0},{8,2,3},{0,0,0},{0,9,3},{0,0,10},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};void action(int i,char *&a,char &how,int &num,char &A,int &b)//action函数[i,a] {int j;switch(*a){case 'i':j=0;break;case '+':j=1;break;case '*':j=2;break;case '(':j=3;break;case ')':j=4;break;case '#':j=5;break;default:j=-1;break;}if(j!=-1){how=sym[i][j];num=snum[i][j];if(how=='r'){switch(num){case 1:A='E',b=3;cout<<"按E->E+T规约"<<endl; break;case 2:A='E',b=1;cout<<"按E->T规约"<<endl; break;case 3:A='T',b=3;cout<<"按T->T*F规约"<<endl; break;case 4:A='T',b=1;cout<<"按T->F规约"<<endl; break;case 5:A='F',b=3;cout<<"按F->(E)规约"<<endl; break;case 6:A='F',b=1;cout<<"按F->id规约"<<endl; break;default:break;}}}}int go(int t,char A)//goto[t,A] {switch(A){case 'E':return go2[t][0];break;case 'T':return go2[t][1];break;case 'F':return go2[t][2];break;}}void error(int i,int j,char *&a)//error处理函数{cout<<"error"<<endl;switch(j){case 1://期望输入id或左括号,但是碰到+,*,或$,就假设已经输入id了,转到状态5 state.push(5);symbol.push('i');//必须有这个,如果假设输入id的话,符号栈里必须有....cout<<"缺少运算对象id"<<endl;break;case 2://从输入中删除右括号a++;cout<<"不配对的右括号"<<endl;break;case 3://期望碰到+,但是输入id或左括号,假设已经输入算符+,转到状态6state.push(6);symbol.push('+');cout<<"缺少运算符"<<endl;break;case 4://缺少右括号,假设已经输入右括号,转到状态11state.push(11);symbol.push(')');cout<<"缺少右括号"<<endl;break;case 5:a++;cout<<"*号无效,应该输入+号!"<<endl;case 6:a++;}}int main(){int s;char *a;char how;int num;int b;char A;while(1){cin>>sen;a=sen;state.push(0);//先输入0状态while(*a!='\0'){b=0;num=0;how='\0';A='\0';s=state.top();action(s,a,how,num,A,b);if(how=='s')//移进{cout<<"移进"<<endl;symbol.push(*a);state.push(num);// if(*a=='i')// a++;//在这里忽略i后面的da++;}else if(how=='r')//规约{for(int i=0;i<b;i++){if(!state.empty())state.pop();if(!symbol.empty())symbol.pop();}int t=state.top();symbol.push(A);state.push(go(t,A));}else if(how=='a')//接受break;else{error(s,num,a);//错误处理}}cout<<"成功接受"<<endl;}return 0;}测试用例:i*(i+i)+i#测试结果:心得体会:通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,实验过程中对于程序的逻辑理解欠缺了考虑,在多次的调试和改进中最终完善了程序,而在调试过程中学习的知识得到了完善和补充,对语法分析器的理解更进一步。
编译原理语法分析报告+代码
语法分析一、实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、实验要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1 待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>::=begin<语句串>end⑵<语句串>::=<语句>{;<语句>}⑶<语句>::=<赋值语句>⑷<赋值语句>::=ID:=<表达式>⑸<表达式>::=<项>{+<项> | -<项>}⑹<项>::=<因子>{*<因子> | /<因子>⑺<因子>::=ID | NUM | (<表达式>)2.2 实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
例如:输入begin a:=9; x:=2*3; b:=a+x end #输出success!输入x:=a+b*c end #输出error2.3 语法分析程序的酸法思想(1)主程序示意图如图2-1所示。
图2-1 语法分析主程序示意图(2)递归下降分析程序示意图如图2-2所示。
(3)语句串分析过程示意图如图2-3所示。
图2-3 语句串分析示意图图2-2 递归下降分析程序示意图(4)statement语句分析程序流程如图2-4、2-5、2-6、2-7所示。
图2-4 statement语句分析函数示意图图2-5 expression表达式分析函数示意图图2-7 factor分析过程示意图三、语法分析程序的C语言程序源代码:#include "stdio.h"#include "string.h"char prog[100],token[8],ch;char *rwtab[6]={"begin","if","then","while","do","end"};int syn,p,m,n,sum;int kk;factor();expression();yucu();term();statement();lrparser();scaner();main(){p=kk=0;printf("\nplease input a string (end with '#'): \n");do{ scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}lrparser(){if(syn==1){scaner(); /*读下一个单词符号*/yucu(); /*调用yucu()函数;*/if (syn==6){ scaner();if ((syn==0)&&(kk==0))printf("success!\n");}else { if(kk!=1) printf("the string haven't got a 'end'!\n");kk=1;}}else { printf("haven't got a 'begin'!\n");kk=1;}return;}yucu(){statement(); /*调用函数statement();*/while(syn==26){scaner(); /*读下一个单词符号*/if(syn!=6)statement(); /*调用函数statement();*/}return;}statement(){ if(syn==10){scaner(); /*读下一个单词符号*/if(syn==18){ scaner(); /*读下一个单词符号*/ expression(); /*调用函数statement();*/ }else { printf("the sing ':=' is wrong!\n");kk=1;}}else { printf("wrong sentence!\n");kk=1;}return;}expression(){ term();while((syn==13)||(syn==14)){ scaner(); /*读下一个单词符号*/ term(); /*调用函数term();*/}return;}term(){ factor();while((syn==15)||(syn==16)){ scaner(); /*读下一个单词符号*/ factor(); /*调用函数factor(); */ }return;}factor(){ if((syn==10)||(syn==11)) scaner();else if(syn==27){ scaner(); /*读下一个单词符号*/expression(); /*调用函数statement();*/ if(syn==28)scaner(); /*读下一个单词符号*/else { printf("the error on '('\n");kk=1;}}else { printf("the expression error!\n");kk=1;}return;}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;m=0;ch=prog[p++];while(ch==' ')ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;token[m++]='\0';for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){ while((ch>='0')&&(ch<='9')){ sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':m=0;ch=prog[p++];if(ch=='>'){ syn=21;}else if(ch=='='){ syn=22;}else{ syn=20;p--;}break;case '>':m=0;ch=prog[p++];if(ch=='='){ syn=24;}else{ syn=23;p--;}break;case ':':m=0;ch=prog[p++];if(ch=='='){ syn=18;}else{ syn=17;p--;}break;case '+': syn=13; break;case '-': syn=14; break;case '*': syn=15;break;case '/': syn=16;break;case '(': syn=27;break;case ')': syn=28;break;case '=': syn=25;break;case ';': syn=26;break;case '#': syn=0;break;default: syn=-1;break;}}四、结果分析:输入begin a:=9; x:=2*3; b:=a+x end # 后输出success!如图4-1所示:图4-1输入x:=a+b*c end # 后输出error 如图4-2所示:图4-2五、总结:通过本次试验,了解了语法分析的运行过程,主程序大致流程为:“置初值”→调用scaner 函数读下一个单词符号→调用IrParse→结束。
编译原理(第三版)语法分析器
编译原理(第三版)语法分析器语法分析器在词法分析器的基础上增加了递归下降分析程序,咱也不知道啥是递归下降程序,咱也不想问。
但是有程序框图和伪代码把程序跑通咱还是⽐较在⾏滴。
为了便于理解,debug过程中的输出也保留了。
下⾯是完整代码。
1/*2 begin a:= 9; x:=2*3;b:=a+x end#3 x:= a+b*c end #4*/5 #include <stdio.h>6 #include <stdlib.h>7 #include <string.h>8#define _KEY_WORD_END "waiting for your expanding"9 typedef struct10 {11int typenum;12char *word;13 }WORD;14char input[255];15char token[255]="";16int p_input;17int p_token;18char ch;19char* rwtab[] = {"begin","if","then","while","do","end",_KEY_WORD_END};20 WORD * scaner();21 WORD* oneword = new WORD;22int syn,kk;23void expression();24void factor()25 {26if(syn == 10 || syn == 11)27 {28 oneword = scaner();29 syn = oneword->typenum;30 printf("%s %d\n",oneword->word,syn);31 }32else if(syn == 27)33 {34 oneword = scaner();35 syn = oneword->typenum;36 printf("%s %d\n",oneword->word,syn);37 expression();38if(syn == 28)39 {40 oneword = scaner();41 syn = oneword->typenum;42 printf("%s %d\n",oneword->word,syn);43 }44else{45 printf("右括号错误\n");46 kk = 1;47 }48 }49else50 {51 printf("表达式错误\n");52 kk = 1;53 }54return;55 }56void term()57 {58 factor();59while(syn == 15 || syn == 16)60 {61 oneword = scaner();62 syn = oneword->typenum;63 printf("%s %d\n",oneword->word,syn);64 factor();65 }66return;67 }68void expression()69 {70 term();71while(syn == 13 || syn == 14)72 {73 oneword = scaner();74 syn = oneword->typenum;75 printf("%s %d\n",oneword->word,syn);76 term();77 }78return;79 }80void statement()81 {82if(syn == 10)83 {84 oneword = scaner();85 syn = oneword->typenum;86 printf("%s %d\n",oneword->word,syn); 87if(syn == 18)88 {89 oneword = scaner();90 syn = oneword->typenum;91 printf("%s %d\n",oneword->word,syn);92 expression();93 }94else{95 printf("赋值号错误\n");96 kk = 1;97 }98 }99else{100 printf("语句错误\n");101 kk = 1;102 }103return;104 }105void yucu()106 {107 statement();108while(syn == 26)109 {110 oneword = scaner();111 syn = oneword->typenum;112 printf("%s %d\n",oneword->word,syn); 113 statement();114 }115return;116 }117void Irparser()118 {119if(syn == 1)120 {121 oneword = scaner();122 syn = oneword->typenum;123 printf("%s %d\n",oneword->word,syn);124 yucu();125126if(syn==6)127 {128 oneword = scaner();129 syn = oneword->typenum;130if(syn == 0 && (kk == 0))131 printf("success\n");132 }133else{134if(kk != 1)135 {136 printf("缺少end错误\n");137 kk = 1;138 }139 }140 }141else{142 printf("begin错误\n");143 kk = 1;144 }145return;146 }147int main()148 {149int over = 1;150151 printf("Enter Your words(end with #):");152 scanf("%[^#]s",input);153 p_input = 0;154 printf("Your words:\n%s\n",input);155156//获取下⼀个单词符号157 oneword = scaner();158 syn = oneword->typenum;159 Irparser();160161 printf("\npress # to exit:");162 scanf("%[^#]s",input);163return0;164 }165char m_getch()166 {167 ch = input[p_input];168 p_input = p_input+1;169return(ch);170 }171void getbc()172 {173while(ch == ''||ch == 10)174 {175 ch = input[p_input];176 p_input++;177 }178 }179void concat()180 {181 token[p_token] = ch;182 p_token++;183 token[p_token] = '\0';184 }185int letter()186 {187if((ch >= 'a'&& ch <= 'z')|| (ch >='A'&&ch <= 'Z')) 188return1;189else190return0;191 }192int digit()193 {194if(ch >= '0'&&ch <='9')return1;195else return0;196 }197int reserve()198 {199int i = 0;200while(strcmp(rwtab[i],_KEY_WORD_END))201 {202if(!strcmp(rwtab[i],token))203return i+1;204 i++;205 }206return10;207 }208void retract()209 {210 p_input--;211 }212213char* dtb()214 {215return NULL;216 }217218 WORD* scaner()219 {220221 WORD* myword = new WORD; 222 myword->typenum = 10;223 myword->word = "";224 p_token = 0;225 m_getch();226 getbc();227if(letter())228 {229while(letter()||digit())230 {231 concat();232 m_getch();233 }234 retract();235 myword->typenum = reserve(); 236 myword->word = token;237return(myword);238 }239else if(digit())240 {241while(digit())242 {243 concat();244 m_getch();245 }246 retract();247 myword->typenum = 11;248 myword->word = token;249return(myword);250 }251else switch(ch)252 {253case'=':m_getch();254if(ch == '=')255 {256 myword->typenum = 25; 257 myword->word = "=="; 258return(myword);259 }260 retract();261 myword->typenum = 21; 262 myword->word = "=";263return(myword);264break;265case'+':266 myword->typenum = 13; 267 myword->word = "+";268return(myword);269break;270case'-':271 myword->typenum = 14; 272 myword->word = "-";273return(myword);274break;275case'*':276 myword->typenum = 15; 277 myword->word = "*";278return(myword);279break;280case'/':281 myword->typenum = 16; 282 myword->word = "/";283return(myword);284break;289break;290case')':291 myword->typenum = 28; 292 myword->word = ")";293return(myword);294break;295case'[':296 myword->typenum = 28; 297 myword->word = "[";298return(myword);299break;300case']':301 myword->typenum = 29; 302 myword->word = "]";303return(myword);304break;305case'{':306 myword->typenum = 30; 307 myword->word = "{";308return(myword);309break;310case'}':311 myword->typenum = 31; 312 myword->word = "}";313return(myword);314break;315case',':316 myword->typenum = 32; 317 myword->word = ",";318return(myword);319break;320case':':m_getch();321if(ch == '=')322 {323 myword->typenum = 18; 324 myword->word = ":="; 325return(myword);326 }327 retract();328 myword->typenum = 17; 329 myword->word = ":";330return(myword);331break;332case';':333 myword->typenum = 26; 334 myword->word = ";";335return(myword);336break;337case'>':m_getch();338if(ch == '=')339 {340 myword->typenum = 24; 341 myword->word = ">="; 342return(myword);343 }344 retract();345 myword->typenum = 23; 346 myword->word = ">";347return(myword);348break;349case'<':m_getch();350if(ch == '=')351 {352 myword->typenum = 22; 353 myword->word = "<="; 354return(myword);355 }356else if(ch == '>')357 {358 myword->typenum = 21; 359 myword->word = "<>"; 360return(myword);361 }362 retract();363 myword->typenum = 20; 364 myword->word = "<";365return(myword);366break;367case'!':m_getch();368if(ch == '=')373 }374 retract();375 myword->typenum = -1; 376 myword->word = "ERROR"; 377return(myword);378break;379case'#':380 myword->typenum = 0;381 myword->word = "#";382return(myword);383break;384case'\0':385 myword->typenum = 0;386 myword->word = "OVER"; 387return(myword);388break;389default: myword->typenum = -1; 390 myword->word = "ERROR"; 391return(myword);392 }393 }。
语法分析器
实验二:语法分析器
课程ห้องสมุดไป่ตู้称:编译原理
学院:计算机科学与工程
班级:
姓名:
学号:
教师:李拥军
2015年01月06日
一、
设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析的理解掌握以及高级语言语法结构的定义,掌握语法分析的常用方法
二、
(1)操作系统:Windows 7
(2)编程环境:Visual Studio 2010
要实现上术的语法分析需要增加一些常量:
typedef enum {StmtK,ExpK} NodeKind;
typedef enum {IfK,RepeatK,AssignK,ReadK,WriteK,WhileK} StmtKind;
typedef enum {OpK,ConstK,IdK,StrK,BoolK} ExpKind;
S.code=Label S.begin||Seq.code||Label Seq.next||E.code
S->if E then S1 end
E.true=newlabel;
E.fasle=S.next
S1.next=S.next
S.code=E.code || gen(E.true) || S1.code
match(ID);
while(token==COMMA)
{
match(COMMA);
st_insert(tokenString,type,lineno,location++);
match(ID);
}
match(SEMI);//';' is expected
}
语法分析器
实验二:语法分析器一、 实验目的:1.强化对系统软件综合工程实现能力的训练;2.采用各种设计方法实现语法分析程序;二、 实验内容:语言的语法分析程序的实用C语言或者其他的高级语言作为宿主语言完成C1现。
三、 实验要求:语言的语法分析器,生成语法分析树。
其中语法分析程序既可以1.实现C1自己手动去完成,也可以利用YACC自动生成。
程序的输入:C语言源程序或者词法分析阶段的输出文件程序的输出:存储了语法分析树信息的XML格式的文件2. 通过测试程序的验收;3.实验报告按照提供的模板填写:(1)功能描述:该程序具有什么功能?(2)程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;另外可以附加函数之间的调用关系图、程序总体执行流程图。
(3)实验总结:你在编程过程中花时多少?多少时间在纸上设计?多少时间上机输入和调试?多少时间在思考问题?遇到了哪些难题?你是怎么克服的?你对你的程序的评价?你的收获有哪些?四、 评判标准:1. 程序的正确性;2. 程序结构清晰,代码规范;3. 提交报告,报告阐述清楚。
五、 程序工作说明:(以C1语言为例)程序的输入是C语言源程序或者前一阶段词法分析器的输出文件。
程序的输出为包含了语法树相关信息的XML格式的文件程序输入/输出示例:如源程序为如下:1.void f1(int a,int b) {2. a = 1;3. b = a+b;4.}5.void main()6.{7. int a[100];8. int b;9. float c;10. a[b]=a;11. if(c<b){12. f1(a,b);13. }14.}那么词法分析输出文件:<?xml version="1.0"?><root><token line="1" type="VOID" string="void" /> <token line="1" type="ID" string="f1" /><token line="1" type="LPAREN" string="(" /> <token line="1" type="INT" string="int" /> <token line="1" type="ID" string="a" /><token line="1" type="COMMA" string="," /> <token line="1" type="INT" string="int" /> <token line="1" type="ID" string="b" /><token line="1" type="RPAREN" string=")" /> <token line="1" type="LBRACE" string="{" /> <token line="2" type="ID" string="a" /><token line="2" type="ASSIGN" string="=" /> <token line="2" type="NUMBER" string="1" /> <token line="2" type="SEMI" string=";" /> <token line="3" type="ID" string="b" /><token line="3" type="ASSIGN" string="=" /> <token line="3" type="ID" string="a" /><token line="3" type="ADD" string="+" /><token line="3" type="ID" string="b" /><token line="3" type="SEMI" string=";" /> <token line="4" type="RBRACE" string="}" /> <token line="5" type="VOID" string="void" /> <token line="5" type="ID" string="main" /> <token line="5" type="LPAREN" string="(" /> <token line="5" type="RPAREN" string=")" /> <token line="6" type="LBRACE" string="{" /> <token line="7" type="INT" string="int" />>>><token line="7" type="ID" string="a" />><token line="7" type="ASSIGN" string="=" />><token line="7" type="LSQUAR" string="[" /><token line="7" type="NUMBER" string="100" /><token line="7" type="RSQUAR" string="]" /><token line="7" type="SEMI" string=";" /><token line="8" type="INT" string="int" /><token line="8" type="ID" string="b" /><token line="8" type="SEMI" string=";" /><token line="9" type="FLOAT" string="float" /> <token line="9" type="ID" string="c" /><token line="9" type="SEMI" string=";" /><token line="10" type="ID" string="a" /><token line="10" type="LSQUAR" string="[" /><token line="10" type="ID" string="b" /><token line="10" type="RSQUAR" string="]" /><token line="10" type="ASSIGN" string="=" /><token line="10" type="ID" string="a" /><token line="10" type="SEMI" string=";" /><token line="11" type="IF" string="if" /><token line="11" type="LPAREN" string="(" /><token line="11" type="ID" string="c" /><token line="11" type="LT" string="<" /><token line="11" type="ID" string="b" /><token line="11" type="LBRACE" string="{" /><token line="12" type="ID" string="f1" /><token line="12" type="LPAREN" string="(" /><token line="12" type="ID" string="a" /><token line="12" type="COMMA" string="," /><token line="12" type="ID" string="b" /><token line="12" type="SEMI" string=";" /><token line="13" type="RBRACE" string="}" /><token line="14" type="RBRACE" string="}" /></root>语法分析器以此文件作为输入,产生以下输出文件:<?xml version="1.0" ?><file name="test.c">line="1"<Prog<DecListline="1"line="1"<Declline="1"<FunDecl/line="1"<TypeSpecstring="void"<ID line="1" string="f1" /><LPARTEN line="1" string="(" /><ID line="1" string="a" /><ID line="1" string="b" /><RPARTEN line="1" string=")" /><CompStmt line="1"><LBRACE line="2" string="{" /> <LoclDecls line="2" /> <StmtList line="2"> <Stmt line="2"> <ExprStmt line="2"> <Expr line="2"> <Var line="2"><ID line="2" string="a" /></Var > <ASMT line="2" string="=" /><Expr line="2"> <SimpExpr line="2"> <AddExpr line="2"> <Term line="2"> <Factor line="2"> <NUMBER line="2" string="1" /> </Factor > </Term > </AddExpr > </SimpExpr > </Expr ></Expr ><SEMI line="2" string=";" /></ExprStmt ></Stmt >...六、 参考书目:1. Kenneth C. Louden 著,冯博琴译《编译原理及实践》,机械工业出版社,2000年2. Andrew W.Appel 著,赵克佳等译《现代编译原理C 语言描述》人民邮电出版社,2006年3. 陈火旺,刘春林等,《程序设计语言编译原理》第三版,国防科大出版社,2001年。
编译原理-语法分析器-(java完美运行版)教学文案
编译原理-语法分析器-(j a v a完美运行版)实验二语法分析器一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验内容◆根据某一文法编制调试 LL ( 1 )分析程序,以便对任意输入的符号串进行分析。
◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。
◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
三、 LL(1)分析法实验设计思想及算法◆模块结构:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
四、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、如果遇到错误的表达式,应输出错误提示信息。
3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:五、实验源程序LL1.javaimport java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.sql.*;import java.util.Vector;public class LL1 extends JFrame implements ActionListener {/****/private static final long serialVersionUID = 1L;JTextField tf1;JTextField tf2;JLabel l;JButton b0;JPanel p1,p2,p3;JTextArea t1,t2,t3;JButton b1,b2,b3;JLabel l0,l1,l2,l3,l4;JTable table;Statement sta;Connection conn;ResultSet rs;DefaultTableModel dtm;String Vn[]=null;Vector<String> P=null;int firstComplete[]=null;//存储已判断过first的数据char first[][]=null;//存储最后first结果int followComplete[]=null;//存储已判断过follow的数据char follow[][]=null;//存储最后follow结果char select[][]=null;//存储最后select结果int LL=0;//标记是否为LL(1)String vt_tou[]=null;//储存VtObject shuju[][]=null;//存储表达式数据char yn_null[]=null;//存储能否推出空LL1(){setLocation(100,0);setSize(700,780);tf1=new JTextField(13);tf2=new JTextField(13);l=new JLabel(">>");l0=new JLabel("输入字符串:");l1=new JLabel("输入的文法为:");l2=new JLabel(" ");l3=new JLabel("分析的结果:");l4=new JLabel("预测分析表:");//p1=new JPanel();p2=new JPanel();p3=new JPanel();t1=new JTextArea(24,20);t2=new JTextArea(1,30);t3=new JTextArea(24,40);b0=new JButton("确定(S为开始)");b1=new JButton(" 判断文法 ");b2=new JButton("输入");b3=new JButton("清空");table=new JTable();JScrollPane jp1=new JScrollPane(t1);JScrollPane jp2=new JScrollPane(t2);JScrollPane jp3=new JScrollPane(t3);p2.add(tf1);p2.add(l);p2.add(tf2);p2.add(b0);p2.add(b1);p2.add(l0);p2.add(l2);p2.add(jp2);p2.add(b2);p2.add(b3);p2.add(l1);p2.add(l3);p2.add(jp1);p2.add(jp3);p3.add(l4);p3.add(new JScrollPane(table));add(p2,"Center");add(p3,"South");b0.addActionListener(this);b1.addActionListener(this);b2.addActionListener(this);b3.addActionListener(this);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);table.setPreferredScrollableViewportSize(new Dimension(660,200));setVisible(true);}public void actionPerformed(ActionEvent e){if(e.getSource()==b0){String a=tf1.getText();String b=tf2.getText();t1.append(a+'→'+b+'\n');}if(e.getSource()==b1){t3.setText("");int Vnnum=0,k;Vn=new String[100];P=new Vector<String>();String s[]=t1.getText().split("\n");for(int i=0;i<s.length;i++){if(s.length<2){t3.setText("文法输入有误,请重新输入");//判断长度是否符合return;}if(s[i].charAt(0)<='Z'&&s[i].charAt(0)>='A'&&s[i].charAt( 1)=='→'){for(k=0;k<Vnnum;k++){if(Vn[k].equals(s[i].substring(0, 1))){break;}}if(Vnnum==0||k>=Vnnum){Vn[Vnnum]=s[i].substring(0,1);//存入Vn数据Vnnum++;}P.add(s[i]);}else{t3.setText("文法输入有误,请重新输入");return;}}yn_null=new char[100];first=new char[Vnnum][100];int flag=0;String firstVn[]=null;firstComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++) //依次求FIRST**{flag=0;firstVn=new String[20];if((flag=add_First(first[i],Vn[i],firstVn,flag))==-1)return;firstComplete[i]=1;}t3.append("first集:"+"\n"); //显示FIRST**for(int i=0;Vn[i]!=null;i++)t3.append("first("+Vn[i]+")={ ");for(int j=0;first[i][j]!='\0';j++){t3.append(first[i][j]+" , ");}t3.append("}"+"\n");}follow=new char[Vnnum][100];String followVn[]=null;followComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++) //求FOLLOW**{flag=0;followVn=new String[20];if((flag=tianjiaFollow(follow[i],Vn[i],followVn,flag))==-1)return;followComplete[i]=1;}t3.append("follow集:"+"\n"); //显示FOLLOW**for(int i=0;Vn[i]!=null;i++){t3.append("follow("+Vn[i]+")={ ");for(int j=0;follow[i][j]!='\0';j++){t3.append(follow[i][j]+" , ");}t3.append("}"+"\n");}select=new char[P.size()][100];for(int i=0;i<P.size();i++) //求SELECT**{flag=0;tianjiaSelect(select[i],(String)P.elementAt(i),flag);t3.append("select集:"+"\n"); //显示SELECT**for(int i=0;i<P.size();i++){t3.append("select("+(String)P.elementAt(i)+")={ ");for(int j=0;select[i][j]!='\0';j++){t3.append(select[i][j]+" , ");}t3.append("}"+"\n");}for(int i=0;Vn[i]!=null;i++)//判断select交集是否为空{int biaozhi=0;char save[]=new char[100];for(int j=0;j<P.size();j++){String t=(String)P.elementAt(j);if(t.substring(0,1).equals(Vn[i])) {for(k=0;select[j][k]!='\0';k++) {if(puanduanChar(save,select[j][k])){save[biaozhi]=select[j][k];biaozhi++;}else//当有交集时,不为LL(1)文法{t3.append("不是LL(1)文法!!"+"\n");return;}}}}}char Vt[]=new char[100];int biaozhi=0;for(int i=0;i<P.size();i++){String t=(String)P.elementAt(i);for(int j=2;j<t.length();j++)//提取表达式右侧的终结符存入Vt{if(t.charAt(j)>'Z'||t.charAt(j)<'A') {if(puanduanChar(Vt,t.charAt(j))) {Vt[biaozhi]=t.charAt(j);biaozhi++;}}}}if(puanduanChar(Vt,'#'))//若可推出空集,则将#加入Vt。
编译原理词法分析和语法分析报告+代码(C语言版)
编译原理词法分析和语法分析报告+代码(C语言版)-CAL-FENGHAI.-(YICAI)-Company One1信息工程学院实验报告(2010 ~2011 学年度第一学期)姓名:柳冠天学号:2081908318班级:083词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
编译原理课程设计--语法分析器
计算机类课程设计报告课程名称:编译原理课程设计题目:语法分析器姓名:系:计算机专业:计算机科学与技术年级:学号:指导教师:职称:副教授2011~2012学年第二学期目录1 正则表达式 (1)1.1 正则表达式 (1)1.2 确定化(化简)后的状态转换图 (1)1.3 分析程序代码 (1)1.4 程序运行截图 (2)1.5 小结 (3)2 LL(1)分析 (4)2.1 LL(1)文法 (4)2.2 LL(1)预测分析表 (4)2.3 分析程序代码 (4)2.4 程序运行截图 (7)2.5 小结 (8)参考文献: (8)1 正则表达式1.1 正则表达式ab(a|b)*ba1.2 确定化(化简)后的状态转换图ab1.3 分析程序代码import java.util.Scanner;import java.util.regex.Matcher;import java.util.regex.Pattern;//导入所需要的包public class RegTest {//创建类RegTeststatic boolean test(String s1,String s2){/*编写测试函数返回布尔类型,用于验证输入字符串与要验证的表达式是否符合*/Pattern p=pile(s1);//正则表达式Matcher m=p.matcher(s2);//操作字符串boolean b=false;//p=pile(s1); ////m=p.matcher(s2);b=m.matches();//判断是否满足是则返回true否返回falseif(b==false){System.out.println("您输入的不符合您要求的正则表达式");}else{System.out.println("符合您所输入的正则表达式");}return b;}public static void main(String[] args) {// 主函数Scanner cin=new Scanner(System.in);//用于输入字符串String s;while(true){System.out.println("请输入正则表达式:");String s1=cin.nextLine();System.out.println("请输入字符串:");String s2=cin.nextLine();//输入表达式和要验证的字符串test(s1,s2);//调用函数,测试是否符合要验证的表达式while(true){System.out.println("是否继续验证该表达式?(yes/no)");s=cin.nextLine();//如果还想继续验证刚才输入的表达式,可以继续输入字符串if(!s.equals("yes")){break;}System.out.println("请输入字符串:");s2=cin.nextLine();test(s1,s2);//调用函数,测试是否符合要验证的表达式}System.out.println("是否继续验证正则表达式?(yes/no)");s=cin.nextLine();//如果需要验证其他字符串的话,可以继续输入if(!s.equals("yes")){break;}}}}1.4 程序运行截图1.5 小结总的来说对于正则表达有一定的了解,正则表达简单来说不算难,但是要深入就很难。
编译原理课程设计--- 语法分析器
编译原理课程设计题目语法分析器学生姓名学号学院专业软件工程指导教师二O一三年一月十日目录1 系统目标 (1)1.1 要求介绍 (3)1.2 功能要求 (4)2 逻辑设计过程 (4)3 系统展示 (4)4 系统实现 (6)4.1词法分析的实现 (6)4.2语法分析的实现 (13)1 系统目标1.1 要求介绍课程设计所用的Tiny文法:Program →stmt-sequencestmt-sequence →stmt-sequence ;statement | statementstatement →if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt if-stmt →if exp then stmt-sequence end| if exp then stmt-sequence else stmt-sequence end repeat-stmt →repeat stmt-sequence until expassign-stmt →identifier := expread-stmt →read identifierwrite-stmt →write expexp→simple-exp comparison-op simple-exp | simple-expsimple-exp →simple-exp addop term | termcomparison-op →<|= addop→+|- mulop→*|/term →term mulop factor | factorfactor →( exp ) | number | identifierTiny语言关键字表:表一: 保留字表保留字if then else end repeatuntilread write种别码 0 1 2 3 4 5 6 7助记符$IF $THEN$ELSE$END$REPEAT$UNTIL $READ $WRITE表二: 算符表算符+-* /=<:=种别码891011121314助记符$ADD$SUBTRACT $MUL #DIVIDE $EQUAL $LESS $ASSIGN表三: 分隔符表分隔符;(){}#种别码151617181920助记符$SEMICOLON$LPAR$RPAR$LBRA$RBRA$CROSS其他: 标志符: identifier 种别码: 21 助记符: $ID数字 : number 种别码: 22 助记符: $NUMBER1.2 功能要求根据Tiny文法的要求,能够对语句进行词法分析,当词法分析正确时能够进行语法分析,生成语法树,当语法发生错误时能够进行报错。
编译原理课程设计(JAVA)-语法分析器
福建农林大学计算机与信息学院计算机类课程设计报告课程名称:编译原理课程设计题目:语法分析器姓名:系:计算机专业:计算机科学与技术年级:2009级学号:指导教师:职称:2010~2011学年第一学期福建农林大学计算机与信息学院计算机类课程设计结果评定评语:成绩:指导教师签字:任务下达日期:评定日期:目录1 正则表达式 (1)1.1 正则表达式 (1)1.2 确定化(化简)后的状态转换图 (1)1.3 分析程序代码 (1)1.4 程序运行截图 (1)1.5 小结 (8)2 LL(1)分析·····································································································错误!未定义书签。
c语言语法分析器
#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出@的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/ int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果'|'后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果'|'后的首符号和左部不同*/ left[count]=ch;right[count][0]='@';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/ void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]){char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i); scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的' @ '一并并入目串;type=2,源串中的' @ '不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='@');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出@的符号********************************************/void emp(char c){ /*即求所有由' @ '推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出' @ '********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/ if(j==1&&in(right[i][0],empty)==1)return(1);else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='@'){ /*若右部某一符号不在非终结符、终结符中且不为' @ ',报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/ char c,temp[20];int j,k,m;c=v[i];char ch='@';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='@') {temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='@';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='@'){if(i>=0){first[i][0]='@';first[i][1]='\0';}else{TEMP[0]='@';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/ {for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1) {temp[0]='@';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/ temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/ {for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\n各非终结符导出的first集:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\n能导空的非终结符集合:%s",empty);// printf("\n_emp:");//for(j=0;j<=strlen(v)-1;j++)// printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}//printf("\nfirst:");//for(i=0;i<=count-1;i++)// printf("%s ",first[i]);printf("\nfollow集合:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='@')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect集合顺序是:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/M[m][k]=i;}}}}/*******************************************判断符号串是否是该文法的句型********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("词法错误!");return;}}if(M[i][k]==-1){printf("语法错误!");return;}else{m=M[i][k];if(right[m][0]=='@')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("S:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" \n");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\n开始符号为:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\n所有符号集为:%s",v);printf("\n非终结符集合:{%s",non_ter);printf("}");printf("\n终结符集合:{%s",termin);printf("}");printf("\n文法所有右边表达式依次是:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\n文法所有左边开始符依次是:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();//printf("\nvalidity=%d",validity);if(validity==1){ll=ll1();// printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{printf("\n该文法是一个LL(1)文法!");MM();// printf("\n");//for(i=0;i<=19;i++)// for(j=0;j<=19;j++)// if(M[i][j]>=0)//printf("M[%d][%d]=%d ",i,j,M[i][j]);menu();}}}/////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////。
语法分析器(基于mini-C的源程序)
语法分析器LEX代码段:%{#include <stdlib.h>#include "calc3.h"#include "y.tab.h"void yyerror(char *);%}%%[a-z] {yylval.sIndex = *yytext - 'a';return VARIABLE;}[0-9]+ {yylval.iValue = atoi(yytext);return INTEGER;}[-()<>=+*/;{}.] {return *yytext;}">=" return GE;"<=" return LE;"==" return EQ;"!=" return NE; "while" return WHILE; "for" r eturn FOR;"if" return IF;"else" return ELSE; "print" return PRINT; "return" return RETURN;[ \t\n]+ ; /* ignore whitespace */ . yyerror("Unknown character"); %%int yywrap(void) {return 1;}YACC代码段:%{#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include "calc3.h"/* prototypes */nodeType *opr(int oper, int nops, ...); nodeType *id(int i);nodeType *con(int value);void freeNode(nodeType *p);int ex(nodeType *p);int yylex(void);void yyerror(char *s);int sym[26]; /* symbol table */%}%union {int iValue; /* integer value */char sIndex; /* symbol table index */nodeType *nPtr; /* node pointer */};%token <iValue> INTEGER%token <sIndex> VARIABLE%token WHILE FOR IF PRINT RETURN%nonassoc IFX%nonassoc ELSE%left GE LE EQ NE '>' '<'%left '+' '-'%left '*' '/'%nonassoc UMINUS%type <nPtr> stmt expr stmt_list%%program:function { exit(0); };function:function stmt { ex($2); freeNode($2); }| /* NULL */;stmt:';' { $$ = opr(';', 2, NULL, NULL); }| expr ';' { $$ = $1; }| PRINT expr ';' { $$ = opr(PRINT, 1, $2); }| RETURN expr ';' { $$ = opr(RETURN, 1, $2); }| VARIABLE '=' expr ';' { $$ = opr('=', 2, id($1), $3); }| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); }| FOR '(' stmt expr ';' stmt ')' stmt { $$ = opr(FOR, 4, $3, $4,$6,$8); } | IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); }| IF '(' expr ')' stmt ELSE stmt{ $$ = opr(IF, 3, $3, $5, $7); }| '{' stmt_list '}' { $$ = $2; };stmt_list:stmt { $$ = $1; }| stmt_list stmt { $$ = opr(';', 2, $1, $2); };expr:INTEGER { $$ = con($1); }| VARIABLE { $$ = id($1); }| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); }| expr '+' expr { $$ = opr('+', 2, $1, $3); }| expr '-' expr { $$ = opr('-', 2, $1, $3); }| expr '*' expr { $$ = opr('*', 2, $1, $3); }| expr '/' expr { $$ = opr('/', 2, $1, $3); }| expr '<' expr { $$ = opr('<', 2, $1, $3); }| expr '>' expr { $$ = opr('>', 2, $1, $3); }| expr GE expr { $$ = opr(GE, 2, $1, $3); }| expr LE expr { $$ = opr(LE, 2, $1, $3); }| expr NE expr { $$ = opr(NE, 2, $1, $3); }| expr EQ expr { $$ = opr(EQ, 2, $1, $3); }| '(' expr ')' { $$ = $2; };%%#define SIZEOF_NODETYPE ((char *)&p->con - (char *)p)nodeType *con(int value) {nodeType *p;size_t nodeSize;/* allocate node */nodeSize = SIZEOF_NODETYPE + sizeof(conNodeType);if ((p = malloc(nodeSize)) == NULL)yyerror("out of memory");/* copy information */p->type = typeCon;p->con.value = value;return p;}nodeType *id(int i) {nodeType *p;size_t nodeSize;/* allocate node */nodeSize = SIZEOF_NODETYPE + sizeof(idNodeType);if ((p = malloc(nodeSize)) == NULL)yyerror("out of memory");/* copy information */p->type = typeId;p->id.i = i;return p;}nodeType *opr(int oper, int nops, ...) {va_list ap;nodeType *p;size_t nodeSize;int i;/* allocate node */nodeSize = SIZEOF_NODETYPE + sizeof(oprNodeType) + (nops - 1) * sizeof(nodeType*);if ((p = malloc(nodeSize)) == NULL)yyerror("out of memory");/* copy information */p->type = typeOpr;p->opr.oper = oper;p->opr.nops = nops;va_start(ap, nops);for (i = 0; i < nops; i++)p->opr.op[i] = va_arg(ap, nodeType*);va_end(ap);return p;}void freeNode(nodeType *p) {int i;if (!p) return;if (p->type == typeOpr) {for (i = 0; i < p->opr.nops; i++)freeNode(p->opr.op[i]);}free (p);}void yyerror(char *s) {fprintf(stdout, "%s\n", s);}int main(void) {yyparse();return 0;}测试程序:x=1;while(x<3){print(x);x = x+1;if(x>10)x=7;elsex=9;return x;}for(x=0 ; x<10 ; x=x+1;) {x = x+2;print(x);return x;}图形生成:Graph 0:[=]||----|| |id(X) c(1)Graph 1:while||-------------------------------------|| |[<] [;]| ||----| |-------------------------------|| | | | id(X) c(3) [;] return| ||----------------------------| || | |[;] if id(X)| ||----------| |---------------------|| | | | |print [=] [>] [=] [=]| | | | || |-------| |-----| |----| |----|| | | | | | | | |id(X) id(X) [+] id(X) c(10) id(X) c(7) id(X) c(9)||----|| |id(X) c(1)Graph 2:for||-----------|-------------|-----------------------|| | | |[=] [<] [=] [;]| | | ||----| |-----| |-------| |--------------|| | | | | | | |id(X) c(0) id(X) c(10) id(X) [+] [;] return| | ||----| |-----------| || | | | |id(X) c(1) [=] print id(X)| ||-------| || | | id(X) [+] id(X)||----|| |id(X) c(2)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
语法分析器(含完整源码)语法分析实验报告一、实验目的:1. 了解单词(内部编码)符号串中的短语句型结构形成规律。
2. 理解和掌握语法分析过程中语法分析思想(LL,LR)的智能算法化方法。
二、实验内容:构造自己设计的小语言的语法分析器:1. 小语言的语法描述(语法规则)的设计即文法的设计;2. 把文法形式符号中所隐含的信息内容挖掘出来并用LL或LR 的资料形式(分析表)表示出来;3. 语法分析的数据输入形式和输出形式的确定;4. 语法分析程序各个模块的设计与调试。
主要设备和材料:电脑、winxp操作系统、VC语言系统三、实验分工:081四、实验步骤:1、语法规则①<程序>::= {<变量定义语句>|<赋值语句>|<条件语句> |<循环语句> }②<变量定义语句>::=var 变量{,变量};③<赋值语句>::=变量:= <表达式>;④<表达式>::=标识符{运算符标识符};⑤<标识符>::=变量|常量⑥<运算符>::=+ | - | * | / | >= | <=⑦<条件语句>::=<if语句>[<else语句>]⑧<if语句>::= if(表达式) then[begin] {赋值语句|条件语句| 循环语句}[end]⑨<else语句>::= [begin] {赋值语句|条件语句| 循环语句} [end]⑩<循环语句>::=while(表达式) [begin] {赋值语句| 条件语句| 循环语句} [end]<输出语句>::=prn 表达式--注1:若if语句、else语句、循环语句中出现begin,后面的end必须出现,即begin与end同对出现--注2:if、while后的"(",")"表示终结符,而不是定义成分优先的说明符号2、分析表:( ) : = 变量常量,;运算符变量定义->②->②->②->②赋值语句->③->③->③->③ ->③条件语句->⑦->⑦->⑦->⑦->⑦->⑦->⑦循环语句->⑩->⑩->⑩->⑩->⑩->⑩->⑩输出语句->->->分析表(续):while var begin end if then prn 变量定义->②赋值语句条件语句->⑦->⑦->⑦->⑦循环语句->⑩->⑩->⑩输出语句-> 3、调试和测试五、源代码(见附录):六、实验总结:本实验在词法分析的基础上,对提取出的标识符进行语法判断。
对已有的语法规则运用LL(1)文法判别并进行构造分析表时,遇到的最大困难是:当发生规约冲突时,该如何处理。
如对于产生式s-->aAb,当对a进行规约时,满足语法规则的β(用户输入串中当前要进行规约的标识符)只有有限种,而不满足的却有无限种情况。
当发生规约冲突时,如何在这无限种情况中,确定冲突的具体信息,以便用户查找。
在反复的尝试和验证中,我们发现发生冲突的用户输入串满足一定的规律,且按这种规律可以把这无限种情况化归为有限类,于是我们找出其中规律并进行划分,然后再对这些有限类冲突进行处理。
七、实验心得:通过这次实验有以下几点收获:1. LR(1)的构造使得对理论的知识理解的更加透彻。
其中LR(1)分析表构造了很多遍,一直无法得到正确结果,这是恒心的考验。
2.在写程序中用类数组来存放单词属性使得对单词各项值的调用更加方便,特别是对出错信息的检测有很大的作用。
3.本实验是在词法基础上的更进一步,在词法程序上添加语法程序,更加理解二者之间的关系。
词法分析为语法分析提供了词法单元,方便分析,使程序模块化,易于读懂。
附录:#include <iostream>#include <fstream>#include <string>#include <math.h>#include <ctype.h>#include <cstdlib>using namespace std;#define Max 655 //最大代码长度#define WordMaxNum 256 //变量最大个数#define DigitNum 256 //常量最大个数#define MaxKeyWord 32 //关键字数量#define MaxOptANum 8 //运算符最大个数#define MaxOptBNum 4 //运算符最大个数#define MaxEndNum 11 //界符最大个数typedef struct DisplayTable{int Index; //标识符所在表的下标int type; //标识符的类型int line; //标识符所在表的行数char symbol[20]; //标识符所在表的名称}Table;int TableNum = 0; //display表的表项总数char Word[WordMaxNum][20]; //标识符表char Digit[WordMaxNum][20]; //数字表int WordNum = 0; //变量表的下标int DigNum = 0; //常量表的下标bool errorFlag = 0; //错误标志int TableIndex = -1; //display 表的下标索引int beginCount = 0;//遇到begin加1,遇到end减1int ifCount = 0; //遇到if加1Table *table = new Table[Max];//关键字const char* const KeyWord[MaxKeyWord] = {"and","array", "begin","case","char","constant","do","else","end","false", "for","if","input","integer","not","of","or","output", "packed","procedure","program","read","real","repeat","set", "then", "to", "type", "until", "var","while", "with","prn"};// 单目运算const char OptA[] = {'+','-','*','/','=','#','<','>'};//双目运算符const char *OptB[] = {"<=",">=",":=","<>"};// 界符const char End[] = {'(', ')' , ',' , ';' , '.' , '[' , ']' , ':' , '{' , '}' , '"'};void error(char str[20],int nLine, int errorType){errorFlag = 1;cout <<" \nError : ";switch(errorType){case 1:cout << "第" << nLine-1 <<"行" << str << " 变量的长度超过限制!\n";break;case 2:cout << "第" << nLine-1 <<"行" << str << " 小数点错误!\n";break;case 3:cout << "第" << nLine-1 <<"行" << str << " 常量的长度超过限制!\n";break;}//switch}//errorvoid Scanner(char ch[],int chLen,int nLine){int chIndex = 0;while(chIndex < chLen) //对输入的字符扫描{/****************处理空格和tab***************************/ //忽略空格和tabwhile(ch[chIndex] == ' ' || ch[chIndex] == 9 ){ chIndex ++; }/*************************处理换行符*********************/ //遇到换行符,行数加1while(ch[chIndex] == 10){ nLine++;chIndex ++;}/***************************标识符**********************/ if( isalpha(ch[chIndex])) //以字母、下划线开头{char str[256];int strLen = 0;//是字母、下划线while(isalpha(ch[chIndex]) || ch[chIndex] == '_' ){str[strLen ++] = ch[chIndex];chIndex ++;while(isdigit(ch[chIndex]))//不是第一位,可以为数字{str[strLen ++] = ch[chIndex];chIndex ++;}}str[strLen] = 0; //字符串结束符if(strlen(str) > 20) //标识符超过规定长度,报错处理{error(str,nLine,1);}else{int i;for(i = 0;i < MaxKeyWord; i++) //与关键字匹配//是关键字,写入table表中if(strcmp(str, KeyWord[i]) == 0){strcpy(table[TableNum].symbol,str);table[TableNum].type = 1; //关键字table[TableNum].line = nLine;table[TableNum].Index = i;TableNum ++;break;}if(i >= MaxKeyWord) //不是关键字{table[TableNum].Index = WordNum;strcpy(Word[WordNum++],str);table[TableNum].type = 2; //变量标识符strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;TableNum ++;}}}/**************************常数**************************/ else if(isdigit(ch[chIndex])) //遇到数字{int flag = 0;char str[256];int strLen = 0;//数字和小数点while(isdigit(ch[chIndex]) || ch[chIndex] == '.') {//flag表记小数点的个数,0时为整数,1时为小数,2时出错if(ch[chIndex] == '.')flag ++;str[strLen ++] = ch[chIndex];chIndex ++;}str[strLen] = 0;if(strlen(str) > 20) //常量标识符超过规定长度20,报错处理{error(str,nLine,3);}if(flag == 0){table[TableNum].type = 3; //整数}if(flag == 1){table[TableNum].type = 4; //小数}if(flag > 1){error(str,nLine,2);}table[TableNum].Index = DigNum;strcpy(Digit[DigNum ++],str);strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;TableNum ++;}/*************************运算符************************/ else{//用来区分是不是无法识别的标识符,0为运算符,1为界符int errorFlag;char str[3];str[0] = ch[chIndex];str[1] = ch[chIndex + 1];str[2] = '\0';int i;for( i = 0;i < MaxOptBNum;i++)//MaxOptBNum)if(strcmp(str,OptB[i]) == 0){errorFlag = 0;table[TableNum].type = 6;strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;table[TableNum].Index = i;TableNum ++;chIndex = chIndex + 2;break;}if(i >= MaxOptBNum){for( int k = 0;k < MaxOptANum; k++)if(OptA[k] == ch[chIndex]){errorFlag = 0;table[TableNum].type = 5;table[TableNum].symbol[0] =ch[chIndex];table[TableNum].symbol[1] = 0;table[TableNum].line = nLine;table[TableNum].Index = k;TableNum ++;chIndex ++;break;}/*************************界符************************/for(int j = 0;j < MaxEndNum;j ++)if(End[j] ==ch[chIndex]){errorFlag = 1;table[TableNum].line = nLine;table[TableNum].symbol[0] = ch[chIndex];table[TableNum].symbol[1] = 0;table[TableNum].Index = j;table[TableNum].type = 7;TableNum ++;chIndex ++;}/********************其他无法识别字符*****************/ //开头的不是字母、数字、运算符、界符if(errorFlag != 0 && errorFlag != 1){char str[256];int strLen = -1;str[strLen ++] = ch[chIndex];chIndex ++;while(*ch != ' ' || *ch != 9 || ch[chIndex] != 10){str[strLen ++] = ch[chIndex];chIndex ++;}str[strLen] = 0;table[TableNum].type = 8;strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;table[TableNum].Index = -2;TableNum ++;}}}}}/**************把十进制小数转为16进制******************/ void Trans(double x,int p) //把十进制小数转为16进制{int i=0; //控制保留的有效位数while(i<p){if(x==0) //如果小数部分是0break; //则退出循环else{int k=int(x*16); //取整数部分x=x*16-int(k); //得到小数部分if(k<=9)cout<<k;elsecout<<char(k+55);};i++;};};/***********************语法错误*************************/ void Gerror(int errorType,int nIndex){errorFlag = 1;switch(errorType){case 1:cout << "第" << table[nIndex].line <<"行:" <<table[nIndex].symbol <<" 应该为赋值号:= \n";break;case 2:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为变量 \n";break;case 3:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为逗号 \n";break;case 4:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为分号 \n";break;case 5:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为运算符 \n";break;case 6:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为变量或常量 \n";break;case 7:cout << "第" <<table[TableIndex].line <<"行 "<< table[nIndex].symbol << "与"<<table[TableIndex + 1].symbol<<"之间缺少运算符 \n";break;case 8:cout << "第" << table[nIndex].line <<"行:" <<table[nIndex + 1 ].symbol <<" 应为'(' \n";break;case 9:cout << "第" <<table[TableIndex].line <<"行 "<< table[TableIndex].symbol << "与"<<table[nIndex + 1].symbol <<"之间缺少'(' \n";break;case 10:cout << "第" << table[TableIndex - 1].line<< " 行: 缺少'then'" << endl;break;case 11:cout << "第" << table[TableIndex].line << " 行:"<<table[nIndex].symbol << "应为then \n";break;case 12:cout << "第" << table[TableIndex].line << " 行: end 后不能接 " <<table[TableIndex].symbol <<endl;break;case 13:cout << "第" << table[nIndex].line <<"行:"<< table[nIndex - 1].symbol <<"与 "<<table[TableIndex].symbol <<"之间缺少变量 \n";break;case 14:cout << "第" <<table[nIndex ].line <<"行 "<< table[nIndex ].symbol << "后缺少';' \n";break;case 15:cout << "第" << table[TableIndex].line << " 行:"<<table[nIndex].symbol << "应为')' \n";break;case 16:cout << "第" << table[TableIndex].line<< " 行,begin 后不能接 "<<table[TableIndex].symbol << endl;break;}}/************************表达式判断********************/ bool express(){while(1 ){if(table[TableIndex].type==2||table[TableIndex].type == 3 ){if(table[TableIndex].type==3&&table[TableIndex+ 1].type == 2 && table[TableIndex].line == table[TableIndex + 1].line){Gerror(7,TableIndex); //出错信息:该处缺少运算符//TableIndex = TableIndex + 2;TableIndex ++;}if(table[TableIndex].line != table[TableIndex + 1].line){// Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;}TableIndex ++;}else{if(table[TableIndex].type == 5||table[TableIndex].type == 6) {Gerror(13,TableIndex);TableIndex ++;}else{Gerror(6,TableIndex); //出错信息:该处应为变量或常量}TableIndex ++;}if(table[TableIndex].type ==5|| table[TableIndex].type ==6 )TableIndex ++;else if(table[TableIndex].type == 7)return 1;else if(TableIndex >= TableNum) //|| ){Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;}else{Gerror(5,TableIndex); //出错信息:此处应为运算符TableIndex ++;}}}/*******************赋值语句判断*************************/ bool Assign() //赋值语句的判断{TableIndex ++;if(strcmp( ":=" , table[TableIndex].symbol) == 0){TableIndex ++;}else{Gerror(1,TableIndex); //出错信息:赋值号应该为":="TableIndex ++;}if(express()) //":="后可以为变量或常量{if(strcmp(";",table[TableIndex].symbol) == 0){return 1;}else{if(TableIndex >= TableNum){Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;}else if(table[TableIndex].line != table[TableIndex +1].line){Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;//TableIndex ++;}}}else{Gerror(6,TableIndex); //出错信息:":="后应为变量或常量TableIndex ++;}return 0;}/**********************语句判断*************************/ bool judge() //条件、循环、初始化语句的判断{/**************************begin********************** /if(strcmp("begin",table[TableIndex].symbol)==0) //匹配begin{beginCount ++;if(table[TableIndex + 1].type == 7){TableIndex ++;cout << "第" << table[TableIndex].line<< " 行,begin 后不能接 "<<table[TableIndex].symbol << endl;return 1;}}/**************************end***********************/if(strcmp("end",table[TableIndex].symbol) == 0) //匹配end {beginCount --;if(TableIndex < TableNum)if(table[TableIndex+1].type==7||table[TableIndex+ 1].type == 8){TableIndex ++;Gerror(12,TableIndex);return 1;}}/**************************else**********************/if(strcmp("else",table[TableIndex].symbol) == 0) //匹配else{ifCount --;return 1;}if(strcmp("prn",table[TableIndex].symbol) == 0) //匹配prn{TableIndex ++;if(table[TableIndex].type == 2 ||table[TableIndex].type == 3) // prn 后为变量或常量{TableIndex ++;//语句结束,“;”0) {return 1;}else{Gerror(4,TableIndex);//出错信息:此处应为";"}} //ifelse{Gerror(2,TableIndex);//出错信息:此处应为变量TableIndex ++;}}//if_prn/**********************var变量定义**********************/if(strcmp("var",table[TableIndex].symbol) == 0)// var a,b,c; {TableIndex ++;if(table[TableIndex].type != 2){Gerror(13,TableIndex);else Gerror(2,TableIndex);//出错信息:此处应为变量}TableIndex ++;if(strcmp(",",table[TableIndex].symbol) !=0){Gerror(3,TableIndex); //出错信息:此处应为","TableIndex ++;}while(1){while(strcmp(",",table[TableIndex].symbol)==0){TableIndex = TableIndex + 1;if(table[TableIndex].type !=2){Gerror(2,TableIndex);//出错信息:此处应为变量TableIndex ++;}TableIndex ++;}if(strcmp(";",table[TableIndex].symbol)==0){return 1;}else{Gerror(4,TableIndex);//出错信息:此处应为分号";"return 0;}}}/*****************if语句判断************************///if语句else if(strcmp("if",table[TableIndex].symbol) == 0){ifCount ++; //if个数加1if(table[TableIndex +1].type == 2 || table[TableIndex + 1].type == 3){Gerror(9,TableIndex); //出错信息:此处缺少')'TableIndex ++;}else if(strcmp("(",table[TableIndex + 1].symbol) != 0) {Gerror(8,TableIndex);//出错信息:此处应为分号"("}TableIndex = TableIndex + 2;if(express()){if(strcmp(")",table[TableIndex].symbol) == 0) //'('匹配{TableIndex ++;if(strcmp("begin",table[TableIndex ].symbol) == 0) {beginCount ++;if(table[TableIndex + 1].type == 7){Gerror(16,TableIndex);TableIndex ++;return 1;}Gerror(10,TableIndex);//出错信息:此处缺少"then"return 0;}if(strcmp("then",table[TableIndex].symbol) != 0){Gerror(11,TableIndex);//出错信息:此处应为"then"return 0;}//if_thenelse{return 1;}}//if_)else{Gerror(15,TableIndex);return 0;}} //if_express}//if_if//return 1;}int main(){ifstream in;ofstream out;char in_file_name[26],out_file_name[26];char ch[Max];cin.getline(ch,Max,'#');int nLine = 1;/**********************调用词法分析**********************/ Scanner(ch, strlen(ch),nLine);//for(int i = 0; i < TableNum;i ++)// cout << table[i].type<< " "<<table[i].symbol<< " "<<table[i].Index<<""<<table[i].line<< endl;/**********************调用语法分析**********************/ cout << endl << "语法分析结果:\n "<< endl;while(TableIndex <= TableNum){TableIndex ++;if(table[TableIndex].type == 1)judge();else if(table[TableIndex].type == 2)Assign(); //赋值语句}if(ifCount < 0){errorFlag = 1;cout << "程序缺少if \n";}if(beginCount <0){errorFlag = 1;cout << "程序缺少begin \n";}if(beginCount >0){errorFlag = 1;cout << "程序缺少end \n";}if(errorFlag == 0){cout << "语法分析成功!"; }return 0;}。