开发编程语言(五):词法分析

随笔 2016-07-24

起步

我的开发阶段比写博客的速度要快一些,终于也有了可以运行的版本了. github:https://github.com/OriginUnion/origin

词法分析

词法分析其实就是把源代码分割为若干个记号(Token),给一个单词或者数字标记,给保留字添加标签,数字归数字的一类,变量归变量,运算符归运算符.

执行词法分析器的程序也称为词法分析器.在这个开发过程中我用了flex/lex工具来完成.关于它的用法兄台可以自己查找.

词法划分

定义下保留字,操作符,变量命名规则,注释,字符串.需要注意的的,在注释里面是要忽视里面的所有内容的,这里可以用通过开始条件完成.

<INITIAL>#      {BEGIN COMMENT;}
<COMMENT>.  ;/*注释的其他字符都不予处理*/
<COMMENT>\n {
    //单行注释结束,条件设为初始条件
    increase_line_num();
    BEGIN INITIAL;
}

这样就可以对#开头的行不进行处理了. 处理字符串如下:

<STRING_LITERAL_STATE>\"    {
    //遇到字符串形如 "this is string\n"
    Expression *expression = org_alloc_expression(STRING_EXPRESSION);
    expression->u.string_value = org_close_string_literal();
    yylval.expression = expression;
    BEGIN INITIAL;
    return STRING_LITERAL;
}

<STRING_LITERAL_STATE>\n    {
    org_add_string_literal('\n');
    increase_line_num();
}
<STRING_LITERAL_STATE>\\\"  org_add_string_literal('"');
<STRING_LITERAL_STATE>\\n   org_add_string_literal('\n');
<STRING_LITERAL_STATE>\\t   org_add_string_literal('\t');
<STRING_LITERAL_STATE>\\\\  org_add_string_literal('\\');
<STRING_LITERAL_STATE>.     org_add_string_literal(yytext[0]);

完整的词法分析器

%{

    //词法分析器
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "DBG.h"
    #include "origin.h"
    #include "y.tab.h"

    /*
    解析一个文件完毕后会调用yywrap,返回表示1结束,返回0表示继续
    */
    int yywrap(void) {
        return 1;
    }

    static void increase_line_num(void) {
        org_get_current_interpreter()->current_line_number++;
    }

    //定义保留字
%}

%start COMMENT STRING_LITERAL_STATE

%%
<INITIAL>"function"     return FUNCTION;
<INITIAL>"if"           return IF;
<INITIAL>"else"         return ELSE;
<INITIAL>"elseif"       return ELSEIF;
<INITIAL>"while"        return WHILE;
<INITIAL>"for"          return FOR;
<INITIAL>"continue"     return CONTINUE;
<INITIAL>"break"        return BREAK;
<INITIAL>"null"         return NULL_O;
<INITIAL>"true"         return TRUE_O;
<INITIAL>"false"        return FALSE_O;
<INITIAL>"global"       return GLOBAL_O;
<INITIAL>"return"       return RETURN_O;
<INITIAL>"("            return LP;
<INITIAL>")"            return RP;
<INITIAL>"{"            return LC;
<INITIAL>"}"            return RC;
<INITIAL>";"            return SEMICOLON;
<INITIAL>","            return COMMA;
<INITIAL>"&&"           return LOGICAL_AND;
<INITIAL>"||"           return LOGICAL_OR;
<INITIAL>"="            return ASSIGN;
<INITIAL>"=="           return EQ;
<INITIAL>"!="           return NE;
<INITIAL>">"            return GT;
<INITIAL>">="           return GE;
<INITIAL>"<"            return LT;
<INITIAL>"<="           return LE;
<INITIAL>"+"            return ADD;
<INITIAL>"-"            return SUB;
<INITIAL>"*"            return MUL;
<INITIAL>"/"            return DIV;
<INITIAL>"%"            return MOD;

<INITIAL>[A-Za-z_][A-Za-z_0-9]* {
    //标识符(变量名,函数名)
    yylval.identifier = org_create_identifier(yytext);
    return IDENTIFIER;
}

<INITIAL>([1-9][0-9]*big)|0big {
    //大数类型
    int len = strlen(yytext);
    char *text = malloc(len - 2);
    memcpy(text, yytext, len-3);
    text[len-1] = '\0';
    Expression *expression = org_create_bignum(text);
    yylval.expression = expression;
    return INT_LITERAL;
}

<INITIAL>([1-9][0-9]*)|0 {
    //整数类型
    Expression *expression = org_alloc_expression(INT_EXPRESSION);
    sscanf(yytext, "%d", &expression->u.int_value);
    yylval.expression = expression;
    return INT_LITERAL;
}

<INITIAL>[0-9]\.[0-9]+ {
    //处理double类型
    Expression *expression = org_alloc_expression(DOUBLE_EXPRESSION);
    sscanf(yytext, "%lf", &expression->u.double_value);
    yylval.expression = expression;
    return DOUBLE_EXPRESSION;
}

<INITIAL>\" {
    //处理字符串
    org_open_string_literal();
    BEGIN STRING_LITERAL_STATE;
}

<INITIAL>[ \t] ;/*对于空格和制表符,无动作*/
<INITIAL>\n     {increase_line_num();}
<INITIAL>#      {BEGIN COMMENT;}
<INITIAL>.      {
    char buf[LINE_BUF_SIZE];
    if(isprint(yytext[0])) {
        buf[0] = yytext[0];
        buf[1] = '\0';
    }else {
        sprintf(buf, "0x%02x", (unsigned char)yytext[0]);
    }
    //编译错误
    //org_compile_error();
}

<COMMENT>\n {
    //单行注释结束,条件设为初始条件
    increase_line_num();
    BEGIN INITIAL;
}
<COMMENT>.  ;/*注释的其他字符都不予处理*/

<STRING_LITERAL_STATE>\"    {
    //遇到字符串形如 "this is string\n"
    Expression *expression = org_alloc_expression(STRING_EXPRESSION);
    expression->u.string_value = org_close_string_literal();
    yylval.expression = expression;
    BEGIN INITIAL;
    return STRING_LITERAL;
}

<STRING_LITERAL_STATE>\n    {
    org_add_string_literal('\n');
    increase_line_num();
}
<STRING_LITERAL_STATE>\\\"  org_add_string_literal('"');
<STRING_LITERAL_STATE>\\n   org_add_string_literal('\n');
<STRING_LITERAL_STATE>\\t   org_add_string_literal('\t');
<STRING_LITERAL_STATE>\\\\  org_add_string_literal('\\');
<STRING_LITERAL_STATE>.     org_add_string_literal(yytext[0]);

%%

本文由 hongweipeng 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

如果对您有用,您的支持将鼓励我继续创作!