💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] > # 说明 自己写的`mcu`使用的指令是自己独有的,之前都是尽量让指令和别人设计的保持一致,这样可以使用别人的汇编器将汇编语言翻译为机器码,但是当为了实现一些比较特有或者是更适合自己项目的指令操作时,使用别人的无法翻译得到支持自己`mcu`的机器指令,所以写一个比较简单的翻译工具十分有必要! > # 词法分析器实验 写这种工具没有必要自己来从零来写,我们可以考虑使用词法分析器,在这里我从现在开始学习词法分析器,并对关键点做笔记。 ## 快速了解流程的一个例子 * 实验平台 : linux操作系统 * 工具 : flex **流程** **step1:新建 lexical.l 词法文件** 文件内容如下: ``` %{ #include<stdio.h> #define LT 1 #define LE 2 #define GT 3 #define GE 4 #define EQ 5 #define ADD 6 #define DEC 7 #define MUL 8 #define DIV 9 #define SEM 10 #define LB 11 #define RB 12 #define BLB 13 #define BRB 14 #define WHILE 18 #define DO 19 #define IF 20 #define THEN 21 #define ELSE 22 #define FOR 23 #define ID 24 #define NUMBER 25 #define REAL8 26 #define REAL10 27 #define REAL16 28 #define INT8 29 #define INT10 30 #define INT16 31 #define NEWLINE 40 #define ERRORCHAR 41 int yylval; %} delim [ \t\n] whitespace {delim}+ digit [0-9] letter [A-Za-z_] id {letter}({letter}|{digit})* number {digit}+(\.{digit}+)?([eE][+-]?{digit}+)? int8 (0([0-7])+) int10 ([1-9]|[1-9]([0-9])+|0) int16 (0[xX]([A-Fa-f0-9])+) real8 (0([0-7])+\.([0-7])*) real10 (([1-9]|[1-9]([0-9])+)\.[0-9]+|0\.([0-9])+) real16 0[xX]([A-Fa-f0-9])+\.([A-Fa-f0-9])* %% {whitespace} {;} (while|WHILE) {return (WHILE);} (do|DO) {return (DO);} (if|IF) {return (IF);} (then|THEN) {return (THEN);} (else|ELSE) {return (ELSE);} (for|FOR) {return (FOR);} {id} {return (ID);} {int8} {return (INT8);} {int10} {return (INT10);} {int16} {return (INT16);} {real8} {return (REAL8);} {real10} {return (REAL10);} {real16} {return (REAL16);} "<" {return (LT);} "<=" {return (LE);} ">" {return (GT);} ">=" {return (GE);} "=" {return (EQ);} "+" {return (ADD);} "-" {return (DEC);} "*" {return (MUL);} "/" {return (DIV);} ";" {return (SEM);} "(" {return (LB);} ")" {return (RB);} "{" {return (BLB);} "}" {return (BRB);} . {return (ERRORCHAR);} %% int yywrap(){ return 1; } void writeout(int c){ switch(c){ case ERRORCHAR:fprintf(yyout,"(ERRORCHAR,\"%s\")",yytext); break; case INT10:fprintf(yyout,"(INT10,\"%s\")",yytext); break; case INT16:fprintf(yyout,"(INT16,\"%s\")",yytext); break; case INT8:fprintf(yyout,"(INT8,\"%s\")",yytext); break; case WHILE:fprintf(yyout,"(WHILE,\"%s\")",yytext); break; case DO:fprintf(yyout,"(DO,\"%s\")",yytext); break; case IF:fprintf(yyout,"(IF,\"%s\")",yytext); break; case THEN:fprintf(yyout,"(THEN,\"%s\")",yytext); break; case ELSE:fprintf(yyout,"(ELSE,\"%s\")",yytext); break; case FOR:fprintf(yyout,"(FOR,\"%s\")",yytext); break; case ID:fprintf(yyout,"(ID,\"%s\")",yytext); break; //case NUMBER:fprintf(yyout,"(NUMBER,\"%s\")",yytext); // break; case RB:fprintf(yyout,"(RB,\"%s\")",yytext); break; case LB:fprintf(yyout,"(LB,\"%s\")",yytext); break; case SEM:fprintf(yyout,"(SEM,\"%s\")",yytext); break; case DIV:fprintf(yyout,"(DIV,\"%s\")",yytext); break; case MUL:fprintf(yyout,"(MUL,\"%s\")",yytext); break; case DEC:fprintf(yyout,"(DEC,\"%s\")",yytext); break; case ADD:fprintf(yyout,"(ADD,\"%s\")",yytext); break; case EQ:fprintf(yyout,"(EQ,\"%s\")",yytext); break; case GE:fprintf(yyout,"(GE,\"%s\")",yytext); break; case GT:fprintf(yyout,"(GT,\"%s\")",yytext); break; case LE:fprintf(yyout,"(LE,\"%s\")",yytext); break; case LT:fprintf(yyout,"(LT,\"%s\")",yytext); break; case BLB:fprintf(yyout,"(BLB,\"%s\")",yytext); break; case BRB:fprintf(yyout,"(BRB,\"%s\")",yytext); break; case NEWLINE:fprintf(yyout,"\n"); break; case REAL8:fprintf(yyout,"(REAL8,\"%s\")",yytext); break; case REAL10:fprintf(yyout,"(REAL10,\"%s\")",yytext); break; case REAL16:fprintf(yyout,"(REAL16,\"%s\")",yytext); break; default:break; } return; } int main(int argc,char ** argv){ int c,j=0; if(argc>=2){ if((yyin=fopen(argv[1],"r"))==NULL){ printf("Can't open file %s\n",argv[1]); return 1; } if(argc>=3){ yyout=fopen(argv[2],"w"); } } while(c=yylex()){ writeout(c); j++; if(j%5==0) writeout(NEWLINE); } if(argc>=2){ fclose(yyin); if(argc>=3) fclose(yyout); } return 0; } ``` **step2:使用命令`flex lexical.l`编译文件生成`lex.yy.c文件`** **step3:使用gcc编译`lex.yy.c`,命令如下** ```bash gcc -o lexical lex.yy.c -lfl ``` **step4:新建测试文件test.txt ** ```txt 0 92+data> 0x3f 00 while a+acc>xx do x=x-1; a=6.2+a*0X88.80; if a>b then a=b else a=b-1+c; ``` **step5:使用 lexical编译 test.txt** ``` ./lexical test.txt ```