语法分析器源代码

合集下载

编译的四个阶段

编译的四个阶段

编译的四个阶段编译的四个阶段编译是将高级语言翻译成机器能够理解和执行的底层语言的过程。

通常来说,编译由四个主要阶段组成:词法分析、语法分析、语义分析和代码生成。

第一阶段:词法分析在词法分析阶段,编译器会扫描源代码文件,并将其分解为被称为单词(token)的基本单位。

词法分析器会忽略源代码中的空格和注释,并将程序中的每一个单词与语言规范中所定义的单词进行匹配。

同时,它还会分配一个符号来代表程序中的变量、常量和操作符。

第二阶段:语法分析一旦编译器将程序分解为单词,其下一个工作阶段便是进行语法分析。

语法分析器将检查程序中的单词序列是否遵守特定的语法规则。

如果程序遵循正确的语法规范,则语法分析器将创建语法树。

语法树是一个包含程序结构和语法元素的数据结构,它能够反映出程序的结构,如条件语句、循环语句和函数定义等。

第三阶段:语义分析在语义分析阶段中,编译器将对语法树进行检查来确保程序的语义正确性。

这个过程需要编译器检查变量和常量是否有正确的类型、函数是否正确地调用、符号是否被正确声明等。

它还可以进行一些优化,例如将表达式简化为更简单的形式,以便生成更有效的代码。

第四阶段:代码生成最后一个阶段是代码生成,它将优化后的语法树转化为真正的目标代码。

在这个过程中,编译器会将程序的不同部分映射到机器操作、汇编指令或指令序列,以产生可执行的机器代码。

在这个过程中,编译器还需要生成调试信息以及生成符号表,以便程序员在调试过程中能够进行更加有效的调试。

结语所有这些阶段都是编译的必要步骤,每个阶段都具有一定的重要性。

词法分析、语法分析和语义分析都被理解为“静态分析”,因为它们都是在编译时完成的,而不是在程序运行时。

当然,编译器只是程序员工具的一部分,编写高质量的代码是开发应用程序的另一方面,所以程序员需要通过实践来不断提高编程技能。

编译原理中的词法分析与语法分析原理解析

编译原理中的词法分析与语法分析原理解析

编译原理中的词法分析与语法分析原理解析编译原理中的词法分析和语法分析是编译器中两个基本阶段的解析过程。

词法分析(Lexical Analysis)是将源代码按照语法规则拆解成一个个的词法单元(Token)的过程。

词法单元是代码中的最小语义单位,如标识符、关键字、运算符、常数等。

词法分析器会从源代码中读取字符流,将字符流转换为具有词法单元类型和属性值的Token序列输出。

词法分析过程中可能会遇到不合法的字符序列,此时会产生词法错误。

语法分析(Syntax Analysis)是对词法单元序列进行语法分析的过程。

语法分析器会根据语法规则,将词法单元序列转换为对应的抽象语法树(Abstract Syntax Tree,AST)。

语法规则用于描述代码的结构和组织方式,如变量声明、函数定义、控制流结构等。

语法分析的过程中,语法分析器会检查代码中的语法错误,例如语法不匹配、缺失分号等。

词法分析和语法分析是编译器的前端部分,也是编译器的基础。

词法分析和语法分析的正确性对于后续的优化和代码生成阶段至关重要。

拓展部分:除了词法分析和语法分析,编译原理中还有其他重要的解析过程,例如语义分析、语法制导翻译、中间代码生成等。

语义分析(Semantic Analysis)是对代码进行语义检查的过程。

语义分析器会根据语言的语义规则检查代码中的语义错误,例如类型不匹配、变量声明未使用等。

语义分析还会进行符号表的构建,维护变量和函数的属性信息。

语法制导翻译(Syntax-Directed Translation)是在语法分析的过程中进行语义处理的一种技术。

通过在语法规则中嵌入语义动作(Semantic Action),语法制导翻译可在语法分析的同时进行语义处理,例如求解表达式的值、生成目标代码等。

中间代码生成(Intermediate Code Generation)是将高级语言源代码转换为中间表示形式的过程。

中间代码是一种抽象的表示形式,可以是三地址码、四元式等形式。

软件开发中的语法分析器技术

软件开发中的语法分析器技术

软件开发中的语法分析器技术在软件开发中,语法分析器技术是一项十分重要的技术,它负责将代码进行解析和翻译,从而进行编译或执行。

语法分析器技术可以帮助开发人员识别并纠正代码中的错误,提高编程效率和代码质量。

本文将介绍语法分析器技术的相关知识和应用。

什么是语法分析器?语法分析器是一种翻译器,其作用是将源代码转换为目标代码或解释执行。

它的主要任务是进行句法分析和语义分析,检查代码的正确性和逻辑性,同时生成代码树以生成目标代码或解释执行。

语法分析器可以划分为两种类型:自下而上语法分析器和自上而下语法分析器。

自下而上语法分析器是一种逆向分析方式,它从最小的语法单元开始,将其组合成较大的语法单元,最终生成一棵代码树。

自上而下语法分析器则是先由代码的上层结构进行分析,逐级分解为更小的语法单元,最后得到一颗代码树。

语法分析器的作用语法分析器在软件开发中具有非常重要的作用,它可以提高代码的正确性和可读性,同时能够检测并纠正代码中的错误,加快软件开发过程。

具体来说,语法分析器能够:1.检查代码的正确性语法分析器能够在编译或执行代码之前检查代码的正确性。

它能够检查代码中的语法错误、类型错误、语义错误等,在代码编写过程中及时发现并及时纠正错误,提高代码的质量和可维护性。

2.加快编译及执行速度语法分析器能够将源代码转换为目标代码或解释执行,加快程序的执行速度。

它能够分析代码逻辑,优化相关代码的执行流程,同时减少代码执行的时间。

3.提高代码可读性语法分析器能够将代码转换成易于理解和维护的代码,同时增强代码的可读性。

例如,它可以将代码中重复的部分统一,提高代码的可读性和可维护性。

语法分析器的应用语法分析器在软件开发中广泛应用,具体包括以下方面:1.编译器编译器是一种将源代码转换为目标代码的软件。

编译过程包括词法分析、语法分析、代码生成等,其中语法分析器起着非常重要的作用,它能够将代码转换为目标代码或解释执行。

2.解析器解析器是一种将指定格式的文本转换为结构化数据的软件。

计算机编译的名词解释

计算机编译的名词解释

计算机编译的名词解释计算机编译是指将人类编写的高级语言程序翻译成计算机能够理解和执行的机器语言的过程。

在计算机科学中,编译器是实现这个过程的关键工具。

本文将对计算机编译的相关名词进行解释,以帮助读者更好地理解这一概念。

一、编译器(Compiler)编译器是一种程序,它将高级语言的源代码转换为目标代码,使计算机能够直接执行。

编译器通常包含以下几个主要的组件:1. 词法分析器(Lexer):也称为扫描器,负责将源代码分解成一个个记号(Token)。

记号是语言中的最小单位,例如关键字、标识符、运算符等。

2. 语法分析器(Parser):语法分析器根据语言的语法规则,将记号组织成一棵由语法构成的语法树(Parse Tree)。

语法树表示了源代码的结构。

3. 语义分析器(Semantic Analyzer):语义分析器对语法树进行检查,以确保源代码的语义正确。

它会检查变量的声明与使用是否匹配、类型转换是否正确等。

4. 目标代码生成器(Code Generator):目标代码生成器将语法树转换为计算机能够执行的目标代码。

目标代码可以是二进制文件、字节码或其他形式的中间表示。

二、解释器(Interpreter)解释器是一种执行高级语言程序的程序。

与编译器不同,解释器不会直接将源代码转换为目标代码,而是逐行解释并执行源代码。

解释器通常包含以下几个主要的组件:1. 词法分析器(Lexer):与编译器的词法分析器相同,将源代码分解成记号。

2. 语法分析器(Parser):解释器的语法分析器根据语言的语法规则,将源代码解析为语法树。

但与编译器不同,解释器不会生成目标代码。

3. 解释器核心(Interpreter Core):解释器核心逐行读取语法树,并实时解释和执行源代码。

它会根据不同的语法规则执行相应的操作。

三、即时编译(Just-in-Time Compilation)即时编译是一种将高级语言程序动态转换为机器代码的技术。

程序编译的四个步骤

程序编译的四个步骤

程序编译的四个步骤程序编译是将高级语言编写的程序翻译成机器语言的过程。

编译器是用来进行编译的工具,它可以将源代码转换为可执行的机器码,从而能够被计算机直接执行。

程序编译通常包括四个主要步骤:词法分析、语法分析、语义分析和代码生成。

1.词法分析词法分析是程序编译的第一步,也是一个很关键的步骤。

在词法分析中,编译器会将源代码分解为一个个的词法单元。

词法单元是程序的最小语法单位,可以是关键字、标识符、运算符、常量等等。

编译器会根据事先定义好的语法规则,将源代码中的字符序列解析成词法单元序列,并且给每个词法单元加上相应的标记,以便后面的步骤进行处理。

2.语法分析语法分析是程序编译的第二步。

在语法分析中,编译器会根据词法分析得到的词法单元序列,构建语法树或抽象语法树。

语法树是一个树状的数据结构,它表示程序的语法结构。

编译器会根据文法规则和词法单元的组合规则,对词法单元序列进行检查,并将其组织成语法树或抽象语法树。

语法树或抽象语法树是编译器进行后续处理的基础,它描述了程序的语法结构,方便后续步骤对程序进行分析和优化。

3.语义分析语义分析是程序编译的第三步。

在语义分析中,编译器会对语法树或抽象语法树进行分析,进行语义检查和语义推导。

语义是指程序中传达的意义和规则,它描述了程序如何运行和产生结果。

编译器会根据语义规则检查程序是否存在语义错误,并进行类型检查和类型推导。

如果程序存在语义错误,则编译器会输出错误信息,提示开发人员进行修正。

另外,编译器还会进行一些语义转换和优化,例如将高级语言中的循环结构转换为汇编语言中的跳转指令。

4.代码生成代码生成是程序编译的最后一步。

在代码生成中,编译器会根据语义分析得到的语法树或抽象语法树,生成目标代码或机器代码。

目标代码是特定平台上的中间代码表示,它与具体的机器相关性较低。

机器代码是目标机器上可以直接执行的二进制代码。

编译器会将目标代码或机器代码生成为对应的输出文件,例如可执行文件、动态链接库或静态链接库。

语法分析器源代码

语法分析器源代码

语法分析程序的源代码#include<stdio.h>#include<string.h>char prog[80],token[6];char ch;int syn,p,m,n,sum,kk=0;char * rwtab[6]={"begin","if","then","while","do","end"};main(){p=0;printf("\nplease intput string:");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}/*词法扫描程序:*/scaner(){for(n=0;n<8;n++)token[n]=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<='9'&&ch>='0')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';ch=prog[--p];syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}elseif((ch<='9'&&ch>='0')){sum=0;while((ch<='9'&&ch>='0')){sum=sum*10+ch-'0';ch=prog[p++];}ch=prog[--p];syn=11;}elseswitch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}elseif(ch=='='){syn=22;token[m++]=ch;}else{syn=20;ch=prog[--p];}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=23;ch=prog[--p];}break;case ':':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;ch=prog[--p];}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ':=':syn=18;token[0]=ch;break;case '<>':syn=21;token[0]=ch;break;case '<=':syn=22;token[0]=ch;break;case '>=':syn=24;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}lrparser(){if(syn==1){scaner();if(syn==6){scaner();if((syn==0)&&(kk==0))printf("sucess");}else{if(kk!=1) printf("lost end error!");kk=1;}}else{printf("output of begin is error!");kk=1;}return;}yucu(){statement();while(syn==26){scaner();statement();}return;}statement(){if(syn==10){scaner();if(syn==18){scaner();expression();}{printf("output of equal is error!");kk=1;}}else{printf("input of sentence is error!");kk=1;}return;}expression(){term();while(syn==13||syn==14){scaner();term();}return;}term(){factor();while(syn==15||syn==16){scaner();factor();}return;}factor(){if(syn==10||syn==11)scaner();elseif(syn==27){scaner();expression();if(syn==28)scaner();else{printf("output ')' is error!");kk=1;}}else{printf("output expression is error!");kk=1;}return;}。

python编译的过程

python编译的过程

python编译的过程摘要:Python是一种广泛使用的高级编程语言,它的编译过程相对简单。

本文将详细介绍Python的编译过程,包括源代码处理、编译成字节码、执行引擎等步骤。

一、Python的编译过程Python的编译过程可以分为以下几个步骤:1. 源代码处理2. 编译成字节码3. 执行引擎下面我们详细了解一下每个步骤。

二、源代码处理1. 源代码文件Python的源代码文件通常以.py为扩展名。

在Windows系统中,源代码文件扩展名为.pyc。

源代码文件包含一系列Python语句,这些语句可以是一个简单的变量赋值,也可以是一个复杂的函数定义。

2. 预处理预处理阶段的主要任务是处理源代码中的宏定义、注释和包含文件。

预处理器会将所有的宏定义展开,将注释删除,并将包含文件的内容合并到主源文件中。

3. 语法检查预处理完成后,源代码将进入语法检查阶段。

Python的解释器会对源代码进行语法检查,确保源代码符合Python的语法规范。

如果源代码中存在语法错误,解释器将报告错误并终止编译过程。

三、编译成字节码1. 词法分析词法分析阶段将源代码分解成一系列的词法单元(tokens)。

词法单元是源代码中的最小单位,通常包括关键字、变量名、操作符等。

词法分析器会将源代码转换成一个词法单元的列表。

2. 语法分析语法分析阶段将词法单元列表转换成一个抽象语法树(abstract syntax tree, AST)。

抽象语法树表示了源代码的结构,包括变量声明、函数定义、表达式等。

语法分析器会根据Python的语法规则构建抽象语法树。

3. 语义分析语义分析阶段对抽象语法树进行语义检查,确保源代码中没有语法错误。

此外,语义分析器还会为抽象语法树中的每个语句分配一个运算符优先级。

4. 字节码生成字节码生成阶段将抽象语法树转换成字节码(bytecode)列表。

字节码是Python程序的执行指令,包括载入模块、调用函数、计算表达式等。

简述编译程序的工作过程以及每个阶段的功能

简述编译程序的工作过程以及每个阶段的功能

简述编译程序的工作过程以及每个阶段的功能
编译程序是将高级语言(如C、Java等)翻译成机器语言的程序。


译程序的工作过程一般可以分为以下四个阶段:词法分析、语法分析、语义分析和代码生成。

1. 词法分析
词法分析是将源代码划分为一个个单独的单词或符号,称为“记号”。

这些记号包括关键字、标识符、运算符、界符等。

在这个阶段,编译
器会扫描整个源代码,并将其转化为一个记号序列。

同时,编译器也
会进行错误检查,例如检查是否有拼写错误或语法错误等。

2. 语法分析
语法分析是对记号序列进行处理,以确定源代码是否符合所定义的文
法规则。

在这个阶段,编译器会构建抽象语法树(AST),并检查源代码是否存在语法错误。

如果存在错误,则编译器会输出相应的错误信息。

3. 语义分析
在语义分析阶段中,编译器会对AST进行处理,并确定源代码中各种
元素之间的含义和关系。

在这个阶段,编译器会进行类型检查和作用
域检查等操作,并生成相应的符号表和类型表等数据结构。

4. 代码生成
最后一个阶段是代码生成阶段,编译器会将AST转化为机器语言,并
生成可执行的目标代码。

在这个阶段,编译器会进行优化操作,例如
常量折叠、死代码消除等。

最终,编译器会将目标代码输出到文件中,以供后续的执行。

总的来说,编译程序的工作过程是一个非常复杂的过程。

每个阶段都
有其独特的功能和作用。

通过这些阶段的处理,编译器可以将高级语
言转化为机器语言,并生成可执行的目标代码。

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

#include<stdio.h>#include<stdlib.h>#include<string.h>#define HIGHER 1#define LOWER -1#define EQUAL 0#define TRUE 1#define FALSE 0#define OPER_NUM 50 //默认算符数目#define VN_NUM 50 //默认非终结符数目#define MAX_BUFFER 128 //每行输入行最大长度#define MAX_GRA_NUM 20 //最大文法数目#define EMPTY -2 //算符优先表初始值,表示这对算符没有优先关系#define STACK_SIZE 64typedef struct{char c; //非终极符符号int firstvt[OPER_NUM]; //firstvt集,保存算符在oper_list中的下标int fir_n,last_n;int lastvt[OPER_NUM];}vn_t;int prior_table[OPER_NUM][OPER_NUM];char oper_list[OPER_NUM];int oper_num = 0;vn_t vn_list[VN_NUM];int vn_num = 0;char *grammar[MAX_GRA_NUM][2];int gra_num = 0;char start_vn;char stack[STACK_SIZE];int top = 0;void get_input(char *buf);int buf_deal(char* buf);void get_FIRVT_LASTVT(int vn_n);int create_table();void init_table();int analyze(char *sentence);void display_table();void display_fir_lastvt();int get_oper(char c); //得到算符c的数组下标没有返回-1int get_vn(char c); //得到非终结符c的数组下标,没有返回-1int is_vn(char a){return (('A'<=a&&a<='Z')?1:0);}int get_oper(char c){int i;for(i = 0; i < oper_num; ++i)if(oper_list[i] == c)return i;return -1;}int get_vn(char c){int i;for(i = 0; i < vn_num; ++i)if(vn_list[i].c == c)return i;return -1;}char reduce(int start, int end, int size) //规约{char *tar, *g, t1, t2, left;int i, j =0, gi, ti, cn = 0;int same;tar = (char *)malloc(sizeof(char)*MAX_BUFFER);if(!tar){printf("Allocation fails.\n");exit(-1);}for(i = start; i <= end; ++i) //将此最左素短语的终结符存入tar字符串{if(!is_vn(stack[i]))tar[j++] = stack[i];}tar[j++] = '\0';for(i = 0; i < gra_num; ++i){g = grammar[i][1];gi = 0;ti = 0;same = FALSE;t1 = g[gi];t2 = tar[ti];while (t1 != '\0'){if(t2 == '\0' && !is_vn(t1)){same = FALSE;break;}if(!is_vn(t1)){if(t1 != t2){same = FALSE;break;}t2 = tar[++ti];same = TRUE;}t1= g[++gi];}if(same && t2 == '\0')break;}if(i == gra_num){printf("无法找到相应文法!\n");return FALSE;}left = grammar[i][0][0];return vn_list[get_vn(left)].c;}int analyze(char *sentence){char r, c,new_vn;int i = 0, k = 0, j, pi, printi = 1, cou = 1; //i是sentence[]和stack[]的索引int r_index, s_index, pre_index;printf("\n\n规约过程如下表所示:\n");printf("--------------------------------------\n");stack[top++] = '#';printf("序号\t符号栈\t最左素短语\t规约\t\n");do{r = sentence[i++];if((r_index = get_oper(r)) == -1){printf("Error : 您输入的字符不在文法定义中!\n");flushall();c = getchar();flushall();return FALSE;}if(!is_vn(stack[k])){j = k;s_index = get_oper(stack[j]);}else{j = k - 1;s_index = get_oper(stack[j]);}while(prior_table[s_index][r_index] == HIGHER){do{pre_index = s_index;if(!is_vn(stack[j-1])){j--;s_index = get_oper(stack[j]);}else{j -= 2;s_index = get_oper(stack[j]);}}while(prior_table[s_index][pre_index] != LOWER);printf(" %d\t", cou++);for(pi = 0; pi < top; ++pi){printf("%c",stack[pi]);}printf(" \t");for(pi = j + 1; pi <= k; ++pi){if (pi == j+1)printf(" %c",stack[pi]);elseprintf("%c",stack[pi]);}if((new_vn = reduce(j + 1, k, k - j)) == 0){return FALSE;}printf("\t\t %c\n",new_vn);k = j + 1; //规约最左素短语stack[k] = new_vn;top = k + 1;}if(prior_table[s_index][r_index] == LOWER || prior_table[s_index][r_index] == EQUAL){stack[++k] = r;top++;}else{printf("Error : 您输入的句型有错误!\n");return FALSE;}}while(r != '#');printf("--------------------------------------\n");return TRUE;}int buf_deal(char *buf){int i = 2,count = 0;char pre = buf[0], now;char *left_g, *right_g, *new_buf;left_g = (char *)malloc(sizeof(char)*2);right_g = (char *)malloc(sizeof(char)*(MAX_BUFFER-2));if(!left_g || !right_g){printf("Allocation fails.\n");exit(-2);}if(is_vn(pre)){if(get_vn(pre) == -1){vn_list[vn_num].c = pre;vn_list[vn_num].fir_n = 0;vn_list[vn_num].last_n = 0;vn_num++;}left_g[count] = pre;count++;left_g[count] = '\0';}elsereturn FALSE;if(buf[1] != '-' || buf[2] != '>')return FALSE;pre = buf[2];count = 0;while((now = buf[++i]) != '\0'){if(now != '|'){right_g[count] = now;count++;if(is_vn(now) && is_vn(pre))return FALSE;if(is_vn(now)){if(get_vn(now) == -1){vn_list[vn_num].c = now;vn_list[vn_num].fir_n = 0;vn_list[vn_num].last_n = 0;vn_num++;}elsecontinue;}else{if(get_oper(now) == -1){oper_list[oper_num] = now;oper_num++;}elsecontinue;}pre = now;}else{right_g[count] = '\0';grammar[gra_num][0] = left_g;grammar[gra_num][1] = right_g;gra_num++;break;}}if(buf[i] == '\0'){right_g[count] = '\0';grammar[gra_num][0] = left_g;grammar[gra_num][1] = right_g;gra_num++;}else{new_buf = (char *)malloc(sizeof(char)*MAX_BUFFER);new_buf[0] = left_g[0];new_buf[1] = '-';new_buf[2] = '>';strcpy(&new_buf[3],&buf[++i]);return buf_deal(new_buf);}return TRUE;}int create_table(){int gi = 0, ti, ni, fi, li, i;char *ng, t,next, next1;int t_index,n_index, n_index1, n_vn, t_vn;vn_t temp;for(gi = 0; gi < gra_num; ++gi ){ng = grammar[gi][1];t = ng[0];ti = 0;t_index = get_oper(t);next = ng[1];ni = 1;n_index = get_oper(next);while(next != '\0'){if(t_index != -1 && n_index != -1){if (prior_table[t_index][n_index] == EMPTY)prior_table[t_index][n_index] = EQUAL;else{printf("%c与%c有多种优先关系!\n",oper_list[t_index],oper_list[n_index]);return FALSE;}}else if(t_index != -1 && n_index == -1 && ng[ni+1] != '\0'){next1 = ng[ni+1];n_index1 = get_oper(next1);if(prior_table[t_index][n_index1] == EMPTY)prior_table[t_index][n_index1] = EQUAL;else{printf("%c与%c有多种优先关系!\n",oper_list[t_index],oper_list[n_index1]);return FALSE;}prior_table[t_index][oper_num - 1] = -3;prior_table[oper_num - 1][n_index1] = -3;}if (t_index != -1 && n_index == -1){n_vn = get_vn(next);temp = vn_list[n_vn];for(fi = 0; fi < temp.fir_n; fi++){if(prior_table[t_index][temp.firstvt[fi]] == EMPTY)prior_table[t_index][temp.firstvt[fi]] = LOWER;else{printf("%c与%c有多种优先关系!\n",oper_list[t_index],oper_list[temp.firstvt[fi]]);return FALSE;}}}else if(t_index == -1 && n_index != -1){n_vn = get_vn(t);temp = vn_list[n_vn];for(fi = 0; fi < st_n; fi++){if(prior_table[stvt[fi]][n_index] == EMPTY)prior_table[stvt[fi]][n_index] = HIGHER;else{printf("%c与%c有多种优先关系!\n",oper_list[fi],oper_list[n_index]);return FALSE;}}}t = ng[++ti];next = ng[++ni];t_index = get_oper(t);n_index = get_oper(next);}}for(i = 0; i < oper_num - 1; ++i){if(prior_table[oper_num - 1][i] != -3)prior_table[oper_num - 1][i] = LOWER;}for(i = 0; i < oper_num - 1; ++i){if(prior_table[i][oper_num - 1] != -3)prior_table[i][oper_num - 1] = HIGHER;}prior_table[oper_num - 1][oper_num - 1] = EQUAL;return TRUE;}void display_fir_lastvt(){int i, j;for (i = 0; i < vn_num; ++i){printf("FIRSTVT\(%c\) = { ", vn_list[i].c);for(j = 0; j < vn_list[i].fir_n; ++j){if (j == vn_list[i].fir_n - 1)printf(" %c ",oper_list[vn_list[i].firstvt[j]]);elseprintf(" %c ,",oper_list[vn_list[i].firstvt[j]]);}printf("}\n");printf("LASTVT\(%c\) = { ", vn_list[i].c);for(j = 0; j < vn_list[i].last_n; ++j){if (j == vn_list[i].last_n - 1)printf(" %c ",oper_list[vn_list[i].lastvt[j]]);elseprintf(" %c ,",oper_list[vn_list[i].lastvt[j]]);}printf("}\n\n");}}void display_table(){int i,j;printf("\n\t算符");for(i = 0; i < oper_num; ++i)printf("\t%c",oper_list[i]);printf("\n");for(i = 0; i < oper_num; ++i){printf("\t%c",oper_list[i]);for(j = 0; j <oper_num; ++j){if(prior_table[i][j] == 1)printf("\t>");else if(prior_table[i][j] == -1)printf("\t<");else if(prior_table[i][j] == 0)printf("\t=");elseprintf("\tNO");}printf("\n");}}void firstvt(int vn){int i, j, t, c_index, v_i, orin, pre = -1;char *ng, c;for(i = 0; i < gra_num; ++i){if (grammar[i][0][0] == vn_list[vn].c){ng = grammar[i][1];c = ng[0];if((c_index = get_oper(c)) != -1){vn_list[vn].firstvt[vn_list[vn].fir_n++] = c_index;continue;}else{v_i = get_vn(c);if(v_i != vn && v_i != pre){if(vn_list[v_i].fir_n == 0 )firstvt(v_i);orin = vn_list[vn].fir_n;vn_list[vn].fir_n += vn_list[v_i].fir_n;t = 0;for(j = orin; j < vn_list[vn].fir_n; ++j ){vn_list[vn].firstvt[j] = vn_list[v_i].firstvt[t++];}}pre = v_i;if(ng[1] != '\0'){vn_list[vn].firstvt[vn_list[vn].fir_n++] = get_oper(ng[1]);}}}}}void lastvt(int vn){int i, j, t, c_index, v_i, orin, ni = 0, pre = -1;char *ng, c;for(i = 0; i < gra_num; ++i){if (grammar[i][0][0] == vn_list[vn].c){ng = grammar[i][1];ni = 0; //每次对新语法搜索时初始化位置。

相关文档
最新文档