基本

基本

簡単な紹介

Bisonは、.y ファイル内の事前定義されたルールに基づくユーザー入力コンテンツに基づいて構文分析ツリーを構築する構文アナライザーです(いわゆるルールは、対応する文字を一致させた後、対応するアクションを実行するというものです。)

簡単な文法の例と分析:

statement :NAME '=' expression
expression : NUMBER '+' NUMBER 
           | NUMBER '-' NUMBER

コロン (:) は、ルールの左側と右側を区切るために使用されます。ステートメントは NAME '=' 式と同等です。

文法では、大文字と引用符の内容は終端記号であると規定されており、たとえば、NAME '=' という 2 文字は意味を持たなくなり、終了します。

Expression は非終端記号であり、2 行目の規定により、Expression は
2 つの数の加算または 2 つの数の減算に相当します。**垂直バー (|)** は、構文シンボルに 2 つの同等の方法があることを示します。
NUMBER '+' NUMBER NUMBER '-' NUMBER はすべて終端記号であり、文法の解析は終了します。

引っ越しプロトコル分析

Bison が解析ツリーを処理すると、一連の状態が作成されます。各状態は 1 つ以上の解析されたルール内の可能な位置に対応します。

読み取りトークンがルールを終了するのに十分でない場合、トークンは内部スタックにプッシュされ、新しい状態に切り替えられます。このプロセスは シフトイン と呼ばれます

スタックにプッシュされたすべての構文シンボルがルールの右側の部分と同等の場合、これらのシンボルをすべてポップし、ルールの左側の部分をスタックにプッシュします。このプロセスは仕様と呼ばれます。

Bison コンポーネント

定義部
%%
ルール部
%%
ユーザ付加C言語部

最初の部分は定義部分で、主にオプションテキスト ブロックコメント宣言シンボルセマンティック値データ型のコレクション指定された開始シンボルおよびその他の宣言などが含まれます。
%{ と %} の間に存在するテキスト ブロックは、変更されずに生成されたファイルにコピーされます。

/* 指定起始符号(start symbol)有时也称为目标符号(goal symbol) */
%start calclist
/* 声明tokens记号,以便于告诉bison在语法分析程序中记号的名称。通常这些记号总是使用大写字母,虽然bison本身并没有这个要求。 */
%token NUMBER 
    
%{
  /* 文字块,该部分的内容将直接复制到生成的代码文件的开头,
  以便它们在使用yyparse定义之前使用。 */
  #define _GNU_SOURCE
  #include <stdio.h>
  #include "ptypes.h"
%}

後半は主に文法規則についてです

%%
 /* 空规则 -- 起始符号(start symbol)有时也称为目标符号(goal symbol) */
calclist:
  /* 如果没有指定语义动作,bison将使用默认的动作: { $$ = $1; }*/
  | calclist exp EOL { printf("- %d\n", $2); } 
  //EOL代表一个表达式的结束。像flex一样,大括号中的表示规则的动作
  ;

exp: factor // default $$ = $1
  | exp ADD factor { $$ = $1 + $3; }
  | exp SUB factor { $$ = $1 - $3; }
  ; // represent the termination of this rule.

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

term: NUMBER // default $$ = $1
  | ABS term { $$ = $2 >= 0? $2 : - $2; }
  ;
%%

3 番目の部分では、この部分の内容が、生成されたコード ファイルの末尾にそのままコピーされます。この部分は主に、以前に宣言されたいくつかの関数を実装するために使用されます。

int main(int argc, char ** argv)
{
    printf(">");
    yyparse();
    return 0;
}
 
yyerror(char *s)
{
    fprintf(stderr,"error:%s\n",s);
}

左再帰と右再帰 再帰
ルールを作成する場合、ルールの右側部分の左端または右端に再帰参照を配置できます。次に例を示します。

exprlist: exprlist ',' expr; /* 左递归 */
exprlist: expr ',' exprlist; /* 右递归 */

ほとんどの場合、どちらの方法でも構文を記述することができます。bison は、右再帰よりも左再帰を効率的に処理しますこれは、内部スタックが現在分析中のすべてのルールのすべてのシンボルを追跡する必要があるためです。

YYINITDEPTH はパーサー スタックの長さを制御し、スタックの初期サイズ (通常は 200) を示します。また、YYMAXDEPTH を定義して最大スタック長 (通常は 1000) を設定することもできます。

%{
#define YYMAXDEPTH 50000
%}

おすすめ

転載: blog.csdn.net/u010523811/article/details/132954912