如何在编译器野牛/词法分析器中打印字符串

How print string in compiler bison/lexer?

本文关键字:词法分析器 打印 字符串 编译器      更新时间:2023-10-16

我创建了一个小编译器,需要帮助来修复它。

我的编译器代码:

T.L:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "y.tab.h"
%}
%x DOUBLE_QUOTES
%%
<INITIAL>[s|S][h|H][o|O][w|W]               {return show;}
<INITIAL>[a-zA-z]                           {yylval.id=yytext[0];return identifier;}
<INITIAL>[0-9]+                             {yylval.num=atoi(yytext);return number;}
<INITIAL>[-+=;*/]                     {return yytext[0];}
<INITIAL>["] {
    printf("(STRING_OPEN) ");
    BEGIN(DOUBLE_QUOTES);
}
<DOUBLE_QUOTES>["] {
    printf("(STRING_CLOSE) ");
    BEGIN(INITIAL);
    printf("(STRING:%S) ",yytext[1]);
}
%%
int yywrap (void) {return 1;}

T.Y:

%{
void yyerror(char *s);
#include <stdio.h>
#include <stdlib.h>
int symbols[52];
int symbolVal(char symbol);
void updateSymbolVal(char symbol,int val);  
%}
%union {int num;char id;}
%start line
%token show
%token <num> number
%token <id> identifier
%type <num> line exp term
%type <id> assignment
%%
line    : assignment ';'        {;}
        | show exp ';'          {printf("showing : %dn",$2);}
        | line assignment ';'   {;}
        | line show exp ';' {printf("showing : %dn",$3);}
        ;
assignment: identifier '=' exp  {updateSymbolVal($1,$3);}
        ;
exp     : term                  {$$ = $1;}
        | exp '+' term          {$$ = $1 + $3;}
        | exp '-' term          {$$ = $1 - $3;}
        | exp '*' term          {$$ = $1 * $3;}
        | exp '/' term          {$$ = $1 / $3;}
        ;
term    : number                {$$ = $1;}
        | identifier            {$$ = symbolVal($1);}
%%
int computerSymbolIndex(char token)
{
    int idx=-1;
    if(islower(token))
    {
        idx=token-'a'+26;
    }
    else if(isupper(token))
    {
        idx = token - 'A';
    }
    return idx;
}
int symbolVal(char symbol)
{
    int bucket = computerSymbolIndex(symbol);
    return symbols[bucket];
}
void updateSymbolVal(char symbol,int val)
{
    int bucket = computerSymbolIndex(symbol);
    symbols[bucket] = val;
}
int main (void) {
    printf("Created By BoxWeb Incn");
    int i;
    for(i=0;i<52;i++)
    {
        symbols[i]=0;
    }
    return yyparse();
}
void yyerror (char *s) {printf("-%s at %s !n",s );}

测试编译器命令:

show 5+5;
show 5*2;
show 5+5-2*2/1;

我需要升级到(想要可以打印字符串):

show "hello" . " " . "mr";//hello mr
show 5+5 . " ?";//10 ?
and more....

在词法分析器中,我使用:

<INITIAL>["] {
    printf("(STRING_OPEN) ");
    BEGIN(DOUBLE_QUOTES);
}
<DOUBLE_QUOTES>["] {
    printf("(STRING_CLOSE) ");
    BEGIN(INITIAL);
    printf("(STRING:%S) ",yytext[1]);
}

但我不知道如何在解析器中使用它。

请帮助我完成此编译器。

让我们暂时将其简化为一种可能的操作

我们有以下语法

assignment: '$' identifier '=' exp ';'    {updateSymbolVal($2,$4); }
            ;
exp: number                               {$$ = createExp($1);}
   | string                               {$$ = createExp($1);}
   | exp '+' exp                          {$$ = addExp($1,$3);}
   ;

由于表达式可以是许多不同的东西,我们不能只将其保存在整数中,而是需要一个更复杂的结构,如下所示:

enum expType {NUMBER, STRING};
struct Exp{
    expType type;
    double number;
    std::string str;
};

然后我们制作函数来创建表达式:

Exp* createExp(int v){
    Exp *e = new Exp();
    e->type = NUMBER;
    e->number = v;
    return e;
}
Exp* createExp(std::string s){
    Exp *e = new Exp();
    e->type = STRING;
    e->str = s;
    return e;
}

然后要进行所有计算和分配,您将始终必须检查类型。

Exp* addExp(Exp *a, Exp *b){
    Exp *c;
    if(a->type == NUMBER && b->type == NUMBER){
         c->type == NUMBER;
         c->number == a->number + b->number;
    }
    else{
         std::cout << "some nice error messagen";
    }
    return c;
}

与赋值函数相同

void updateSymbolVal(const std::string &identifier, Exp *e){
    if(e->type == NUMBER){
        myNumbers[identifier] = e->number;
    }
    if(e->type == STRING){
        myStrings[identifier] = e->str;
    }
}

当然,如果您需要对结构体 Exp 进行更多操作,您也可以制作结构体 Exp 的映射/向量/数组。或者只是把它交给下一个级别。

针对多语言支持问题进行编辑

正如评论中所写的,我指的是这个问题 Flex(lexer) 对 unicode 的支持。为了根据您的需要简化它,您可以像这样。

ASC     [a-zA-Z_0-9]
U       [x80-xbf]
U2      [xc2-xdf]
U3      [xe0-xef]
U4      [xf0-xf4]
UANY    {ASC}|{U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}
UANY+   {yylval.id = yytext[0]; return string;}