编译原理学习:TINY语言词法扫描程序实现
发布时间:2020-12-15 03:37:00 所属栏目:百科 来源:网络整理
导读:最近对解释型程序(类似python或者是linux里的bc计算器)非常感兴趣,就开始学习一下编译原理。今天自己实现了TINY语言的词法扫描程序。大部分参考《编译原理及实践》一书。但是我做了一些小小的改进。 先说一下TINY语言: 1、注释:放在一对大括号内。书上
最近对解释型程序(类似python或者是linux里的bc计算器)非常感兴趣,就开始学习一下编译原理。今天自己实现了TINY语言的词法扫描程序。大部分参考《编译原理及实践》一书。但是我做了一些小小的改进。 先说一下TINY语言: 1、注释:放在一对大括号内。书上的注释不能嵌套,我做了一点改进,允许嵌套。 2、关键字:read write if end repeat until else 3、类型:只支持整型和布尔型。 4、计算:+ - * / ( ) < = :=,其中:=为赋值运算,=为判断。没有〈和<= >= 一个示例的TINY语言程序: test.tine: (选自《编译原理及实践》) { Sample program in TINY language - computes factorial } read x; { input an integer } if 0 < x then { don't compute if x <= 0 } fact := 1; repeat fact := fact * x; x := x - 1; until x = 0; write fact { output factorial of x } end 在globals.h中,涉及到一些类型的声明: #ifndef GLOBALS_H #define GLOBALS_H #include <stdio.h> typedef enum { ENDFILE,ERROR,IF,THEN,ELSE,END,REPEAT,UNTIL,READ,WRITE,ID,NUM,ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI } TokenType; extern lineno; /* The max size of identifier of reserved word */ #define MAXTOKENLEN 50 #endif 用于生成词法扫描的flex输入,这是程序的核心部分: tiny.l %{ #include <stdio.h> #include <string.h> #include "globals.h" #include "util.h" char tokenString[MAXTOKENLEN + 1]; %} digit [0-9] number {digit}+ letter [a-zA-Z] identifier {letter}[a-zA-Z0-9]* newline n whitespace [ t] %% "if" {return IF;} "then" {return THEN;} "else" {return ELSE;} "end" {return END;} "repeat" {return REPEAT;} "until" {return UNTIL;} "read" {return READ;} "write" {return WRITE;} ":=" {return ASSIGN;} "=" {return EQ;} "<" {return LT;} "+" {return PLUS;} "-" {return MINUS;} "*" {return TIMES;} "/" {return OVER;} "(" {return LPAREN;} ")" {return RPAREN;} ";" {return SEMI;} {number} {return NUM;} {identifier} <span style="white-space:pre"> </span>{return ID;} {newline} {lineno++;} {whitespace} <span style="white-space:pre"> </span>{ /* Do nothing */ } "{" { char c; int count = 1; do { c = input(); if (c == EOF) break; else if (c == 'n') lineno++; else if (c == '{') count++; else if (c == '}') count--; } while (count != 0); } . {return ERROR;} %% TokenType getToken(void) { TokenType currentToken; currentToken = yylex(); strncpy(tokenString,yytext,MAXTOKENLEN); printf("%d: ",lineno); printToken(currentToken,tokenString); return currentToken; } printToken函数在util.c中实现: util.h: #ifndef UTIL_H #define UTIL_H #include "globals.h" void printToken(TokenType token,char* tokenString); TokenType getToken(void); #endif util.c: #include "util.h" #include <stdio.h> #include "globals.h" void printToken(TokenType token,char* tokenString) { switch(token) { case IF: case THEN: case ELSE: case END: case REPEAT: case UNTIL: case READ: case WRITE: printf("treversed word: %sn",tokenString); break; case ID: printf("tidentifier: %sn",tokenString); break; case NUM: printf("tnumber: %sn",tokenString); break; case ASSIGN: case EQ: case LT: case PLUS: case MINUS: case TIMES: case OVER: case LPAREN: case RPAREN: case SEMI: printf("toperator: %sn",tokenString); } } 这就是所有的文件了!最后,是makefile文件: scanner.exe: main.o lex.yy.o util.o gcc main.o lex.yy.o util.o -o scanner.exe -lfl main.o: main.c globals.h util.h gcc main.c -c util.o: util.c util.h globals.h gcc util.c -c lex.yy.o: tiny.l flex tiny.l gcc lex.yy.c -c 于是,一个简单的词法扫描程序就完成了。 由于使用的是默认的输入,所以这个程序直接支持从键盘输入,运行效果如下: 当然,也可以使用重定向操作,使用效果如下: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |