Having recently been interested in an interpretive program (like python or BC calculator in Linux), start learning how to compile. Today, I realized the lexical scanning procedure of tiny language. Most of them refer to the book compiling principles and practices. But I made some minor improvements.
First talk about Tiny language:
1. Note: Put in a pair of curly braces. The notes in the book cannot be nested, and I have made a little improvement to allow nesting.
2. Keyword: Read write if end repeat until else
3. Type: Only integer and Boolean are supported.
4, Calculation: +-*/() < =: =, where: = is the assignment operation, = is judged. No, and <= >=.
An example of the tiny language program:
Test.tine: (Selected from "Compiling Principles and practices")
{Sample program in TINY language- computes factorial}read x; {input An integer}if 0 < x then {don ' t compute if x <= 0}fact: = 1;repeatfact: = Fact * X;x: = X-1;until x = 0 ; write fact {output factorial of x}end
In globals.h, some types of declarations are involved:
#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 s Ize of identifier of reserved word */#define Maxtokenlen 50#ENDIF
The flex input used to generate the lexical scan, which is the core part of the program:
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\nwhitespace[\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);p rintf ("%d:", Lineno);p Rinttoken (Currenttoken, tokenstring); return currenttoken;}
The Printtoken function is implemented in 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: %s\n ", tokenstring); Break;case id:printf (" \tidentifier:%s\n ", tokenstring); Break;case num:printf (" \tnumber:%s\n ", tokenstring) break;case assign:case eq:case lt:case plus:case minus:case times:case OVER:case LPAREN:case RPAREN:case semi:printf ("\toperator:%s\n", tokenstring);}}
That's all the papers! Finally, it is the makefile file:
SCANNER.EXE:MAIN.O lex.yy.o util.ogcc main.o lex.yy.o util.o-o scanner.exe-lflmain.o:main.c globals.h util.hgcc main.c -CUTIL.O:UTIL.C util.h globals.hgcc Util.c-clex.yy.o:tiny.lflex tiny.lgcc lex.yy.c-c
As a result, a simple lexical scanning program is completed.
Because the default input is used, the program directly supports input from the keyboard, and the effect is as follows:
Of course, you can also use the redirect operation, with the following effect:
Compiling principle learning: Tiny language lexical scanning program implementation