今は、中間コードの生成をやっています。
関数generateは、中間コードを生成する関数です。
以下のパーサプログラムは、簡単な四則演算プログラムに対して正しく動作します。
以下のプログラムに、手続き,制御文,入出力が処理できるようなコードを追加したいのですが、
どのように書けばよいのかがわかりません。
backpatchを使えばできるそうなんですが、どのように書けばよいのか教えてください。
よろしくお願いします。
%{
#define MAXLENGTH 16
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "code.h"
#include "optype.h"
struct LIST
{
char name[MAXLENGTH+1];
int flag;
int addr;
struct LIST *next;
};
struct LIST head;
int flg;
FILE *fp;
int address=0;
int n=0;
%}
%union {
int num;
char ident[MAXLENGTH+1];
}
%token SBEGIN DO ELSE SEND
%token FOR FORWARD FUNCTION IF PROCEDURE
%token PROGRAM READ THEN TO VAR
%token WHILE WRITE
%left PLUS MINUS
%left MULT DIV
%token EQ NEQ LE LT GE GT
%token LPAREN RPAREN LBRACE RBRACE
%token COMMA SEMICOLON COLON INTERVAL
%token PERIOD ASSIGN
%token <num> NUMBER
%token <ident> IDENT
%%
program
:{fp = fopen("result.code", "wb");} PROGRAM IDENT SEMICOLON outblock PERIOD{close(fp);}
;
outblock
: var_decl_part subprog_decl_part statement
;
var_decl_part
: /* empty */
| var_decl_list SEMICOLON
;
var_decl_list
: var_decl_list SEMICOLON var_decl
| var_decl
;
var_decl
: VAR id_list
;
subprog_decl_part
: subprog_decl_list SEMICOLON
| /* empty */
;
subprog_decl_list
: subprog_decl_list SEMICOLON subprog_decl
| subprog_decl
;
subprog_decl
: proc_decl
;
proc_decl
: PROCEDURE proc_name SEMICOLON local_begin inblock local_end{delete();}
;
proc_name
: IDENT{insert($1,2);}
;
inblock
: var_decl_part statement
;
statement_list
: statement_list SEMICOLON statement
| statement
;
statement
: assignment_statement
| if_statement
| while_statement
| for_statement
| proc_call_statement
| null_statement
| block_statement
| read_statement
| write_statement
;
assignment_statement
: IDENT ASSIGN expression{lookup($1);}{generate(STO,0,0,address++);}
;
if_statement
: IF condition THEN statement else_statement
;
else_statement
: ELSE statement
| /* empty */
;
while_statement
: WHILE condition DO statement
;
for_statement
: FOR IDENT ASSIGN expression TO expression DO statement{lookup($2);}
;
proc_call_statement
: proc_call_name
;
proc_call_name
: IDENT{lookup($1);}
;
block_statement
: SBEGIN statement_list SEND
;
read_statement
: READ LPAREN IDENT RPAREN{lookup($3);}
;
write_statement
: WRITE LPAREN expression RPAREN
;
null_statement
: /* empty */
;
condition
: expression EQ expression
| expression NEQ expression
| expression LT expression
| expression GT expression
| expression LE expression
| expression GE expression
;
expression
: term
| PLUS term
| MINUS term
{
generate(OPR,0,0,0);
}
| expression PLUS term
{
generate(OPR,0,0,1);
}
| expression MINUS term
{
generate(OPR,0,0,2);
}
;
term
: factor
| term MULT factor
| term DIV factor
;
factor
: var_name
| NUMBER{generate(LIT,0,0,$1);}
| LPAREN expression RPAREN
;
var_name
: IDENT{lookup($1);}{generate(LOD,0,0,n++);}
;
arg_list
: expression
| arg_list COMMA expression
;
id_list
: IDENT{insert($1,flg);}{generate(LIT,0,0,0);}
| id_list COMMA IDENT{insert($3,flg);}{generate(LIT,0,0,0);}
;
local_begin:{flg++;}
local_end:{flg--;}
%%
yyerror(char *s)
{
extern yylineno;
extern *yytext;
fprintf(stderr, "%s\n", s);
fprintf(stderr, "line%d %s\n",yylineno,yytext);
}
insert(char *name, int flag){
struct LIST *p,*q,*new;
p = head.next;
q = &head;
while(p != NULL){
q = p;
p = p->next;
}
new = malloc(sizeof(struct LIST));
if(new == NULL){
printf("error\n");
return;
}
strcpy(new->name,name);
new->flag = flag;
new->next = p;
q->next = new;
printf("insert:%s %d\n",name,address);
printAll();
}
lookup(char *name){
struct LIST *p,*q,*list;
p = head.next;
q = &head;
while(1){
if(strcmp(q->name,name) == 0){
list = q;
}
if(p == NULL) break;
q = p;
p = p->next;
}
printf("lookup:");
printf(" %s %d\n",list->name,list->flag);
}
delete(){
struct LIST *p, *q;
p = head.next;
q = &head;
while(1){
if(q->flag == 2){
if(p->flag != 2){
q->next = p->next;
}
}
if(p == NULL) break;
q = p;
p = p->next;
}
printf("\n");
printf("delete local\n");
printAll();
}
printAll(void){
struct LIST *list_ptr;
printf("------------------table----------------------\n");
for(list_ptr = head.next; list_ptr != NULL; list_ptr=list_ptr->next){
printf("%s %d\n",list_ptr->name, list_ptr->flag);
}
printf("---------------------------------------------\n");
}
generate(int opcode, REG base, REG index, REG address){
OPCODE *op;
op = malloc(sizeof(OPCODE));
op->opcode = opcode;
op->basereg = base;
op->indexreg = index;
op->address = address;
fwrite(op,sizeof(OPCODE),1,fp);
}