C语言的教材中有列出各种操作符的优先级。我们编写编译器的时候可以按早教材中定义的优先级编写程序,但是也可以自己定义。通常这样的优先级用一个表格表示。
所以在编译器程序中也可以用结构体数组来定义这个优先级表( operator priority table),简称OPT
1.首先有个tokentype
typedef enum Token_Type{
ID,NUM,EXP,/*JUDGE SYMBOL*/
IF,ELSE,DO,WHILE,SWITCH,CASE,INT,LONG,DOUBLE,FLOAT,CHAR,BREAK,FOR,
EQ,LS,LE,GT,GE,NE, //EQ =,LS <,LE <= ,GT >, GE >=, NE !=
ASSIGN, //'='
ADD,SUB,MUL,DIV,INC,DEC,MOD,//OP + , - , * , / ,++,--
LC,RC, // '(' ')'
LR,RR, // '[' ']'
LS,RS, // '{' '}'
OR,AND,NOT, // '|' '&' '!'
SEMI,// ';'
SHARP,//'#'
ENDFILE,
ERROR
}TOKEN_TYPE;
2.然后定义优先级结构体
typedef struct Opt{
TOKEN_TYPE op;
int Proirity;
}OPT;
3.然后定义一个优先级表
OPT opt[NUM_OP]={
{INC,1},
{DEC,1},
{MUL,2},
{DIV,2},
{MOD,2},
{ADD,3},
{SUB,3}
}; //biger proirity number,lower proirity
4.写个得到优先级的函数
int get_proirity(TOKEN_TYPE tt){
int i;
for(i=0;i<NUM_OP;i++){
if(opt[i].op==tt)
return opt[i].Proirity;
}
}
5。扫描函数get token
TOKEN_TYPE GetToken(void){
int tokenBufferIndex=0;
char ch;
TOKEN_TYPE tt;
TOKEN_STATE state=INIT;
while(state!=DONE){
ch=getc(fps);
switch(state){
case INIT: if(isdigit(ch))
{
state=INNUM;
tokenStr[tokenBufferIndex++]=ch;
}
else if (isalpha(ch)){
state=INID;
tokenStr[tokenBufferIndex++]=ch;}
else if((ch==' ')||ch=='/t') state=INIT;
else {
switch(ch){
case '=' : ch=getc(fps);
if(ch=='=') tt=EQ;
else {
ungetc(ch,fps);
tt= ASSIGN;
}
break;
case '<' : ch=getc(fps);
if(ch=='=') tt=LE;
else if(ch=='>') tt=NE;
else {
ungetc(ch,fps);
tt= LS;
}
break;
case '>' : ch=getc(fps);
if(ch=='=') tt= GE;
else {
ungetc(ch,fps);
tt= GT;
}
break;
case '|': tt=OR;
state=DONE;
break;
case '&': tt=AND;
state=DONE;
break;
case '!': tt=NOT;
state=DONE;
break;
case '+': ch=getc(fps);
if(ch=='+') tt= INC;
else{
tt= ADD;
ungetc(ch,fps);
}
state=DONE;
break;
case '-': ch=getc(fps);
if(ch=='-') tt= DEC;
else{
ungetc(ch,fps);
tt=SUB;
}
state=DONE;
break;
case '*':
tt= MUL;
state=DONE;
break;
case '/': state=IN_MARK;
break;
case '/n': lineno++;
break;
case '#': tt=SHARP;
break;
case ';' : tt= SEMI;
state=DONE;
break;
case '(' : tt= LC;
state=DONE;
break;
case ')' : tt= RC;
state=DONE;
break;
case '[' : tt= LR;
state=DONE;
break;
case ']' : tt= RR;
state=DONE;
break;
case '{' : tt= LS;
state=DONE;
break;
case '}' : tt= RS;
state=DONE;
break;
case EOF:
tt=ENDFILE;
state=DONE;
break;
default : break;
}
}
break;
case IN_MARK:
if(ch=='*') state= IN_MARK_SEG;
else if(ch=='/') state= IN_MARK_LINE;
else {
ungetc(ch,fps);
tt=DIV;
state=DONE;
}
break;
case IN_MARK_SEG:
if(ch=='*') state=IN_MARK_SEG1;
break;
case IN_MARK_SEG1:
if(ch=='/') state=INIT;
break;
case IN_MARK_LINE:
if(ch=='/n') state=INIT;
break;
case INNUM: if(isdigit(ch))
tokenStr[tokenBufferIndex++]=ch;
else
{ tokenStr[tokenBufferIndex]='/0';
state=DONE;
ungetc(ch,fps);
tt=NUM;
}
break;
case INID: if(isalpha(ch))
tokenStr[tokenBufferIndex++]=ch;
else{
tokenStr[tokenBufferIndex]='/0';
state=DONE;
ungetc(ch,fps);
tt=ID;
}
break;
case DONE: break;
}
}
if(tt==ID){
fprintf(fpt,"Get ID -->%s/n",tokenStr);
}
else if(tt==NUM)
fprintf(fpt,"Get NUM -->%s/n",tokenStr);
return tt;
}
6.编写主函数
//main.c
/*
programed by:alex shoal
edit date:2009-7-11, Satday
revision:2
****************
*Question:How to get the priority of operator?
****************
*/
#include <stdio.h>
#include <stdlib.h>
#include "global.h"
#include "scan.h"
#include "opt.h"
FILE *fps; //* file point of source
FILE *fpt; //* file point of target
int lineno=0;
int main(int argc, char *argv[]){
TOKEN_TYPE tp;
int j=0;
fpt=stdout;
if (argc != 2){
printf("Usage: %s filename/n", argv[0]);
exit(1);
}
if ((fps = fopen(argv[1], "r")) == NULL){
printf("Can't open file :%s/n", argv[1]);
exit(1);
}
if ((fpt = fopen("out.txt", "w+")) == NULL){
printf("Can't open file :out.txt /n");
exit(1);
}
while (((tp = GetToken()) != ENDFILE)){
switch (tp){
case ADD:
j=get_proirity(tp);
fprintf(fpt,"the proirity of OP [ADD] is %d/n",j);
break;
case SUB:
j=get_proirity(tp);
fprintf(fpt,"the proirity of OP [SUB] is %d/n",j);
break;
case MUL:
j=get_proirity(tp);
fprintf(fpt,"the proirity of OP [MUL] is %d/n",j);
break;
case DIV:
j=get_proirity(tp);
fprintf(fpt,"the proirity of OP [DIV] is %d/n",j);
break;
case INC:
j=get_proirity(tp);
fprintf(fpt,"the proirity of OP [INC] is %d/n",j);
break;
case DEC:
j=get_proirity(tp);
fprintf(fpt,"the proirity of OP [DEC] is %d/n",j);
break;
default:
break;
}
}
fclose(fps);
return 0;
}
7. 编译程序,得到可执行程序 比如可执行文件名为 opt.exe
8。写个输入文件,含一些操作符
//filename: in.txt
a + b - c * 3 / 2 + i++ - j--
9. 运行程序
opt.ext in.txt
10。产看结果,从程序主函数中可看到,
运行之后有个 out.txt 产生。
打开 out.txt 可看到内容
Get ID -->a
the proirity of OP [ADD] is 3
Get ID -->b
the proirity of OP [SUB] is 3
Get ID -->c
the proirity of OP [MUL] is 2
Get NUM -->3
the proirity of OP [DIV] is 2
Get NUM -->2
the proirity of OP [ADD] is 3
Get ID -->i
the proirity of OP [INC] is 1
the proirity of OP [SUB] is 3
Get ID -->j
the proirity of OP [DEC] is 1
由此可见函数运行基本正常。