分享
 
 
 

编译器(解释器)编写指南-编写编译器(解释器)的工具-LEX

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

作者:Riceball(riceballl@hotmail.com)

关键字: 编译器, 解释器, LEX, YACC, 编译原理, 正则表达式, Pascal

预备知识:编译原理,正则表达式,Pascal

本文并不希望深入透彻的讲解编译原理,而是讲解如何利用工具(生成编译器的编译器)去编写编译器。如果你完全不知道编译什么东西,那么请看懂了编译原理,在看此文,本文不是为初学者准备的。

一、什么是编译器(解释器)

编译器是将一种计算机语言翻译为另一种计算机语言的程序。编译器将源程序(source language)

编写的程序作为输入,翻译产生用目标语言(target language)编写的等价程序。源程序一般为高级语言(high-level language),如Pascal 或Delphi,而目标语言则是汇编语言或目标机器的目标代码(object code),有时也称作机器代码(machine code)

源程序→ 编译器→ 目标程序

解释器也是同编译器一样的一种语言翻译程序。它与编译器的不同之处在于:它立即执行源程序而不是生成目标代码。从原理上讲,任何程序设计语言都可以被解释或被编译。

(1) 扫描程序(scanner)

由扫描程序(Scanner)阅读源程序(通常以字符流的形式表示),进行词法分析(Lexical analysis),它将源程序翻译成单词ID(Token),放入单词ID(Token)表中。在此过程中,扫描程序会进行简单的拼写检查。

单词ID(Token):

一个Token可以有若干种类型,典型的有:关键字(keyword),例如 if 和 while;标识符(identifier)是由用户定义的变量名,过程名等,它们通常由字母和数字组成并由一个字母开头;特殊符号(special symbol)如算术符号+和*、一些多字符符号,如 >= 和<>。TokenType 为枚举数据类型。实际上就是整数值,每一个数值代表一种单词ID类型。

TTokenType = (ttNone, ttStrVal, ttIntVal, ttFloatVal,

//ttNAME 就是标识符 Identifier 或关键字

ttNAME,

ttSWITCH,

ttVAR, ttCONST, ttTYPE, ttRECORD, ttARRAY, ttDOT, ttDOTDOT, ttOF,

ttTRY, ttEXCEPT, ttRAISE, ttFINALLY, ttON, ttREAD, ttWRITE, ttPROPERTY,

ttPROCEDURE, ttFUNCTION, ttCONSTRUCTOR, ttDESTRUCTOR, ttCLASS, ttNIL, ttIS,

ttAS,

ttVIRTUAL, ttOVERRIDE, ttREINTRODUCE, ttINHERITED, ttABSTRACT,

ttEXTERNAL, ttFORWARD, ttIN,

ttBEGIN, ttEND, ttBREAK, ttCONTINUE, ttEXIT,

ttIF, ttTHEN, ttELSE, ttWHILE, ttREPEAT, ttUNTIL, ttFOR, ttTO, ttDOWNTO, ttDO,

ttCASE,

ttTRUE, ttFALSE, ttAND, ttOR, ttXOR, ttDIV, ttMOD, ttNOT, ttPLUS, ttMINUS,

ttTIMES, ttDIVIDE,

ttEQ, ttNOTEQ, ttGTR, ttGTREQ, ttLESS, ttLESSEQ, ttSEMI, ttCOMMA, ttCOLON,

ttASSIGN,

ttBLEFT, ttBRIGHT, ttALEFT, ttARIGHT, ttCRIGHT,

ttDEFAULT,

// Tokens for compatibility to Delphi

ttPRIVATE, ttPROTECTED, ttPUBLIC, ttPUBLISHED,

ttREGISTER, ttPASCAL, ttCDECL, ttSTDCALL, ttFASTCALL);

TTokenTypes = set of TTokenType;

为了表示 Token 的内容,一般我们这样定义Token:

TToken = Record

TokenType: TTokenType;

TokenValue: Variant;

end;

TP LEX

TP Lex 是词法分析(Lexical analysis)扫描器源程序的生成器,它用于创建Pascal(TurboPascal, Delohi)扫描器子过程。

TP Lex 分析 LEX 文件(默认扩展名为.L),产生词法分析(Lexical analysis)扫描器过程,输出pascal源程序文件。如果 LEX 文件在分析过程发现错误,错误信息将会被写入相应的列表文件(扩展名为.lst)。

创建的 pascal 源文件程序将包含词法分析(Lexical analysis)扫描器过程:yylex。

function yylex : Integer;

你应该在你的主程序中调用该过程进行词法分析。每调用一次,yylex 的返回值为当前分析的Token类型值。当文件结束时,yylex 的返回值为0。

yylex 过程的代码模板在 yylex.cod 文件中。TP Lex 需要该文件构建生成 pascal 源程序文件。该文件必须在当前目录或TP LEX所在目录下。另外生成好的源程序需要 LexLib.pas 文件进行编译。

用法:

lex [options] lex-file[.l] [output-file[.pas]]

Options(参数)

-------

-v "详尽(Verbose):" 在该参数下,Lex 在生成词法分析器的同时,将生成一个可读的说明文件,扩展名`.lst'.

-o "优化(Optimize):" Lex 将优化 DFA 表,产生一个最小的 DFA.

如何编写 LEX 文件(.L)

LEX 文件(.L)分为三个部分,每个部分之间用“%%”隔开:

定义部分(definitions)

%%

规则部分(rules)

%%

辅助过程部分(auxiliary procedures)

三个部分可以都是空的也没有关系,以行为单位作为语句的分隔符。

定义部分(definitions)

定义部分出现在第1个双百分号之前。定义部分(definitions)可以包含以下的元素:

- 正则表达式一般定义格式:

定义的表达式名称(name) 替换的结果(substitution)

正则表达式的名字也得在该部分定义。这个名字的定义写在另一行的第1列,且其后(后面有一个或多个空格)是它所表示的正则表达式。定义的名称(name)必须是一个合法的标识符(第一位必须是字母,第二位可以是字母或数字)

替换的结果(substitution)是一个LEX正则表达式,你也可以在正则表达式中引用前面定义好的表达式名称,只要将该名称用花括号("{}")扩起即可。例如,带符号数字的定义:

Number [0-9]+

signedNumber ("+"|"-")? {Number}

- 开始(start)状态按照如下的格式书写:

%start name ...

这用来指定规则的启动条件(详见规则部分)。%start 关键字可以被简写为 %s 或 %S.

- “%{”与“%}”对

插入在 “%{”与“%}”对中间的是函数外部的任意Pascal源代码(请注意这些字符的顺序)。

规则部分(rules)

它们由一连串带有Pascal代码的正则表达式组成;当匹配相对应的正则表达式时,后面的Pascal代码(动作)就会被执行。规则的格式如下:

正则表达式(expression) 语句(statement);

注意:语句(statement)必须是单独的一个Pascal语句,最后以分号结尾(如果有多个语句使用Begin...End)。语句(statement)可以分成多行书写,不过后续行必须首先至少留一个空格或tab,用来指示该行是属于上一行的。使用“|”表示该表达式执行的动作和下一个表达式执行的动作(语句)一样。例如,Pascal的注释:

"(*" |

"{" begin

repeat

c := get_char;

case c of

'}' : ;

'*' : begin

c := get_char;

if c=')' then exit else unget_char(c)

end;

#0 : begin

commenteof;

exit;

end;

end;

until false

end;

TP Lex 库单元提供了一系列有用的变量和过程,你可以在你编写的动作(语句)中使用。如:yytext 变量返回匹配的字符串。yyleng 变量返回匹配的字符串长度。

在规则部分中的“%{”与“%}”对,中间插入的Pascal源代码,被当作是动作的局部变量(过程)出现。

辅助过程部分(auxiliary procedures)

辅助过程部分可以包含Pascal源程序,如辅助过程或主程序,该部分会被简单的放在文件的末尾。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有