📄 parser.y
字号:
/* ---------------------------------------------------------------------- * FILE: as31.y * PACKAGE: as31 - 8031/8051 Assembler. * * DESCRIPTION: * This file contains the yacc parser for the assembler. * Related to this are the following: * error(), warn(), yyerror() * genbyte(), genword(), genstr(), makeop() * * * REVISION HISTORY: * Jan. 19, 1990 - Created. (Ken Stauffer) * * AUTHOR: * All code in this file written by Ken Stauffer (University of Calgary). * January 1990. * */%{#include <stdio.h>#include <stdlib.h>#define NOPE#include "as31.h"#undef NOPE#define YYSTYPE union ystackstatic unsigned char bytebuf[1024]; /* used by dumplist() */static int bytecount;void yyerror(const char *s);int makeop(struct opcode * op, struct mode *m, int add);void inclc(int i);char *padline(char *line);void dumplist(char *txt, int show);void genbyte(int b);void genstr(const char *s);void genword(unsigned long w);/* ------------------------ G R A M M E R ----------------------------- */%}%token STRING%token D_ORG%token D_BYTE%token D_WORD%token D_SKIP%token D_EQU%token D_FLAG%token D_END%token ACALL%token ADD%token ADDC%token AJMP%token ANL%token CJNE%token CLR%token CPL%token DA%token DEC%token DIV%token DJNZ%token INC%token JB%token JBC%token JC%token JMP%token JNB%token JNC%token JNZ%token JZ%token LCALL%token LJMP%token MOV%token MOVC%token MOVX%token NOP%token MUL%token ORL%token POP%token PUSH%token RET%token RETI%token RL%token RLC%token RR%token RRC%token SETB%token SJMP%token SUBB%token SWAP%token XCH%token XCHD%token XRL%token AB%token A%token C%token PC%token DPTR%token BITPOS%token R0%token R1%token R2%token R3%token R4%token R5%token R6%token R7%token VALUE%token SYMBOL%left '+' '-'%left '*' '/' '%'%left '|' '&'%left '>' '<'%start program%%program : linelist{} ;linelist : linelist line | line ;line : undefsym ':' linerest{ if (abort_asap) {YYABORT;} if( pass1 ) { $1.sym->type = LABEL; $1.sym->value = lc; } inclc($3.value); bytecount = 0;} | linerest { inclc($1.value); bytecount = 0; } ;linerest : directive '\n' { $$.value = $1.value; if( dashl && pass2 ) dumplist($2.str,1); } | instr '\n' { $$.value = $1.value; if( dashl && pass2 ) dumplist($2.str,1); } | '\n' { $$.value = 0; if( dashl && pass2 ) dumplist($1.str,0); } | error { seek_eol(); } '\n' { $$.value = 0; if( dashl && pass2 ) dumplist($1.str,0); } ;/* -------------------- * DIRECTIVES: * */directive : '.' D_ORG defexpr{ lc = $3.val.v; if( pass2 ) emitaddr(lc); bytecount = 0; $$.value = 0;} | '.' D_BYTE blist { $$.value = $3.value; } | '.' D_WORD wlist { $$.value = $3.value; } | '.' D_SKIP defexpr { $$.value = $3.val.v; if( pass2 ) emitaddr(lc+$$.value); } | '.' D_EQU undefsym ',' expr{ if( $5.val.d == 0 ) warn("Expression is undefined in pass 1"); $3.sym->type = LABEL; $3.sym->value = $5.val.v; $$.value = 0;} | '.' D_FLAG SYMBOL ',' flag{ $3.sym->type = LABEL; $3.sym->value = $5.value; $$.value = 0;} | '.' D_END { $$.value = 0; } ;defexpr : expr{ if( $1.val.d == 0 ) warn("Expression is undefined in pass 1"); if( !(isbit16($1.val.v)) ) warn("Value greater than 16-bits"); $$.value = $1.val.v;} ;flag : flagv BITPOS{ if( !isbit8($1.value) ) warn("Bit address exceeds 8-bits"); if( isbmram($1.value) ) $$.value = ($1.value-0x20)*8+ $2.value; else if( isbmsfr($1.value) ) $$.value = $1.value + $2.value; else warn("Invalid bit addressable RAM location");} ;flagv : SYMBOL{ if( $1.sym->type == UNDEF ) warn("Symbol %s must be defined in pass 1",$1.sym->name); $$.value = $1.sym->value;} | VALUE { $$.value = $1.value; } ;undefsym : SYMBOL{ if( $1.sym->type != UNDEF && pass1) warn("Attempt to redefine symbol: %s",$1.sym->name); $$.sym = $1.sym;} ;blist : blist ',' data8{ if( pass2 ) genbyte($3.value); $$.value = $1.value + 1;} | blist ',' STRING{ if( pass1 ) $$.value = $1.value + $3.value; else { $$.value = $1.value + strlen($3.str); genstr($3.str); free($3.str); }} | data8{ if( pass2 ) genbyte($1.value); $$.value = 1;} | STRING{ if( pass1 ) $$.value = $1.value; else { $$.value = strlen($1.str); genstr($1.str); free($1.str); }} ;wlist : wlist ',' data16{ if( pass2 ) genword($3.value); $$.value = $1.value + 2;} | data16{ if( pass2 ) genword($1.value); $$.value = 2;} ;/* -------------------- * EXPRESSIONS: * */expr : '*' { $$.val.v = lc; $$.val.d = 1; } | '(' expr ')' { $$.val.v = $2.val.v; $$.val.d = $2.val.d; } | '-' expr %prec '*' { $$.val.v = -$2.val.v; $$.val.d = $2.val.d; } | expr '|' expr { $$.val.v = $1.val.v | $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '&' expr { $$.val.v = $1.val.v & $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '*' expr { $$.val.v = $1.val.v * $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '/' expr { $$.val.v = $1.val.v / $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '%' expr { $$.val.v = $1.val.v % $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '-' expr { $$.val.v = $1.val.v - $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '+' expr { $$.val.v = $1.val.v + $3.val.v; $$.val.d = $1.val.d && $3.val.d; } | expr '>' '>' expr { $$.val.v = $1.val.v >> $4.val.v; $$.val.d = $1.val.d && $4.val.d; } | expr '<' '<' expr { $$.val.v = $1.val.v << $4.val.v; $$.val.d = $1.val.d && $4.val.d; } | SYMBOL{ if( pass1 ) { $$.val.v = $1.sym->value; $$.val.d = ($1.sym->type != UNDEF); } else { if( $1.sym->type == UNDEF ) warn("Undefined symbol %s",$1.sym->name); $$.val.v = $1.sym->value; $$.val.d = 1; }} | VALUE { $$.val.v = $1.val.v; $$.val.d=1; } ;/* -------------------- * INSTRUCTIONS: * */instr : NOP { $$.value = makeop($1.op,NULL,0); } | ACALL addr11 { $$.value = makeop($1.op,&$2.mode,0); } | AJMP addr11 { $$.value = makeop($1.op,&$2.mode,0); } | ADD two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | ADDC two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | SUBB two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | XRL two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | XRL two_op2 { $$.value = makeop($1.op,&$2.mode,4); } | ANL two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | ANL two_op2 { $$.value = makeop($1.op,&$2.mode,4); } | ANL two_op3 { $$.value = makeop($1.op,&$2.mode,6); } | ORL two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | ORL two_op2 { $$.value = makeop($1.op,&$2.mode,4); } | ORL two_op3 { $$.value = makeop($1.op,&$2.mode,6); } | XCH two_op1 { if( get_md($2.mode) == 3 ) warn("Immediate mode is illegal"); $$.value = makeop($1.op,&$2.mode,0); } | INC single_op1 { $$.value = makeop($1.op,&$2.mode,0); } | INC DPTR { $$.value = makeop($1.op,NULL,4); } | DEC single_op1 { $$.value = makeop($1.op,&$2.mode,0); } | DA A { $$.value = makeop($1.op,NULL,0); } | DIV AB { $$.value = makeop($1.op,NULL,0); } | JMP '@' A '+' DPTR { $$.value = makeop($1.op,NULL,0); } | JMP '@' DPTR '+' A { $$.value = makeop($1.op,NULL,0); } | MUL AB { $$.value = makeop($1.op,NULL,0); } | RET { $$.value = makeop($1.op,NULL,0); } | RETI { $$.value = makeop($1.op,NULL,0); } | RL A { $$.value = makeop($1.op,NULL,0); } | RLC A { $$.value = makeop($1.op,NULL,0); } | RR A { $$.value = makeop($1.op,NULL,0); } | RRC A { $$.value = makeop($1.op,NULL,0); } | SWAP A { $$.value = makeop($1.op,NULL,0); } | XCHD two_op1 { if( get_md($2.mode) != 2 ) warn("Invalid addressing mode"); $$.value = makeop($1.op,&$2.mode,-2); } | CLR single_op2 { $$.value = makeop($1.op,&$2.mode,0); } | CPL single_op2 { $$.value = makeop($1.op,&$2.mode,0); } | SETB single_op2 { if( get_md($2.mode) == 0 ) warn("Invalid addressing mode"); $$.value = makeop($1.op,&$2.mode,-1); } | PUSH data8 { struct mode tmp; set_md(tmp,0); set_ov(tmp,0); set_sz(tmp,1); set_b1(tmp,$2.value); $$.value = makeop($1.op,&tmp,0); } | POP data8 { struct mode tmp; set_md(tmp,0); set_ov(tmp,0); set_sz(tmp,1); set_b1(tmp,$2.value); $$.value = makeop($1.op,&tmp,0); } | LJMP addr16 { $$.value = makeop($1.op,&$2.mode,0); } | LCALL addr16 { $$.value = makeop($1.op,&$2.mode,0); } | JC relative { $$.value = makeop($1.op,&$2.mode,0); } | JNC relative { $$.value = makeop($1.op,&$2.mode,0); } | JNZ relative { $$.value = makeop($1.op,&$2.mode,0); } | JZ relative { $$.value = makeop($1.op,&$2.mode,0); } | SJMP relative { $$.value = makeop($1.op,&$2.mode,0); } | CJNE three_op1 { $$.value = makeop($1.op,&$2.mode,0); } | JB two_op4 { $$.value = makeop($1.op,&$2.mode,0); } | JNB two_op4 { $$.value = makeop($1.op,&$2.mode,0); } | JBC two_op4 { $$.value = makeop($1.op,&$2.mode,0); } | DJNZ two_op5 { $$.value = makeop($1.op,&$2.mode,0); } | MOV two_op1 { $$.value = makeop($1.op,&$2.mode,0); } | MOV two_op2 { $$.value = makeop($1.op,&$2.mode,4); } | MOV two_op6 { $$.value = makeop($1.op,&$2.mode,6); } | MOVC A ',' '@' A '+' DPTR { $$.value = makeop($1.op,NULL,0); } | MOVC A ',' '@' DPTR '+' A { $$.value = makeop($1.op,NULL,0); } | MOVC A ',' '@' A '+' PC { $$.value = makeop($1.op,NULL,1); } | MOVC A ',' '@' PC '+' A { $$.value = makeop($1.op,NULL,1); } | MOVX A ',' '@' regi { $$.value = makeop($1.op,NULL,$5.value); } | MOVX A ',' '@' DPTR { $$.value = makeop($1.op,NULL,2); } | MOVX '@' regi ',' A { $$.value = makeop($1.op,NULL,$3.value+3); } | MOVX '@' DPTR ',' A { $$.value = makeop($1.op,NULL,5); } ;/* -------------------- * ADDRESSING MODES: * */two_op1 : A ',' reg { set_md($$.mode,0); set_ov($$.mode, $3.value); set_sz($$.mode, 0); } | A ',' data8 { set_md($$.mode,1); set_ov($$.mode,0); set_sz($$.mode,1); set_b1($$.mode,$3.value); } | A ',' '@' regi { set_md($$.mode,2); set_ov($$.mode,$4.value); set_sz($$.mode,0); } | A ',' '#' data8 { set_md($$.mode,3); set_ov($$.mode,0); set_sz($$.mode,1); set_b1($$.mode,$4.value); } ;two_op2 : data8 ',' A { set_md($$.mode,0); set_ov($$.mode,0); set_sz($$.mode,1); set_b1($$.mode,$1.value); } | data8 ',' '#' data8 { set_md($$.mode,1); set_ov($$.mode,0); set_sz($$.mode,2); set_b1($$.mode,$1.value); set_b2($$.mode,$4.value); } ;two_op3 : C ',' bit {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -