##100分求C语言编制一个简单语言的词法分析程序(编译原理课程设计)

wx红杉树 2008-10-25 02:20:31
本人不懂编译原理,帮好友找一个C语言编制一个简单语言的词法分析程序(编译原理课程设计),请高手帮忙
我在网上也找到了好多,好友说和要求差距太大,特贴上要求,请有的朋友提供,谢谢!

2实验目的
通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
3实验要求
Pascal语言或C语言编制一个简单语言的词法分析程序。
(1) 掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
(2) 掌握词法分析的实现方法。
(3) 上机调试编出的词法分析程序。
(4) 所有识别出的单词都用两个字节的等长表示,称为内部码。第一个字节为 t ,第二个字节为 i 。 t 为单词的种类。i 为该单词在各自表中的指针或内部码值, i 值是根据它们在源程序中出现的顺序确定的。

3.1词法规则

3.2状态转换图

4实验仪器、设备或软件

5实验过程(实验步骤、记录、数据、分析)
5.1词法分析程序流程图
(见附件)

图1 词法分析程序流程图

5.2数据结构与算法

5.3实验测试与结果

6实验总结


可以发送到ecitnet163@163.com
或直接跟帖
...全文
1938 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
FJduyezhou 2008-12-31
  • 打赏
  • 举报
回复
正好,可以用!
多谢!
wx红杉树 2008-10-31
  • 打赏
  • 举报
回复
正好,采用楼上
securityworld 2008-10-31
  • 打赏
  • 举报
回复
跟我以前的设计一样,附代码


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define LEN sizeof(struct Node)
#define NULL 0

FILE *fp; /*fp是一个指向FILE类型结构的指针变量,可以使fp指向某一个文
件的结构变量,从而通过该结构体变量中的文件信息访问该文件*/
struct 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(int a,char *b);
void back1(int a, int b);
struct Node *head,*p;
char ch; /*全局变量*/
char *key[]={"begin","do","else","end","if","then","var","while"}; /*关键字表*/

char token[20]; /*字符数组,存放构成单词的符号串*/

int main(void)
{
fp = fopen("test.c", "at+");
head=(struct Node *)malloc(LEN); /*分配头节点存储空间*/
if(!head) {printf("error");exit(1);}
head->next=NULL;
head->data=' ';
p=head;
printf("输入 \"$\" 结束.\n");
printf("关键字 t=1; 分界符 t=2; 算术运算符 t=3;\n");
printf("关系运算符 t=4; 常数 t=5; 标识符 t=6;\n");
printf("\n");
printf("输入源程序:\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(); /*词法分析*/
fclose(fp);
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");
}
/*若ch中是空白字符,则不停调用getch()直到读入的不是空白字符为止*/
void getbc()
{
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<8;k++)
{
if(strcmp(key[k],token)==0) return (k);
}
return 6; /*如果是标识符返回值为t=6*/
}

void retract() /*指针回退一个字符*/
{
struct Node *Q;
Q=head->next;
while(Q->next!=p)
Q=Q->next;
p=Q;
}

void back(int a, char *b) /*返回函数,输出序列*/
{
printf("(%d,%s)\n",a,b);
fprintf(fp,"(%d,%s)\n",a,b);
}

void back1(int a, int b) /*返回函数,输出序列*/
{
printf("(%d,%d)\n",a,b);
fprintf(fp,"(%d,%d)\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(); //c中存放的为K的值,当K为6时,是标识符
if(c!=6) back1(1,c); //t=1为关键字
else back(6,token);
}
else if(digit(ch)) /*处理数字的情况*/
{
while(digit(ch))
{
concat();
getch();
}
retract();
printf("(5,%d)\n",atoi(token));
fprintf(fp,"(5,%d)\n",atoi(token));
}
else
switch(ch) /*处理特殊符号的情况*/
{
case'+': back(3,"10H");break; //符号处理
case'-': back(3,"11H");break;
case'*': back(3,"20H");break;
case'/': back(3,"21H");break; //下面的还没处理
case',': back(2,"0");break;
case';': back(2,"1");break;
case'.': back(2,"2");break;
case':=': back(2,"3");break;
case'(': back(2,"4");break;
case')': back(2,"5");break;
case'=': back(4,"02H");break;
case'<': { getch();
if(ch=='=') back(4,"01H");
else if (ch=='>') back(4,"05H");
else
{ retract();
back(4,"00H");
}
}break;

case'>': { getch();
if(ch=='=') back(4,"04H");
else { retract();
back(4,"03H");
}
}break;
}
}


simulationz 2008-10-26
  • 打赏
  • 举报
回复
顶,关注。
wx红杉树 2008-10-25
  • 打赏
  • 举报
回复
楼上,我下载看了你的连接,都不符合我的要求,还是要谢谢你,好心的朋友
太乙 2008-10-25
  • 打赏
  • 举报
回复
http://d.download.csdn.net/down/486358/lau_j

没资源分了找俺~~
太乙 2008-10-25
  • 打赏
  • 举报
回复
http://d.download.csdn.net/down/382985/tescta
帅得不敢出门 2008-10-25
  • 打赏
  • 举报
回复
也可以参考PL/0语法分析器的代码
http://download.csdn.net/sort/tag/pl%252F0
liufabin 2008-10-25
  • 打赏
  • 举报
回复
c语言专家编程上好像有
过去的我 2008-10-25
  • 打赏
  • 举报
回复
lz是nb
wx红杉树 2008-10-25
  • 打赏
  • 举报
回复
好的,天亮我请好友来看你的代码,有问题再问你。谢谢
baihacker 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 ecitnet 的回复:]
有没有word文档或独立可编译执行的c文件
[/Quote]
没有...在4楼的代码改不了多少就能满足要求...
wx红杉树 2008-10-25
  • 打赏
  • 举报
回复
有没有word文档或独立可编译执行的c文件
wx红杉树 2008-10-25
  • 打赏
  • 举报
回复
就是符合我在3楼上放的那个流程图
baihacker 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ecitnet 的回复:]
就是符合楼上那个流程图
[/Quote]
具体算法参考我在4楼的程序.
1楼的包含了语法分析了...不过是四则运算.
wx红杉树 2008-10-25
  • 打赏
  • 举报
回复
就是符合楼上那个流程图
baihacker 2008-10-25
  • 打赏
  • 举报
回复

//某个支持C语言的子集的词法分析函数

void GetToken()
{

char *temp; //利用一个指针向字符里写内容
item=UNDEF;type=UDF;

temp = stoken;
*temp = '\0';

// 如果当前字符是空格且未到文件末
while(isspace(cbuff) && cbuff) MoveNext();

// 跳过行
while(cbuff == '\r') {
MoveNext();
MoveNext();
while(isspace(cbuff) && cbuff) MoveNext();
}

// 是否结尾
if(cbuff == '\0') {
*stoken = '\0';
item = END;
type=NON;
return ;
}

// 检查{}标识符
if(strchr("{}", cbuff)) {


stoken[0]=cbuff;
stoken[1]='\0';
type=FJF;
if(cbuff=='{')
item=LBLOCK;
else
item=RBLOCK;
MoveNext();//指向下一个字符
return ;
}
// 检查注释信息
if(cbuff == '/')
if(cbuff1 == '*') { // /*注释符
MoveNext();
MoveNext();
do { // 找到结尾
while(cbuff != '*') MoveNext();
MoveNext();
} while (cbuff != '/');
MoveNext();
GetToken();
return;
} else if(cbuff1 == '/') { // is a // CMPment
MoveNext();
MoveNext();
// Find end of CMPment.
while(cbuff != '\r' && cbuff != '\0') MoveNext();
if(cbuff == '\r') {MoveNext();MoveNext();}
GetToken();
return;
}

// 检查双操作符
if(strchr("!<>=+-", cbuff)) {
switch(cbuff) {
case '=':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '=';
temp++;
*temp = '=';
temp++;
*temp = '\0';
item=EQ;
type=CMP;

}
break;
case '!':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '!';
temp++;
*temp = '=';
temp++;
*temp = '\0';
item=NE;
type=CMP;
}
break;
case '<':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '<';
temp++;
*temp = '=';
item=LE;
type=CMP;
}
else if(cbuff1 == '<') {
MoveNext();MoveNext();
*temp = '<';
temp++;
*temp = '<';
item=LS;
type=OPE;
}
else {
MoveNext();
*temp = '<';
item=LT;
type=CMP;
}
temp++;
*temp = '\0';
break;
case '>':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '>';
temp++;
*temp = '=';
item=GE;
type=CMP;
} else if(cbuff1 == '>') {
MoveNext();MoveNext();
*temp = '>';
temp++;
*temp = '>';
item=RS;
type=OPE;
}
else {
MoveNext();
*temp = '>';
item=GT;
type=CMP;
}
temp++;
*temp = '\0';
break;
case '+':
if(cbuff1 == '+') {
MoveNext();MoveNext();
*temp = '+';
temp++;
*temp = '+';
temp++;
*temp = '\0';
item=INC;
type=OPE;
}
break;
case '-':
if(cbuff1 == '-') {
MoveNext();MoveNext();
*temp = '-';
temp++;
*temp = '-';
temp++;
*temp = '\0';
item=DEC;
type=OPE;
}
break;
}

if(*stoken) return;
}

// 其它运算符号
if(strchr("+-*^/=()", cbuff)) {
*temp = cbuff;
MoveNext();
temp++;
*temp = '\0';
type=OPE;
switch(cbuff){
case '+':
item=ADD;break;
case '-':
item=SUB;break;
case '*':
item=MUL;break;
case '/':
item=DIV;break;
case '=':
item=ASS;break;
case '(':
item=LK;break;
case ')':
item=RK;break;
}
return ;
}

// 其它运算符号
if(strchr(";,\'", cbuff)) {
*temp = cbuff;
MoveNext();
temp++;
*temp = '\0';
type=FJF;
switch(cbuff){
case ';':
item=EOS;break;
case ',':
item=DOU;break;
case '\'':
item=SFEN;break;
}
return ;
}

// 读取一个字符串
if(cbuff == '"') {
MoveNext();
while(cbuff != '"' && cbuff != '\r' && cbuff) {
// Check for \n escape sequence.
if(cbuff == '\\') {
if(cbuff1 == 'n') {
MoveNext();
*temp++ = '\n';
}
}
else if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;

MoveNext();
}
//未结束错误处理
MoveNext(); *temp = '\0';
item=STRING;
type=STR;
return ;
}

// 读取一个数字
if(isdigit(cbuff)) {
while(!isdelim(cbuff)) {
if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
*temp = '\0';
item=NUMBER;
type=NUM;
return ;
}

// Read identifier or keyword.
if(isalpha(cbuff)) {
while(!isdelim(cbuff)) {
if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
item=TEMP;
}

*temp = '\0';

// Determine if token is a keyword or identifier.
if(item == TEMP) { // convert to internal form
if(KeyLookUp(stoken,item)) type=KEY; // is a keyword
else {type = IDE;item=IDENTIFIER;}
}

}
wx红杉树 2008-10-25
  • 打赏
  • 举报
回复
baihacker 2008-10-25
  • 打赏
  • 举报
回复

//支持变量定义的计算机的词法分析部分.

char* CAL::GetNextToken(const char*& str_in, TYPE& t)
{

const char* curr = str_in;
static char buffer[256];
memset(buffer, 0, 256);

while (IsSpace(*curr)) curr++;

if (!*curr)
{
str_in = curr;
t = LAST;
return buffer;
}

if (IsOperator(*curr))
{
switch (*curr)
{
case '+': t = ADD; break;
case '-': t = SUB; break;
case '*': t = MUL; break;
case '/': t = DIV; break;
case '^': t = POW; break;
case ',': t = COM; break;
case '!': t = FAC; break;
case '=': t = EQU; break;
default:
t = LAST;
}
buffer[0] = *curr++;
str_in = curr;
return buffer;
}

if (IsDigital(*curr))
{
int i = 0;
do
{
buffer[i++] = *curr++;
} while (IsDigital(*curr));
str_in = curr;
t = NUMBER;
return buffer;
}

if (IsAlpha(*curr))
{
int i = 0;
do
{
buffer[i++] = *curr++;
} while (IsAlpha(*curr) || (IsDigital(*curr) && *curr != '.'));
str_in = curr;
t = STRING;
return buffer;
}

strcpy(buffer, "_error_");
str_in = ++curr;
t = LAST;
return buffer;
}
baihacker 2008-10-25
  • 打赏
  • 举报
回复

//计算器代码...有部分词法分析

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
enum IDENTIFER_TYPE{NUMBER, OPERATOR, LB, RB, END, ERROR};
enum OPERATOR_TYPE{EXPR,ADD,SUB,MUL,DIV,ATOM};
/*ATOM:给原子(数)赋一个优先级*/

typedef struct tagNODE
{
int type;
double value;
int ope;
struct tagNODE * left, * right, * parent;
}NODE;

/*词法分析*/
int g_type;
double g_value;
int g_ope;
const char* g_str;
const char* g_last_str;
int GetNextToken()
{
static char buff[32];
int i = 0, k;
g_last_str = g_str;
while (*g_str && *g_str == ' ') ++g_str;
if (!*g_str) return g_type = END;
if (isdigit(*g_str))
{
while (isdigit(*g_str)) buff[i++] = *g_str++;
buff[i] = 0;
g_value = atof((const char*)buff);
return g_type = NUMBER;
}

switch (*g_str++)
{
case '+' : g_ope = ADD;return g_type=OPERATOR;
case '-' : g_ope = SUB;return g_type=OPERATOR;
case '*' : g_ope = MUL;return g_type=OPERATOR;
case '/' : g_ope = DIV;return g_type=OPERATOR;
case '(' : return g_type=LB;
case ')' : return g_type=RB;
}
return g_type=ERROR;
}

void PutBack()
{
if (g_str != g_last_str) g_str = g_last_str;
}

/*语法分析*/
int g_error;
int g_lb;
const char* g_pos;
NODE* MakeNode(int type, double value, int ope, NODE* l, NODE* r, NODE* p)
{
NODE* node = (NODE*)malloc(sizeof(NODE));
node->type = type;
node->value = value;
node->ope = ope;
node->left = l;
node->right = r;
node->parent = p;
return node;
}

void DestroyTree(NODE* tree)
{
if (!tree) return;
if (tree->left) DestroyTree(tree->left);
if (tree->right) DestroyTree(tree->right);
free(tree);
}

int Level(int ope)
{
switch(ope)
{
case ATOM:return 0;
case MUL:case DIV: return 1;
case ADD:case SUB: return 2;
case EXPR:return 32;
}
}

void ShowError()
{
char buff[256]={0};

switch (g_error)
{
case 1:sprintf(buff, "需要一个运算符\t位置%s\n", g_pos);break;
case 2:sprintf(buff, "需要一个表达式\t位置%s\n", g_pos);break;
case 3:sprintf(buff, "括号不匹配\t位置%s\n", g_pos);break;
case 4:sprintf(buff, "空表达式\t位置%s\n", g_pos);break;
case 5:sprintf(buff, "表达式不应该在此结束\t位置%s\n", g_pos);break;
}
printf(buff);
}

NODE* BuildSyntaxTreeImpl()
{
NODE* root, *c, *new_node;
int use_level = 0;
int state = 0;
root = c = MakeNode(OPERATOR, 0, EXPR, 0, 0, 0);
while (1)
{
GetNextToken();
switch (g_type)
{
case NUMBER:
if (state != 0)
{
PutBack();
g_error = 1;
goto ExitWithError;
}
new_node = MakeNode(NUMBER, g_value, ATOM, 0, 0, 0);
use_level=1;
state = 1;
break;
case LB:
if (state != 0)
{
PutBack();
g_error = 1;
goto ExitWithError;
}
++g_lb;
new_node = BuildSyntaxTreeImpl();
if (new_node == NULL)
{
g_error = 4;
goto ExitWithError;
}
use_level=0;/*括号表达式的优先级很高,不使用优先级比较,直接建为右子树*/
state = 1;
break;
case RB:
if (!g_lb)
{
g_error = 3;
goto ExitWithError;
}
--g_lb;
case END:
{
c = root->right;
free(root);
if (c == NULL)
{
g_error = 4;
goto ExitWithError;
}
if (state != 1)
{
g_error = 5;
goto ExitWithError;
}
c->parent = NULL;
return c;
}
default:
if (state != 1)
{
PutBack();
g_error = 2;
goto ExitWithError;
}
new_node = MakeNode(OPERATOR, 0, g_ope, 0, 0, 0);
use_level=1;
state = 0;
}

if (use_level)
{
while (Level(new_node->ope) >= Level(c->ope)) c = c->parent;

new_node->left = c->right;
c->right = new_node;
new_node->parent = c;
c = new_node;
}
else
{
c->right = new_node;
new_node->parent = c;
}

}

ExitWithError:
g_pos = g_str;
DestroyTree(root);
return 0;
}

NODE* BuildSyntaxTree(const char* expression)
{
NODE* tree;
g_lb = 0;
g_last_str = g_str = expression;
tree = BuildSyntaxTreeImpl();
if (g_lb)
{
PutBack();
g_error = 3;
g_pos = g_str;
DestroyTree(tree);
tree = 0;
}
return tree;
}

/*结果计算*/
double EvalueTree(NODE* tree)
{
double l, r;
if (!tree) return 0;
if (tree->ope==ATOM) return tree->value;
l = EvalueTree(tree->left);
r = EvalueTree(tree->right);
switch(tree->ope)
{
case ADD: return l + r;
case SUB: return l - r;
case MUL: return l * r;
case DIV: return l / r;
}
return 0;
}

double Evalue(const char* expression)
{
NODE* tree = BuildSyntaxTree(expression);
double value = 0;
if (!tree) ShowError();
else value = EvalueTree(tree);
DestroyTree(tree);
return value;
}

int main()
{
printf("%lf\n", Evalue("1+8*(9-8)*9+2-1"));
return 0;
}

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧