词法分析器

Posted megachen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了词法分析器相关的知识,希望对你有一定的参考价值。

1. 词法分析器

函数

  • skip_one_line: 跳过一行, 会在skip_comment中注释为//的时候调用
  • skip_comment: // 和 /**/
  • skip_blanks: 跳过空白行, 会在skip_comment处理完注释之后调用, 同时在get_next_token这个核心的词法分析器的接口函数中调用防止获取到的token含有空白字符
  • to_next_char: 将parser中的next_char_ptr指向的字符赋给cur_char, 并++next_char_ptr
  • to_next_char_if: 和to_next_char类似, 返回类型为bool类型, 当nextchar是我们期望的值的时候调用to_next_char并返回true, 否则直接返回false
  • peek_next_char: *parser->next_char_ptr
  • peek_cur_char: parser->cur_char
  • get_next_token: 给语法分析器调用的函数, 在get_next_token函数中主要由一个伪while循环(之所以是伪while循环, 是因为在while的结尾有return语句), 里面还有continue语句, 主要在遇到了注释, 调用了skip_comment之后continue继续获取Token, 因为注释并不是我们的token, 它是无用的; 在while中有switch case语句, 主要是通过字符判断token的类型, 这是parser->cur_token.type的值
  • parser_id: 解析id, 在该函数中, 会调用is_id_or_keyword, 来判断TokenType到底是id还是keyword
  • is_id_or_keyword: 会在parser_id中调用
  • parse_string: 解析字符串, 注意转义字符的处理, 有switch case
  • parse_num: 解析hex, dec, oct类型的token, 在该函数中调用根据前缀(0x, 0)判断, 调用对应的parse_hex, parse_dec, parse_oct, 在这写函数用主要用到C标准库中的strtol和strtod将字符串转为对应禁止的数字, 通过isxdigit和isdigit函数判断是否一个字符是合法的进制字符
  • consume_token: 和match_token一样, 这是如果不匹配就会直接退出进程

数据结构

  • Parser, 词法解析器

typedef Parser {
    const char *fname;
    const char *source;
    Token cur_token; // 不会为cur_token和pre_token赋整个的值, 而是一直在不断的更新cur_token的属性, 而pre_token则是直接通过cur_token拷贝过来的
    Token pre_token;
    char cur_char;
    char *next_char_ptr;
    VM *vm; // 在词法分析的时候可能会需要分配内存空间, 这个时候需要vm来记录分配的内存空间
} Parser;
  • Token, 简而言之就是字符串加上Token的类型

typedef struct Token {
    TokenType type;
    // ptr 与 length 表示一个单词
    char *ptr;
    unsigned int length;
    unsigned int line_no;
    
    Value value; // 这里为什么会有一个Value呢, 主要是为了方便, 如果Token的类型为num, 则Value直接存放这个值, 如果是其他的则存放其他对象头

} Token;
  • TokenType, 一个包含着Token类型的enum

typedef enum TokenType {
    /*
    符号:
        1. 比较关系符: >, >=, ==, <=, <, !=
        2. 逻辑关系符: &&, ||, !
        3. 位运算符: &, |, ~
        4. 符号: (, [, {, }, ], ), comma(,), dot(.), dotdot(..)
    
    关键字:
        1. while
        2. for
        3. if
        4. else
        5. break
        6. continue
        7. import
        8. class
        9. ...
     其他:
        1. number
        2. string
        3. id
    */
} TokenType;
  • VM虚拟机的结构

typedef struct VM {
    Class *string_class; // 用于让内置的ObjString对象指向它的类对象, 内置的类对象就在这个VM中
    Class *fn_class; // 用于让内置的ObjFunc对象的ObjHeader指向Func类对象
    Class *num_class;
    Class *bool_class;
    Class *thread_class;
    Class *class_class;
    Class *list_class;
    Class *map_class;
    Class *range_class;
    
    Parser *cur_parser;
    int allocated_bytes;
    ObjHeader *all_objects; // 有了这个, VM可以调用GC回收对象
    ObjThread *cur_thread;
    ObjModule *modules;
    MethodBuffer allMethodNames;
} VM;

方法
initVM
newVM, 在newVM中会调用initVM, 紧接着就调用buildCore函数, 在buildCore函数中会调用defineClass函数, 定义出内置的ObjectClass, ObjectMetaClass, ClassOfClass类, 并为他们绑定方法(C语言上的函数), 接着executeModule加载执行核心模块

注意

  1. 词法分析器不负责解析时候的报错, 报错是交给编译模块的

以上是关于词法分析器的主要内容,如果未能解决你的问题,请参考以下文章

词法分析

词法分析器代码复审

实验一 词法分析器+编译原理

Second-词法分析

lex实现扩展的pl0语言的词法分析器(附源码)

词法分析器