首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于lex的词法分析

基于lex的词法分析
EN

Stack Overflow用户
提问于 2017-03-29 09:01:15
回答 1查看 1.8K关注 0票数 2

在我展示我做了什么之前,这里是我尝试过的任务(我是新来的,所以我不太确定我是否做得还好)。

代码语言:javascript
复制
1.  Implement lexical analyzer (using FLEX), as follows:
- Lexical analyzer supplies services next_token(), back_token()
- Lexical analyzer reads text from the input file and identifies tokens. This 
   happens when function   next_token() is called. 
- When a token is identified in the input text, it should be stored in a data 
   structure. For each token, the following attributes are saved:
   * token type
   * token lexeme
   * number of the line in the input text in which this token was found.
- Blanks, tabs, new lines – are not tokens, and should be ignored
- For each token, print (on a separate line) its type (e.g. rel_op , number , etc.) 
   and lexeme 
- Each operation, keyword, separation sign and each type of number should be 
   implemented as a token of a different kind
- Kinds of tokens are coded with integer numbers, for example:
        # define  ID_tok  1
        # define COMMA_tok  2

我使用Flex编写了以下内容:

代码语言:javascript
复制
%{
#include<stdio.h>
int line=1;
# define  ID_tok  1
# define COMMA_tok  2
#define REL_OP_tok 3
#define NUMBER_tok 4
#define KEYWORDS_tok 5
%}
binary_ar_op "*"|"/"|"+"|"-"
rel_op "=="|"!="|">"|"<"|"<="|">="
id      [a-z][a-z0-9]*
number    ["+"|"-"]?[0-9]*("."[0-9]+)?
keywords "prabegin"|"parend"|"task"|"begin"|"end"|"integer"|"real"|"do"|"until"|"od"|"send"|"accept"

%%
\n   {line++;  printf("\n%d:",line);}

{binary_ar_op}+ {printf( "An binary_ar_op: %s (%d) at line(%d)\n", yytext,
                   atoi( yytext ),line);}

{rel_op}+ {printf( "An rel_op: %s (%d) at line(%d)\n", yytext,
                   atoi( yytext ),line);}

{id}+ {printf( "An id: %s (%d) at line(%d)\n", yytext,
                   atoi( yytext ),line);}


{number}+ {printf( "An number: %s (%d) at line(%d)\n", yytext,
                   atoi( yytext ),line);}
%%
int yywrap()
{
return 1;
}
main()
{
printf("Enter a string of data\n");
yylex();
}

正如你所看到的,我已经定义了我所需要的所有类型,我不知道如何实现下一个和后一个,一些指导是很好的,我也保存了行号,但是我想它们是其他的意思--我写的是什么,我也不明白他们写的定义部分。

我知道这个问题听起来很奇怪,但是我以前是在没有任何指导和解释的情况下完成这个任务的,所以我自己正在学习它,我并不完全理解(尽管我知道这个理论,谢谢!)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-31 09:36:31

我在我们公司的项目中做了一些类似的事情。

关于令牌的

我为他们做了列举..。

关于next_token()

我的目的是将所有与令牌相关的信息存储到以下对象中:

  • 穴位标记(一个枚举值)
  • 词汇( std::string)
  • 文件位置(由文件名指针、行和列组成)。

此外,我想对这些生成的对象使用智能指针,更不用说,它们应该是C++对象。

这就是我意识到的:

  1. 重新定义yylex()函数很容易。因此,您甚至可以重命名它并更改它的签名。
  2. 很难(如果不是不可能的话)将其与yacc/bison结合起来。主要问题是数据是使用C联合(如果我记得正确的话,%union)从lex (生成的代码)传递到yacc/bison (生成的代码)。C联合和C++对象--这不太好。(C联合中的一个对象可能工作,但多个对象肯定不起作用。)

幸运的是,第二个问题实际上并不存在于我身上,因为我使用了flex,但是编写(同时生成)递归下降解析器(直接在C++中)。

那么,如何解决第一个问题呢?这是我的代码:

代码语言:javascript
复制
/// redefines proto for generated yylex function.
#define YY_DECL \
  RF::YAMS::Sim::ActionScript::RefToken \
  RF::YAMS::Sim::ActionScript::Compiler::lex(yyscan_t yyscanner)

这是您找到文档的柔性手册页。要找到如何重新定义yylex函数的解释,请在这个网站上搜索"YY_DECL“。

每当我的解析器需要一个新的令牌时,它就调用lex()

备注:

  1. 在我的例子中,我重命名了yylex(),甚至使它成为解析器类的一个方法。(我这样做是为了简化lexer对私有解析器变量的访问。)
  2. 我提供了满的作用域操作符,因为生成的lex代码不考虑我在C++代码中使用的任何名称空间。
  3. yyscan_t yyscanner参数必须存在,因为我生成可重入的扫描器。你必须决定它是否应该在那里。(相反,您也可以提供其他参数。)
  4. 返回的RefToken是指向所产生的令牌的智能指针。(智能指针可以非常容易地在不同的“地方”生成和使用令牌,而不会造成内存泄漏的危险。)

如果生成的lexer与野牛生成的解析器相结合,那么它可能就不那么容易了。在本例中,我将使用静态变量并组织队列将值从lexer传递到解析器。这是可行的,但是,当然,不像上面的方法那样优雅和节省。

关于back_token()

一旦您有了一个使用令牌的解析器,您可以随意使用它们。在我的例子中,其中一个要求是回溯跟踪的选项。因此,我不得不不时地将令牌推回输入。为此,我简单地将它们堆在解析器中。如果需要一个新的令牌,我首先检查这个堆栈是否为空。如果没有,则会弹出最上面的令牌,否则将调用lex()方法以获得真正的新令牌。在您的情况下,我想可以使用类似的解决方案来实现back_token()

关于空白

实际上,我的lexer中有两种类型的规则(即规则操作):

  1. return new Token(...);结束的操作
  2. break;结束的操作

后者我用来消耗分离器(如空格等)。甚至注释(解析器甚至看不到它们)。这是因为lexer实际上只不过是包装在switch()循环中的一个for()。(我从柔性医生那里学到了这个“技巧”。在某个地方明确提到)。

还有.

除了YY_DECL之外,我还重新定义了YY_INPUT。我这样做是为了在C++ std::stream中使用lexer (而不是yyin)。

IMHO flex确实提供了一个非常全面的手册。但是,每当我有疑问时,我都会查看flex生成的C文件。对于有限自动机,有一些可怕的int数组,我通常会忽略它。其余的是围绕在它们周围的底层结构,您会发现您的C操作(写在lex规则中)在某个地方嵌入。检查周围的代码可能会使事情变得更清楚。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43088952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档