在下面的例子中,我们便写了一个更高级的计算器程序,其操作实例如下:
x = 0;
while(x < 3) {
print(x);
x = x + 1;
}
例子中得到的输出结果如下:
0
1
2
首先是我们的全局头文件test3.h:
typedef enum {
typeCon,
typeId,
typeOpr
} nodeEnum;
/* constants */
typedef struct {
int value; /* value of constant */
} conNodeType;
/* identifiers */
typedef struct {
int i; /* subscript to sym array */
} idNodeType;
/* operators */
typedef struct {
int oper; /* operator */
int nops; /* number of operands */
struct nodeTypeTag *op[1]; /* operands (expandable) */
} oprNodeType;
typedef struct nodeTypeTag {
nodeEnum type; /* type of node */
/* union must be last entry in nodeType */
/* because operNodeType may dynamically increase */
union {
conNodeType con; /* constants */
idNodeType id; /* identifiers */
oprNodeType opr; /* operators */
};
} nodeType;
extern int sym[26];
下面是Flex语言文件test3ll.l:
%{
#include <stdlib.h>
#include "test3.h"
#include "test3yy.h"
int 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;
"if" return IF;
"else" return ELSE;
"print" return PRINT;
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void)
{
return 1;
}
然后是我们的Bison文件test3yy.y:
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "test3.h"
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id(int i);
nodeType *con(int value);
void freeNode(nodeType *p);
int yylex(void);
int yyerror(char *s);
int sym[26];
%}
%union {
int iValue; /* integer value */
char sIndex; /* symbol table index */
nodeType *nPtr; /* node pointer */
};
%token <iValue> INTEGER
%token <sIndex> VARIABLE
%token WHILE IF PRINT
%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); }
|
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = $1; }
| PRINT expr ';' { $$ = opr(PRINT, 1, $2); }
| VARIABLE '=' expr ';' { $$ = opr('=', 2, id($1), $3); }
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); }
| 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);
}
int yyerror(char *s) {
fprintf(stdout, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
上面的Flex和Bison代码所作的工作是根据语法建立语意描述树结构。延续我们上面计算器的例子,我们写出如何翻译这些语言的实现部分(对生成的树进行第归分析):
#include <stdio.h>
#include "test3.h"
#include "test3yy.h"
int ex(nodeType *p) {
if(!p) return 0;
switch(p->type) {
case typeCon:
return p->con.value;
case typeId:
return sym[p->id.i];
case typeOpr:
switch(p->opr.oper) {
case WHILE:
while(ex(p->opr.op[0]))
ex(p->opr.op[1]);
return 0;
case IF:
if(ex(p->opr.op[0]))
ex(p->opr.op[1]);
else if(p->opr.nops > 2)
ex(p->opr.op[2]);
return 0;
case PRINT:
printf("%d\n", ex(p->opr.op[0]));
return 0;
case ';':
ex(p->opr.op[0]);
return ex(p->opr.op[1]);
case '=':
return sym[p->opr.op[0]->id.i] = ex(p->opr.op[1]);
case UMINUS:
return -ex(p->opr.op[0]);
case '+':
return ex(p->opr.op[0]) + ex(p->opr.op[1]);
case '-':
return ex(p->opr.op[0]) - ex(p->opr.op[1]);
case '*':
return ex(p->opr.op[0]) * ex(p->opr.op[1]);
case '/':
return ex(p->opr.op[0]) / ex(p->opr.op[1]);
case '<':
return ex(p->opr.op[0]) < ex(p->opr.op[1]);
case '>':
return ex(p->opr.op[0]) > ex(p->opr.op[1]);
case GE:
return ex(p->opr.op[0]) >= ex(p->opr.op[1]);
case LE:
return ex(p->opr.op[0]) <= ex(p->opr.op[1]);
case NE:
return ex(p->opr.op[0]) != ex(p->opr.op[1]);
case EQ:
return ex(p->opr.op[0]) == ex(p->opr.op[1]);
}
}
}
一般实际的编译器都是以汇编代码输出的,所以我们在这里进行一些深入研究,得出了另一个版本的ex函数实现,能够实现汇编代码的输出(compiler.c):
#include <stdio.h>
#include "test3.h"
#include "test3yy.h"
static int lbl;
int ex(nodeType *p) {
int lbl1, lbl2;
if(!p) return 0;
switch(p->type) {
case typeCon:
printf("\tpush\t%d\n", p->con.value);
break;
case typeId:
printf("\tpush\t%c\n", p->id.i + 'a');
break;
case typeOpr:
switch(p->opr.oper) {
case WHILE:
printf("L%03d:\n", lbl1 = lbl++);
ex(p->opr.op[0]);
printf("\tjs\tL%03d\n", lbl2 = lbl++);
ex(p->opr.op[1]);
printf("\tjz\tL%03d\n", lbl1);
printf("L%03d:\n", lbl2);
break;
case IF:
ex(p->opr.op[0]);
if(p->opr.nops > 2) {
/* if else */
printf("\tjs\tL%03d\n", lbl1 = lbl++);
ex(p->opr.op[1]);
printf("\tjmp\tL%03d\n", lbl2 = lbl++);
printf("L%03d:\n", lbl1);
ex(p->opr.op[2]);
printf("L%03d:\n", lbl2);
} else {
/* if */
printf("\tjs\tL%03d\n", lbl1 = lbl++);
ex(p->opr.op[1]);
printf("L%03d:\n", lbl1);
}
break;
case PRINT:
ex(p->opr.op[0]);
printf("\tprint\n");
break;
case '=':
ex(p->opr.op[1]);
printf("\tpop\t%c\n", p->opr.op[0]->id.i + 'a');
break;
case UMINUS:
ex(p->opr.op[0]);
printf("\tneg\n");
break;
default:
ex(p->opr.op[0]);
ex(p->opr.op[1]);
switch(p->opr.oper) {
case '+': printf("\tadd\n"); break;
case '-': printf("\tsub\n"); break;
case '*': printf("\tmul\n"); break;
case '/': printf("\tdiv\n"); break;
case '<': printf("\tcompLT\n"); break;
case '>': printf("\tcompGT\n"); break;
case GE: printf("\tcompGE\n"); break;
case LE: printf("\tcompLE\n"); break;
case NE: printf("\tcompNE\n"); break;
case EQ: printf("\tcompEQ\n"); break;
}
}
}
return 0;
}
使用方法:取消interpreter.c的编译,取而代之用compiler.c即可。关于这个计算器的代码分析,请等待后续,(未完待续)
2023年7月31日 03:53
Para continuar, primero debe acceder al código QR de linkphone y escanear el código QR. Puede comenzar a usar su teléfono en la computadora visitando aka.ms/phonelinkqrc. Si no está interesado en enviar por correo electrónico imágenes, www.aka.msn/phonelinkqrc películas y otros archivos a su PC, debe usar esta función conectando su teléfono a su PC. Las mejores aplicaciones que debes tener en tu smartphone. Puede descargarlo ahora mismo desde el sitio web oficial de Microsoft haciendo clic en este enlace.
2023年7月31日 23:26
SCERT Sikkim Follows NCERT Curriculum These Textbooks are Updated as per the Syllabus Prescribed by SCERT Sikkim. Students of 2nd Class Should follow Prescribed Textbooks while Preparing for Exam.Our Sikkim 2nd Class Textbook 2024 Team Refer to the Respective Subject Textbook while Preparing the Final Important questions. Students Best Practice Study Materiel about Textbooks are the Fact that they are so Comprehensible that it does not require the aid of a Subject Literate.SCERT Sikkim once Publishes the Sikkim Elementary School Textbooks 2024 Other Study materials on the official web site, we will update the Information on this page.