首页 > 编程知识 正文

bison语法分析器,java词法分析器

时间:2023-05-04 23:12:51 阅读:156349 作者:3460

LEX/FLEX词法分析器

CONTENTS :

[TOC]

本文的内容如下。

lex语法格式

在linux上安装和使用flex

flex实例

编译和使用flex源代码

Lex/Flex词法分析器

Lex是LEXical compiler的缩写,在Unix环境中是非常有名的工具,主要功能是生成词法分析器scanner的c源代码,描述规则采用正则表达式regular expression。 记述字句解析器的文件*.l在lex编译后,生成lex.yy.c的文件,c编译器编译后生成字句解析器。 词法分析器简单地说,其任务是将输入的各种符号转换成相应的标识符(token ),从而所转换的标识符容易在后级处理。 —— [百度百科]

安装和使用Flex

在使用apt包管理器的linux系统上,可以轻松安装和使用flex。 在终端上输入以下代码以安装flex。

$ sudo apt-get install flex

flex代码的源文件通常是扩展名. l。

. l文件使用以下命令进行编译: 如果文件名为scanner.l :

$ flex scanner.l

编译后,将在源代码所在的目录中生成lex.yy.c。 这就是能够执行上述scanner.l功能的c语言代码。 gcc编译允许生成词法分析程序

void yywrap () { return 1; }

$ gcc lex.yy.c -o scanner

然后,将需要分析的文件(以input.txt为例)作为参数传递给scanner以执行分析。

$ ./scanner input.txt

Lex语法格式

flex的语法分为三个部分:

{definitions}

%%

{rules}

%%

{user subroutines}

定义:

LABEL REGULAR_EXPRESSION

LABEL是此处类字符串的名称,REGULAR_EXPRESSION是与此字符串匹配的正则表达式。 正则表达式的语法主要如下。

符号

意思是

或者

[]

括号内的文字取其一

-

a-z表示ascii代码在a-z中包含a.z字符

转义(flex无法识别非字母字符) )。

*

0或多个字符

0或1个字符

一个或多个字符

^

其他剩下的文字

同调

n除此之外的所有字符都等效于^n

示例:

1. INT [1-9][0-9]*|[0] /*整数类型,由0-9组成的字符串*/

2. FLOAT [0-9]*[.][0-9] ([eE][ -]? [0-9]*|[0]? f? /*浮点数格式*

3.LP((/*圆括号) /

注意:用%{ %}括起来的语句会完全写入编译的c语言文件中。

例如

` %{

#包含

int num_id=0;

() '

rules:

规则的部分语法如下。

{标签1 } |

{LABLE2} |

.

{

/*TODO*/

}

TODO部分是告诉编译器在匹配字符串后程序需要做什么。

例如匹配整数后,打印这个整数。

{INT} {

printf(pickupaninteger,value is %d ),atoi ) yytext );

printf(pickupaninteger,value is %s ),yytext );

}

其中atoi ()函数将字符串转换为整数。

用户子

这里主要放置用户需要执行的c语言代码。 他们会直接添加到lex.yy.c文件的末尾。

此处常用于存储main函数,后面将详细介绍。

FLEX实例

下面的示例具体说明如何使用flex。 主要功能是扫描并匹配文件中的字符串,然后回显其类型和内容。 代码如下所示。

/* * * * * * * * * * * * * * * * * * * *

* scanner.l

* @author mist

* 2015-9-21 23:08

*****

***********/

%{

#include "stdio.h"

#include "stdlib.h"

%}

INT_DEX [1-9][0-9]*|[0]

INT_HEX [0][Xx]([1-9][0-9]*|[0])

INT_OCT [0][0-7]

FLOAT [0-9]*[.][0-9]+([eE][+-]?[0-9]*|[0])?f?

SEMI [;]

COMMA [,]

ASSIGNOP [=]

RELOP [>]|[][=]|[

PLUS [+]

MINUS [-]

STAR [*]

DIV [/]

AND [&][&]

OR [|][|]

DOT [.]

NOT [!]

TYPE int|float

LP (

RP )

LB [

RB ]

LC {

RC }

STRUCT struct

RETURN return

IF if

ELSE else

WHILE while

SPACE [ nt]

ID [a-zA-Z_][a-zA-Z_0-9]*

/*end of definition*/

%%

{SEMI} {

printf("get semmi : %sn", yytext);

}

{COMMA} {

printf("get comma : %sn", yytext);

}

{ASSIGNOP} {

printf("get assignop : %sn", yytext);

}

{INT_DEX} |

{INT_HEX} |

{INT_OCT} {

printf("get an integer: %sn", yytext);

}

{FLOAT} {

printf("get a float: %sn", yytext);

}

{PLUS} |

{MINUS} |

{DIV} |

{STAR} {

printf("get an operator: %sn", yytext);

}

{RELOP} {

printf("get a relop: %sn", yytext);

}

{AND} |

{OR} |

{NOT} {

printf("get a logic operator: %sn", yytext);

}

{DOT} {

printf("get a dot: %sn", yytext);

}

{STRUCT} |

{RETURN} |

{IF} |

{ELSE} |

{WHILE} {

printf("get keyword: %sn", yytext);

}

{TYPE} {

printf("get type: %sn", yytext);

}

{LP} |

{RP} |

{LB} |

{RB} |

{LC} |

{RC} {

printf("get brackets : %sn", yytext);

}

{SPACE} |

. {

/*ABANDON THESE CHARACTORS*/

}

{ID} {

printf("get an ID: %sn", yytext);

}

%%

int yywrap() {

return 1;

}

int main(int argc, char** argv) {

if (argc > 1) {

if (!(yyin = fopen(argv[1], "r"))) {

perror(argv[1]);

return 1;

}

}

while (yylex());

return 0;

我们需要为生成的分析程序编写main函数。首先需要通过yyin来获取指向被分析文件的文件FILE指针,一般文件的路径通过控制台的第二个参数获得。分析部分的实体在函数yylex()中。

yywrap()用于判断是否已经扫描完了所有的文件。如果它在最后一个文件的末尾被调用,则返回值为1。此时程序将停止分析,可以用来扫描多个文件。

输入文本:

`int float {}()[] 0

0x0 0x123

123.5

.3e-10f

= >= || && ! ; ,

this_is_an_id

id123

if then else

`

输出:

get type: int

get type: float

get brackets : {

get brackets : }

get brackets : (

get brackets : )

get brackets : [

get brackets : ]

get an integer: 0

get an integer: 0x0

get an integer: 0x123

get a float: 123.5

get a float: .3e-10f

get assignop : =

get a relop: >=

get a logic operator: ||

get a logic operator: &&

get a logic operator: !

get semmi : ;

get comma : ,

get an ID: this_is_an_id

get an ID: id123

get keyword: if

get an ID: then

get keyword: else

另外附上词法要求:

INT  /A sequence of digits without spaces1/

FLOAT  /* A real number consisting of digits and one decimal point. The deci-

mal point must be surrounded by at least one digit2 */

ID  /* A character string consisting of 52 upper- or lower-case alphabetic, 10

numeric and one underscore characters. Besides, an identifier must not start

with a digit3 */

SEMI  ;

COMMA  ,

ASSIGNOP  =

RELOP  > | < | >= | <= | == | !=

PLUS  +

MINUS  -

STAR  *

DIV  /

AND  &&

OR  ||

DOT  .

NOT  !

TYPE  int | float

LP  (

RP  )

LB  [

RB  ]

LC  {

RC  }

STRUCT  struct

RETURN  return

IF  if

ELSE  else

WHILE  while

1) 词法单元INT表示的是所有(无符号)整型常数。一个十进制整数由0~9十个数字组

成,数字与数字中间没有如空格之类的分隔符。除“0”之外,十进制整数的首位数字

不为0。例如,下面几个串都表示十进制整数:0、234、10000。为方便起见,你可以

假设(或者只接受)输入的整数都在32bits位之内。

2) 整型常数还可以以八进制或十六进制的形式出现。八进制整数由0~7八个数字组成并以

数字0开头,十六进制整数由0~9、A~F(或a~f)十六个数字组成并以0x或者0X开头。

例如,0237(表示十进制的159)、0xFF32(表示十进制的65330)。

3) 词法单元FLOAT表示的是所有(无符号)浮点型常数。一个浮点数由一串数字与一个

小数点组成,小数点的前后必须有数字出现。例如,下面几个串都是浮点数:0.7、

12.43、9.00。为方便起见,你可以假设(或者只接受)输入的浮点数都符合IEEE754单

精度标准(即都可以转换成C语言中的float类型)。

4) 浮点型常数还可以以指数形式(即科学记数法)表示。指数形式的浮点数必须包括基

数、指数符号和指数三个部分,且三部分依次出现。基数部分由一串数字(0~9)和一

个小数点组成,小数点可以出现在数字串的任何位置;指数符号为“E”或“e”;指

数部分由可带“+”或“”(也可不带)的一串数字(0~9)组成,“+”或“”(如

果有)必须出现在数字串之前。例如01.23E12(表示1.23  1012)、43.e-4(表示43.0 

10-4)、.5E03(表示0.5  103)。

5) 词法单元ID表示的是除去保留字以外的所有标识符。标识符可以由大小写字母、数字

以及下划线组成,但必须以字母或者下划线开头。为方便起见,你可以假设(或者只

接受)标识符的长度小于32个字符。

6) 除了INT、FLOAT和ID这三个词法单元以外,其它产生式中箭头右边都表示具体的字

符串。例如,产生式TYPE  int | float表示:输入文件中的字符串“int”和“float”都

将被识别为词法单元TYPE。

2.2

High-level Definitions

生成词法分析程序 可能会发生yywrap未定义的错误。yywrap必须由用户亲自编写,一般按如下形式即可: ↩

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。