Chinaunix首页 | 论坛 | 博客
  • 博客访问: 597662
  • 博文数量: 5
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 56
  • 用 户 组: 普通用户
  • 注册时间: 2019-06-26 09:19
文章分类
文章存档

2019年(5)

我的朋友

分类: C/C++

2019-06-26 15:07:13

编译器中的词法分析阶段是将源语言的每个符号转化成一个对应的词法单元,例如:

  1. int square(int x)
  2. {
  3.     return x * x;
  4. }

词法分析器将上述代码分解成一个个的词法单元(token):

点击(此处)折叠或打开

  1. INT ID(square) LPAREN INT ID(x) RPAREN
  2. LBRACE
  3. RETURN ID(x) TIMES ID(x)
  4. RBRACE


LPAREN, RPAREN代表左右圆括号, LBRACE, RBRACE代表左右花括号。
词法分析器的自动生成工具:
词法分析器的生成工具有很多, C通常用lex, java通常用antlr, lex只是一个词法分析的生成器,通常需要跟yacc结合来完成编译器的前端。本文主要使用lex。
lex使用正则表达式来完成词法分析器的功能。lex解析后生成一个lex.yy.c文件可以和其他文件一起编译成可执行文件。

lex的语法规则:

点击(此处)折叠或打开

  1. %{
  2. /* 要插入的C声明的代码,例如要包含的头文件,
  3.  要定义的宏等
  4. */
  5. %}
  6. /*可以插入一些正则表达式的简写形式和状态 */
  7. /* 分隔符 */
  8. %%
  9. /*包含正则表达式和匹配成功执行的动作
  10. %%
  11. /* 插入原封不动的C代码,通常插入一些函数和main
  12.  函数,这样对于某些小程序,就不用另起一个文件
  13.  来书写main函数了
  14. */

用上述C代码为例,写一个lex程序.

点击(此处)折叠或打开

  1. /* file name: exam.l */
  2. %option noyywrap
  3. %{
  4. #include "token.h"
  5. char *String(char *str) 

  6.     char *s;
  7.     s = malloc(strlen(str));
  8.     strcpy(s, str);
  9.     return s;
  10. }
  1. %}

  2. %%
  3. int {return INT;}
  4. "(" {return LPAREN;}
  5. ")" {return RPAREN;}
  6. "{" {return LBRACE;}
  7. "}" {return RBRACE;}
  8. [a-zA-Z_][0-9a-zA-Z_]* {yylval.id = String(yytext); return ID;}
  9. [\n\t ]        {continue; /*忽略回车和空白*/}


点击(此处)折叠或打开

  1. /* token.*/

  2. #ifndef _TOKEN_H
  3. #define _TOKEN_H
  4. enum {
  5.     ID = 258, INT, LPAREN, RPAREN, LBRACE, RBRACE,
  6. };
  7. union { 
  8.     char *id
  9. } yylval;
  10. #endif


点击(此处)折叠或打开

  1. /* main.c */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "token.h"
  5.  
  6. extern int yylex();
  1. int main(void)
  2. {
  3.     int tok = 1;
  4.     while (tok) {
  5.         tok = yylex();
  6.         switch (tok) {
  7.         case ID:
  8.             printf("ID(%s)", yylval.id);
  9.             break;
  10.         case INT: 
  11.             printf("INT");
  12.             break;
  13.         case LPAREN:
  14.             printf("LPAREN");
  15.             break;
  16.         case RPAREN: 
  17.             printf("RPAREN"); 
  18.             break;
  19.         case LBRACE: 
  20.             printf("LBRACE");
  21.             break;
  22.         case RBRACE: 
  23.             printf("RBRACE");
  24.             break;
  25.         default: 
  26.             printf("unknown token");
  27.             break; 
  28.         }
  29.     }
  30. }


将上述文件逐个编译:
$ lex exam.l 
$ gcc lex.yy.c main.c -o lexer
就完成了这个简单的词法分析器。

引用: 
Modern Compiler Implementation in C
    Andrew W .Appel
Flex & Bison    John Levine


阅读(280789) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:正则表达式的表示方法

给主人留下些什么吧!~~