1.lex.l文件
%{
#include "stdio.h"
#include "trans.tab.h"//一定要添加该头文件,和后面的语法分析配合
%}
DIGIT [0-9] //申明DIGIT的正则表达式
%%//以上均是申明
{DIGIT}+ { yylval = atoi(yytext); return NUM;} /*printf("int: %s(%d)\n",yytext,atoi(yytext));}*/
\n { return END; }
"+" { return ADD; }
"-" { return MINUS;}
"*" { return MUL; }
"/" { return DIV;}
%%//以上均是正则表达式
int yywrap()
{ return 1; }
如果只要词法分析,代码可以有如下修改
%{
#include "stdio.h"
#include "trans.tab.h"//一定要添加该头文件,和后面的语法分析配合
%}
DIGIT [0-9] //申明DIGIT的正则表达式
%%//以上均是申明
{DIGIT}+ { yylval = atoi(yytext); return NUM;} /*printf("int: %s(%d)\n",yytext,atoi(yytext));}*/
\n { return END; printf("换行符");}
"+" { return ADD; printf("运算符:“+”");}
%%//以上均是正则表达式
int yywrap()
{ return 1; }
1.文法
input -> input line |
line -> '\n' | E '\n'
E -> T | E add T | E minus T
T -> F | T mul F | T div F
F -> (E) | NUM
2.创建trans.y文件
申明部分
%{
#include "lex.yy.c"
#include
#include
#include
#include
//语法树的结构
typedef char* ElemType;
int i;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lChild, *mChild, *rChild;
}BiTNode, *BiTree;
typedef struct Node{
BiTNode *data;
struct Node *next;
}Node, *LinkedList;
void yyerror (char const *);
//创建链表
LinkedList LinkedListInit()
{
Node *L;
L = (Node *)malloc(sizeof(Node));
L->next = NULL;
return L;
}
//插入节点,头插法
LinkedList LinkedListInsert(LinkedList L,BiTNode *x)
{
Node *pre;
pre = L;
Node *p;
p = (Node *)malloc(sizeof(Node));
p->data = x;
p->next = pre->next;
pre->next = p;
return L;
}
//创建叶子
BiTree createLeaf(ElemType root)
{
BiTree T = (BiTree)malloc(sizeof(BiTNode));
if (T != NULL) {
T->data = root;
T->lChild = NULL;
T->mChild = NULL;
T->rChild = NULL;
}
else exit(-1);
return T;
}
BiTree createTree(ElemType root, BiTree lleaf, BiTree mleaf, BiTree rleaf)
{
BiTree T = (BiTree)malloc(sizeof(BiTNode));
if (T != NULL) {
T->data = root;
T->lChild = lleaf;
T->mChild = mleaf;
T->rChild = rleaf;
}
else exit(-1);
return T;
}
//后序遍历
void TraverseBiTree(BiTree T)
{
if (T == NULL) return ;
TraverseBiTree(T->lChild);
TraverseBiTree(T->mChild);
TraverseBiTree(T->rChild);
if(T->data != " ") printf("%s ", T->data);
}
//变量的申明,全局变量必须赋初值
LinkedList list = NULL;
LinkedList head = NULL;
BiTree T, TL, TM, TR;
%}
//从词法分析中提取出来
%token END
%token NUM
%token ADD
%token MUL
%token MINUS
%token DIV
%% /* Grammar rules and actions follow. */
文法部分
input:
/* empty */
| input line
;
line:
'\n' { }
| exp END { head = list->next;
T = head->data;
printf("Traverse BiTree:\n");
TraverseBiTree(T);
printf("\n");
printf ("answer:%d\n", $1);}
;
exp:
term { $$ = $1; printf("E->T\n");
head = list->next;
TL = head->data;
TM = createLeaf(" ");
TR = createLeaf(" ");
T = createTree("E", TL, TM, TR);
list->next = head->next;
LinkedListInsert(list, T); }
| exp ADD term { $$ = $1 + $3; printf("E->E+T\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("+");
TR = head->data;
T = createTree("E", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T); }
| exp MINUS term { $$ = $1 - $3; printf("E->E-T\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("+");
TR = head->data;
T = createTree("E", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T); }
;
term:
factor { head = list->next; printf("T->F\n");
TL = head->data;
TM = createLeaf(" ");
TR = createLeaf(" ");
T = createTree("T", TL, TM, TR);
list->next = head->next;
LinkedListInsert(list, T);}
| term MUL factor { $$ = $1 * $3; printf("T->T*F\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("*");
TR = head->data;
T = createTree("T", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T); }
| term DIV factor { $$ = $1 / $3; printf("T->T/F\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("/");
TR = head->data;
T = createTree("T", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T);
}
;
factor:
'('exp')'
| NUM {
printf("F->%d\n", $1);
int num = $1;
int len = 0;
char* temp1 = (char*)malloc(sizeof(char)*10);//c语言中指针,数组等必须要赋给空间
char* temp2 = (char*)malloc(sizeof(char)*10);
while(num)
{
temp1[len] = '0'+num%10;
num /= 10;
len++;
}
for(i = 0; i < len; ++i)
{
temp2[i] = temp1[len-i-1];
}
temp2[len] = '\0';
TL = createLeaf(temp2);
TM = createLeaf(" ");
TR = createLeaf(" ");
T = createTree("F", TL, TM, TR);
LinkedListInsert(list, T);}
;
%%
主控程序部分
int
main(void)
{
list = LinkedListInit();
T = NULL, TL = NULL, TM = NULL, TR = NULL;
/*yydebug = 1;*/ /*bison -d -t*/ /*bison -d -v*/
yyparse();
return 0;
}
/* Called by yyparse on error. */
void
yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
整个trans.y文件
/* Reverse polish notation calculator. */
%{
#include "lex.yy.c"
#include
#include
#include
#include
typedef char* ElemType;
int i;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lChild, *mChild, *rChild;
}BiTNode, *BiTree;
typedef struct Node{
BiTNode *data;
struct Node *next;
}Node, *LinkedList;
void yyerror (char const *);
//创建链表
LinkedList LinkedListInit()
{
Node *L;
L = (Node *)malloc(sizeof(Node));
L->next = NULL;
return L;
}
//插入节点,头插法
LinkedList LinkedListInsert(LinkedList L,BiTNode *x)
{
Node *pre;
pre = L;
Node *p;
p = (Node *)malloc(sizeof(Node));
p->data = x;
p->next = pre->next;
pre->next = p;
return L;
}
//创建叶子
BiTree createLeaf(ElemType root)
{
BiTree T = (BiTree)malloc(sizeof(BiTNode));
if (T != NULL) {
T->data = root;
T->lChild = NULL;
T->mChild = NULL;
T->rChild = NULL;
}
else exit(-1);
return T;
}
BiTree createTree(ElemType root, BiTree lleaf, BiTree mleaf, BiTree rleaf)
{
BiTree T = (BiTree)malloc(sizeof(BiTNode));
if (T != NULL) {
T->data = root;
T->lChild = lleaf;
T->mChild = mleaf;
T->rChild = rleaf;
}
else exit(-1);
return T;
}
//后序遍历
void TraverseBiTree(BiTree T)
{
if (T == NULL) return ;
TraverseBiTree(T->lChild);
TraverseBiTree(T->mChild);
TraverseBiTree(T->rChild);
if(T->data != " ") printf("%s ", T->data);
}
LinkedList list = NULL;
LinkedList head = NULL;
BiTree T, TL, TM, TR;
%}
%token END
%token NUM
%token ADD
%token MUL
%token MINUS
%token DIV
%% /* Grammar rules and actions follow. */
input:
/* empty */
| input line
;
line:
'\n' { }
| exp END { head = list->next;
T = head->data;
printf("Traverse BiTree:\n");
TraverseBiTree(T);
printf("\n");
printf ("answer:%d\n", $1);}
;
exp:
term { $$ = $1; printf("E->T\n");
head = list->next;
TL = head->data;
TM = createLeaf(" ");
TR = createLeaf(" ");
T = createTree("E", TL, TM, TR);
list->next = head->next;
LinkedListInsert(list, T); }
| exp ADD term { $$ = $1 + $3; printf("E->E+T\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("+");
TR = head->data;
T = createTree("E", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T); }
| exp MINUS term { $$ = $1 - $3; printf("E->E-T\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("+");
TR = head->data;
T = createTree("E", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T); }
;
term:
factor { head = list->next; printf("T->F\n");
TL = head->data;
TM = createLeaf(" ");
TR = createLeaf(" ");
T = createTree("T", TL, TM, TR);
list->next = head->next;
LinkedListInsert(list, T);}
| term MUL factor { $$ = $1 * $3; printf("T->T*F\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("*");
TR = head->data;
T = createTree("T", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T); }
| term DIV factor { $$ = $1 / $3; printf("T->T/F\n");
head = list->next;
TL = (head->next)->data;
TM = createLeaf("/");
TR = head->data;
T = createTree("T", TL, TM, TR);
list->next = (head->next)->next;
LinkedListInsert(list, T);
}
;
factor:
'('exp')'
| NUM {
printf("F->%d\n", $1);
int num = $1;
int len = 0;
char* temp1 = (char*)malloc(sizeof(char)*10);//c语言中指针,数组等必须要赋给空间
char* temp2 = (char*)malloc(sizeof(char)*10);
while(num)
{
temp1[len] = '0'+num%10;
num /= 10;
len++;
}
for(i = 0; i < len; ++i)
{
temp2[i] = temp1[len-i-1];
}
temp2[len] = '\0';
TL = createLeaf(temp2);
TM = createLeaf(" ");
TR = createLeaf(" ");
T = createTree("F", TL, TM, TR);
LinkedListInsert(list, T);}
;
%%
int
main(void)
{
list = LinkedListInit();
T = NULL, TL = NULL, TM = NULL, TR = NULL;
/*yydebug = 1;*/ /*bison -d -t*/ /*bison -d -v*/
yyparse();
return 0;
}
/* Called by yyparse on error. */
void
yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
实验总结知识:
1:C语言中指针,数组等必须给空间,否则容易造成多个指针指向同一个位置
malloc用法
char* temp = (char*)malloc(sizeof(temp)*10) 等价于申明了空间 char temp[10]
char** temp = (char**)malloc(sizeof(temp*)*10) 等价于神明了空间 char* temp[10]
2:当你创建char temp[10]并在其中赋值后,务必要在最后添加'\0'
3:环境搭建:当你要在dos中直接运用bison -d trans.y ,须先将bison.exe添加到环境变量path中
方法:在path最后添加 ; 以及exe所在路径
4:问题:构造语法树的方法?还有没有别的方法了
5:当从输入流中想查看下一个字符,但是并不想读出它时
c++ : char c = cin.peek();
c : char c = getc(stdin);
ungetc(c, stdin);
用处 :从输入流123+456 想要分离出123 , + , 456 ,当每次用getchar()时,想要判断123是否结束,就需要getchar下一位
一旦getchar下一位了,就把“+”号“吃”掉了,用peek来判断下一位是否是数字