2022年4月24日日曜日

BisonとFlexで四則演算(カッコ未実装)

よくある、BisonとFlexを使った四則演算

カッコはまだ実装してない

しかも、抽象構文木も作ってないし、ABSの実装も適当

ただ、優先度つけてるだけ


mycalc.y

%{
#include<stdio.h>
%}

%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL

%%

calclist:
    | calclist exp EOL {printf("= %d\n", $2); }
;

exp: factor
    | exp ADD factor { $$ = $1 + $3; }
    | exp SUB factor { $$ = $1 - $3; }
;

factor: term
    | factor MUL term { $$ = $1 * $3; }
    | factor DIV term { $$ = $1 / $3; }
;

term : NUMBER
    | ABS term { $$ = $2 >= 0 ? $2 : - $2; }
;

%%

int main (int argc, char** argv)
{
    yyparse();
    return 0;
}

yyerror(char *s)
{
    fprintf(stderr, "error: %s\n", s);
}

んで、これをBisonにかける

bison -d mycalc.y

mycalc.tab.hが出来るので、中身を見ると以下の記述が出来ている。

/* Token type.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
  enum yytokentype
  {
    NUMBER = 258,
    ADD = 259,
    SUB = 260,
    MUL = 261,
    DIV = 262,
    ABS = 263,
    EOL = 264
  };
#endif

%tokenから定義が作られる。

つぎに字句解析部

mycalc.l

%{
#include "mycalc.tab.h"
int yylval;
%}

%%
"+" { return ADD;}
"-" { return SUB;}
"*" { return MUL;}
"/" { return DIV;}
"|" { return ABS;}
[0-9]+ { yylval = atoi(yytext); return NUMBER;}
\n { return EOL;}
[ \t] {}
. {printf("Mystery character %c\n", *yytext);}

%%

さきほどbisonが吐き出したmycalc.tab.hをincludeして、

ADDやSUBなどを返すのが主な仕事

値はyylvalに入れて、NUMBERを返すようになっている。

こっちにはmain関数は無い

flexでlex.yy.cを作る

flex mycalc.l


んで、lex.yy.cを見てみると、すげー長いコードが出来ていて、

こんな字句解析要る?ってみんな思うし、

自分で作ったほうがよくね?と話題になったりする。


最後にまとめる

 cc -o mycalc XQParser.tab.c lex.yy.c -lfl


./mycalc

1+2

= 3

3+3

= 6

1+2+3*4/2

= 9

まぁ一応動くのが出来る。


ここまで、Bison And Flexのコードなんだけど、

ABS動かないよね、なんじゃこれ状態?



0 件のコメント: