Lua2.4 词法分析 lex.c

先看一下在打开文件里用到的一个函数 lua_setinput

void lua_setinput (Input fn)
{
  current = ‘ ‘;
  input = fn;
  if (yytext == NULL)
  {
    textsize = MINBUFF;
    yytext = newvector(textsize, char);
  }
}

设置当前是的输入字符为空格。
设置函数指针,函数指针的定义为:
typedef int  (*Input) (void);
即:函数指针指向一个无参的函数,返回一个整数类型。
如果 yytext 为空,则设置其大小,并给它分配内存。newvector 内存分配宏,在 mem.h 中定义。Lua2.4 中的内存分配相关方法都在 mem.h 中声明。

char *lua_lasttext (void)
{
  *yytextLast = 0;
  return yytext;
}

在语法错误时会调用到它,以获取出错处的输入文本。

static struct
  {
    char *name;
    int token;
  } reserved [] = {
      {"and", AND},
      {"do", DO},
      {"else", ELSE},
      {"elseif", ELSEIF},
      {"end", END},
      {"function", FUNCTION},
      {"if", IF},
      {"local", LOCAL},
      {"nil", NIL},
      {"not", NOT},
      {"or", OR},
      {"repeat", REPEAT},
      {"return", RETURN},
      {"then", THEN},
      {"until", UNTIL},
      {"while", WHILE} };
#define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0]))
void luaI_addReserved (void)
{
  int i;
  for (i=0; i<RESERVEDSIZE; i++)
  {
    TaggedString *ts = lua_createstring(reserved[i].name);
    ts->marked = reserved[i].token;  /* reserved word  (always > 255) */
  }
}

定义保留字,或叫关键字。
结构体 name 字段是名字,token 是保留字的值。保留字的值在词法分析的时候会用到。
luaI_addReserved 把所有保留字添加到全局字符串中去。同时设置其为不可回收,也就是把 TaggedString 的 marked 字段设置为上面提到的保留字的值。

luaY_lex 是词法分析的主要部分,它内部是一个循环,输入中的字符一经词法分析之后变成一个个的 token. token 有几种:
一个整数值,在 parser.c 中定义的一些宏,比如 WRONGTOKEN, IF, THEN 之类的, 直接表示它自己的,就是看到这个整数值,它的意思明确的表示了自己.
一个整数值和一个表示内容的数据结构 YYSTYPE luaY_lval,像 NAME, NUMBER 就是此类. 比如 NUMBER,返回一个这个类型则只知道 token 是一个数值,至于具体数值是什么,要看 luaY_lval 的 vFloat 字段.
luaY_lex 就不一行一行的看了,里面相对没有什么难点,照着每个 switch case 一点点来就好。注意就是这里面的和长字符串表示,就是由两个左中括号起头的字符串,这里是特别处理,长字符串中的内容全部保持原样。

词法分析先到这里了。

----------------------------------------
记一下到目前为止的问题:
lex.c
> newvector 内存分配相关的方法
> lua_createstring 是什么? TaggedString 是个什么数据结构?
> luaI_codedebugline 是什么? 调试相关信息有哪些?

inout.c
> luaI_createfixedstring 是什么? 那个 TaggedString 是个什么数据结构?

luac.c
> do_compile 里的 TFunc 是什么?那个初始化 luaI_initTFunc 是什么?
> lua_parser 是什么? do_dump 方法里调的那几个方法又分别是干什么的?
----------------------------------------

时间: 2024-10-13 16:13:52

Lua2.4 词法分析 lex.c的相关文章

Clang之词法分析Lex

Clang是LLVM编译器框架的前端(Frontend)编译器,可编译链接C.C++.Objective-C和Objective-C++四种语言的项目代码.Clang 的开发目标是提供一个可以替代 GCC 的前端编译器,与GCC相比,节省时间和内存空间:拥有更人性化的代码诊断输出:基于库的框架,使编译和链接过程模块化:方便集成进IDE等等(具体参见calng源码目录clang/www/comparison.html, clang都指源码目录,以下都同此).从开发角度,GCC或G++代码庞大,代码

Yacc 与 Lex 快速入门(词法分析和语法分析)

我们知道,高级语言,一般的如c,Java等是不能直接运行的,它们需要经过编译成机器认识的语言.即编译器的工作. 编译器工作流程:词法分析.语法分析.语义分析.IR(中间代码,intermediate Representation)产生.IR优化.代码产生.最终优化: 我们这里主要介绍的是语法分析: Lex 代表 Lexical Analyzar.Yacc 代表 Yet Another Compiler Compiler. 让我们从 Lex 开始吧. Lex Lex 是一种生成扫描器的工具.扫描器

词法分析程序 LEX和VC6整合使用的一个简单例子

词法分析的理论知识不少,包括了正规式.正规文法.它们之间的转换以及确定的有穷自动机和不确定的有穷自动机等等... 要自己写一个词法分析器也不会很难,只要给出了最简的有穷自动机,就能很方便实现了,用if.switch-case来写一通所谓的状态转换就可以,我近期会写一个简单的词法分析程序来作为例子... 现在已经有人发明了一个叫LEX的工具让你去应用,那我们就省了不少力气,毕竟没到万不得已的时候,我们都没必要重新发明轮子,从另一个角度来说,使用工具是我们人类知识继承的一种方法,也是我们比其他动物优

yacc语法分析与lex词法分析相结合

语法 对于某些应用,我们所完成的简单的词类识别也许足够用了;而另一些应用需要识别特殊的标记序列并执行适当的动作.传统上,对这样的一套动作描述成为语法. 使用右箭头"->"意味着可以用一个新的符号取代一套特殊的标记. 例如: subject ->noun\pronoun 指示一个新的符号subject是名词或代词. 词法分析程序和语法分析程序的通信 当一起使用lex扫描程序和yacc语法分析程序的时候,语法分析程序是比较高级别的例程.当他需要来自输入的标记时,就调用词法分析程

软件构造—— 实验二 lex词法分析

实验题目: 拷贝一个C文件,将其中的关键字int替换成float. 代码: 1 %{ 2 %} 3 %% 4 //表示如果是在双引号(")中(即为字符串),则照常打印,编译时请删除此注 5 \".*\" {printf("%s",yytext);} 6 [^ \t\n]+ {printf("%s",yytext);} 7 //表示如果遇到float,且附加模式是后面跟有空白符,则将float替换为double,编译时请删除此注释 8 i

Lua2.4 打开文件 inout.c

这里根据 luac.c 里的函数调用顺序,依次展开相关的代码.首先要看的就是 lua_openfile,该函数定义于 inout.c 中: /* ** Function to open a file to be input unit. ** Return the file. */ FILE *lua_openfile (char *fn) {  lua_setinput (fileinput);  if (fn == NULL)  {    fp = stdin;    fn = "(stdin

Lua2.4 内存分配 mem.c

先看看头文件里的定义,定义了一些出错信息,几个内存管理接口,和宏.几个宏的定义也是用到了内存分配的几个接口.newvector 在之前的词法分析里已经出现了.几个接口,看函数名字比较容易看出来它的作用.下面看一下它们各自的实现: void luaI_free (void *block) {   if (block)   {     *((int *)block) = -1;  /* to catch errors */     free(block);   } } 释放内存.设置 -1 的那个地

Yacc 与 Lex 快速入门

Yacc 与 Lex 快速入门 Lex 与 Yacc 介绍 Lex 和 Yacc 是 UNIX 两个非常重要的.功能强大的工具.事实上,如果你熟练掌握 Lex 和 Yacc 的话,它们的强大功能使创建 FORTRAN 和 C 的编译器如同儿戏.Ashish Bansal 为您详细的讨论了编写自己的语言和编译器所用到的这两种工具,包括常规表达式.声明.匹配模式.变量.Yacc 语法和解析器代码.最后,他解释了怎样把 Lex 和 Yacc 结合起来. 5 评论 Ashish Bansal ([ema

通过词法分析实现的指出C程序中包含的头文件

在阅读有些程序的源码时,很希望能够马上弄清楚源码中到底包含了哪些头文件,以确定是否需要为了特殊的函数而手动加入#include.借助flex的词法分析实现了这一功能,本质上就是对正则表达式的匹配.注意这个程序不能够处理包含嵌套的情形(也就是说不能指出包含文件包含了哪些文件),感兴趣的可以通过栈来实现.源码如下: 1 /*源代码:ic.l*/ 2 3 /*定义文件预处理指令文件名起始状态*/ 4 %x IFILE 5 6 %% 7 ^"#"[ \t]*include[ \t]*[\&qu