📄 用yacclex设计实现小型basic语言.txt
字号:
"then" { SetInteger(THEN);return THEN; }
"else" { SetInteger(ELSE);return ELSE; }
"for" { SetInteger(FOR);return FOR; }
"while" { SetInteger(WHILE);return WHILE; }
"to" { SetInteger(TO);return TO; }
"downto" { SetInteger(DOWNTO);return DOWNTO; }
"do" { SetInteger(DO);return DO; }
"of" { SetInteger(OF);return OF; }
"record" { SetInteger(RECORD);return RECORD; }
"with" { SetInteger(WITH);return WITH;}
("quit"|"q") { SetInteger(EXIT);return EXIT; }
("exit"|"e") { SetInteger(EXIT);return EXIT; }
("print"|"?") {SetInteger(PRINT);return PRINT;}
"run" { SetInteger(RUN);return RUN;}
{Letter}{Id}* {
/* ID */
SetString(yytext);
return ID;
}
\"({NQUOTE}|\"\")*\" {
/* short string */
SetString(yytext);
DeleteChar('\"');
return SHORTSTRING;
}
{DecDigit}{Digit}* {
/* dec */
SetDWord(strtoul(yytext,NULL,10));
return(UNSIGNED_NUMBER);
}
{Zero}{OctDigit}* { /* oct */
SetDWord(strtoul(yytext,NULL,8));
return(UNSIGNED_NUMBER);
}
{Zero}{HexPrev}{HexDigit}+ { /* hex */
SetDWord(strtoul(yytext,NULL,16));
return(UNSIGNED_NUMBER);
}
{Digit}+"."{Digit}+ {
/* float */
SetReal(atof(yytext));
return(REALNUMBER);
}
{Digit}+"."{Digit}+[Ee][+-]?{Digit}+ {
/* sce */
SetReal(atof(yytext));
return(REALNUMBER);
}
"//".* ; { /* line comments */ }
{SPACE} ;
. |
%%
6、 语法分析:使用YACC来生成语法数。这里同时就生成了代码,没有考虑代码优化的问题。
%{
%}
// 这是 Token 的数据结构
%Union {
int Integer;
DWord UnsignedNumber;
double Real;
Char *String;
struct {
double noused;
int Type;
} Info;
}
%token UNSIGNED_NUMBER REALNUMBER SHORTSTRING ID
%token LT LE EQUAL NE GE GT ASSIGN
%token PLUS MINUS STAR SLASH MOD SHL SHR BITNOT BITAND BITOR
%token LPAREN RPAREN OR AND NOT COMMA SEMICOLON COLON DOT
%token LBRACKET RBRACKET BIGLPAREN BIGRPAREN
%token DIM AS ARRAY CASE FUNCTION PROCEDURE PROGRAM LABEL
%token CHAR BYTE INTEGER DWORD REAL STRING
%token RECORD CONST BYVAL
%token IF THEN ELSE FOR TO DOWNTO DO WHILE OF GOTO WITH
%token EXIT PRINT RUN
%type <Real> REALNUMBER
%type <UnsignedNumber> UNSIGNED_NUMBER
%type <String> SHORTSTRING ID
%type <Integer> LT LE EQUAL NE GE GT ASSIGN
%type <Integer> PLUS MINUS STAR SLASH MOD SHL SHR BITNOT BITAND BITOR
%type <Integer> LPAREN RPAREN OR AND NOT COMMA SEMICOLON COLON DOT
%type <Integer> LBRACKET RBRACKET BIGLPAREN BIGRPAREN
%type <Integer> DIM AS ARRAY CASE FUNCTION PROCEDURE PROGRAM LABEL
%type <Integer> CHAR BYTE INTEGER DWORD REAL STRING
%type <Integer> IF THEN ELSE FOR TO DOWNTO WHILE OF GOTO WITH
%type <Integer> RECORD CONST BYVAL
%type <Integer> EXIT PRINT RUN
%type <Integer> relop addop mulop signop datatype logicop
%type <Integer> variable variable_list label
%type <Integer> primary factor term expression simple_expression expr expr_list
%type <Integer> compilation_unit program program_header block
%type <Integer> decl_sect_list decl_sect proc_decl func_decl param_list
%type <Integer> proc_header func_header proc_block fp_list fp_sect_list fp_sect
%type <Integer> compound_statement stmt_list stmt normal_stmt
%type <Integer> dim_statement goto_statement for_statement if_statement
%type <Integer> while_statement with_statement assign_statement proccall_statement
%type <Integer> run_statement
%type <Integer> print_statement print_expr_list print_dot
%right THEN ELSE // 个别需要右结合的 Token
%%
compilation_unit:program
;
program:program_header block
;
program_header: {}
|PROGRAM
|PROGRAM ID SEMICOLON
;
block :decl_sect_list compound_statement
;
decl_sect_list: {}
|decl_sect_list decl_sect
;
decl_sect:proc_decl
|func_decl
;
proc_decl:proc_header proc_block
;
func_decl:func_header proc_block
;
proc_header:PROCEDURE ID fp_list
;
func_header:FUNCTION ID fp_list AS datatype
;
proc_block:block
;
fp_list:{}
|LPAREN fp_sect_list RPAREN
;
fp_sect_list:fp_sect
|fp_sect_list SEMICOLON fp_sect
;
fp_sect:variable_list AS datatype
|BYVAL variable_list AS datatype
;
compound_statement:BIGLPAREN stmt_list BIGRPAREN
;
stmt_list:stmt
|stmt_list SEMICOLON stmt
;
stmt:normal_stmt
|label COLON normal_stmt
;
normal_stmt:{} /* empty */
|dim_statement
|assign_statement
|proccall_statement
|goto_statement
|compound_statement
|if_statement
|for_statement
|while_statement
|with_statement
|print_statement
|run_statement
;
run_statement:RUN {exec();}
|EXIT {exit(0);}
print_statement:PRINT print_expr_list { WriteCode(C_PRINT_LINE); }
;
print_expr_list:expr { WriteCode(C_PRINT_EXPR);}
|print_expr_list print_dot expr {WriteCode(C_PRINT_EXPR);}
;
print_dot:COMMA {WriteCode(C_PRINT_COMMA);}
|COLON {WriteCode(C_PRINT_SEMICOLON);}
;
dim_statement:DIM variable AS datatype {
PVariant p;
p=GetData($2);
VarSetType(p,$4);
}
;
assign_statement:variable ASSIGN expr {
WriteCode2(C_POPVAR,$1);
}
;
proccall_statement:ID param_list {}
;
goto_statement:GOTO label {WriteCode2(C_JMP,$2);}
;
label :ID {
DWord d;
d=GetVar($1);
if(d==OUTOFSTRINGINDEX) {
d=GetIP();
EnterVar($1,d);
}
$$=d;
}
;
if_statement:IF expr {
WriteCode(C_POPCMP);
$2=GetIP();
WriteCode2(C_JEQ,0);
} THEN stmt {
SetCode($2+1,GetIP());
}
;
while_statement:WHILE {
$1=GetIP();
} expr {
WriteCode(C_POPCMP);
$2=GetIP();
WriteCode2(C_JEQ,0);
} DO stmt {
WriteCode2(C_JMP,$1);
SetCode($2+1,GetIP());
}
;
for_statement:FOR variable ASSIGN expr {
$4=GetIP();
WriteCode2(C_POPVAR,$2);
WriteCode2(C_PUSHVAR,$2);
} TO expr {
WriteCode2(C_RELOP,LE);
}
DO {
WriteCode(C_POPCMP);
$6=GetIP();
WriteCode2(C_JEQ,0);
} stmt {
WriteCode2(C_PUSHVAR,$2);
WriteCode2(C_PUSHINTEGER,1);
WriteCode2(C_ADDOP,PLUS);
WriteCode2(C_JMP,$4);
SetCode($6+1,GetIP());
}
;
with_statement:WITH variable DO stmt
;
param_list: {}/* empty */
|LPAREN expr_list RPAREN
;
expr_list:expr
|expr_list COMMA expr
;
expr:simple_expression
|NOT simple_expression
|expr logicop simple_expression
;
simple_expression:expression
|expression relop expression {WriteCode2(C_RELOP,$2);}
;
expression:term
|expression addop term {WriteCode2(C_ADDOP,$2);}
;
term :factor
|term mulop factor { WriteCode2(C_MULOP,$2);}
|BITNOT factor
;
factor :signop factor {WriteCode2(C_SIGNOP,$1);}
|primary
;
primary :variable {WriteCode2(C_PUSHVAR,$1);}
|UNSIGNED_NUMBER { WriteCode2(C_PUSHINTEGER,$1);}
|REALNUMBER {
double r;
DWord *d;
WriteCode(C_PUSHREAL);
r=$1;
d=(DWord *)&r;
WriteCode2(*d,*(d+1));
}
|SHORTSTRING {
char *s;
s=strdup($1);
WriteCode(C_PUSHSTRING);
WriteCode((DWord)s);
}
|LPAREN expr RPAREN
|ID LPAREN expr_list RPAREN {} /* type cast, function call */
;
logicop :AND
|OR
;
relop :EQUAL
|NE
|LT
|LE
|GT
|GE
;
addop :PLUS
|MINUS
;
mulop :STAR
|SLASH
|MOD
|SHL
|SHR
|BITAND
|BITOR
;
signop :addop
;
variable_list:variable
|variable_list COMMA variable
;
variable:ID {
PSymbolTable q;
PVariant p;
DWord d;
d=GetVar($1);
if(d==OUTOFSTRINGINDEX) {
d=GetFreeDIP();
EnterVar($1,d);
InitData(d,NOTYPE);
}
$$=d;
}
|variable LBRACKET expr_list RBRACKET /* array */
|variable DOT ID /* record */
|variable '^' /* pointer */
|ID LPAREN variable RPAREN {} /* type cast */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -