3

こんにちは私はそれがどのように機能するかを学ぶために小さなバイソンに取り組んでいます。バイソンは文を解析することになっています。文は表現で構成され、表現は単語で構成されています。

以下は私のコードです:

%{
#include <stdio.h>
#include <string.h>


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

int yywrap()
{
    return 1;
}

main()
{
    yyparse();
}

%}

%token ASSIGN RANGE OR AND WHITESPACE QUOTE LPAREN RPAREN NOT GREATER LESS

%union 
{
        int number;
        char *string;
}

%token <number> VALUE
%token <string> WORD

%type <string> term
%type <string> expression
%%

query:   /* empty */
    | query expression 
    {
        printf("WOrd:%s",$2);
    }
    ;

expression:
     term
    |expression term
    |expression AND term
        {
            printf("AND");
        }
    ;

term:
    WORD
    {
        $$=$1;
    }
    ;

したがって、ユーザーが単語を入力すると、その単語が印刷されることになっています。ユーザーは次のように入力できる必要があります:単語、単語単語、単語、単語

$$を使用して単語を渡し、「クエリ式」ルールから出力する方法がわかりません。どうすればよいですか?

これは私のフレックスです:

%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
[0-9]+                  yylval.number=atoi(yytext);return VALUE;
[a-zA-Z][a-zA-Z]*       yylval.string=strdup(yytext);return WORD;
":"                     return ASSIGN;
"and"|"&"|"&&"          return AND; 
".."                    return RANGE;
"-"                     return NOT;
"|"                     return OR;
"\""                    return QUOTE;
">"                     return GREATER;
"<"                     return LESS;
\n                      /* ignore end of line */;
\t                      /* ignore end of line */;

%%

事前に感謝します。サラ

4

1 に答える 1

9

通常、パーサーを作成するポイントは、最終的に入力を表すデータ構造になるようにすることです。次に、何らかの方法で構造を変換するか、あなたの場合は単に印刷します。

式を生成するたびに、これまでに認識したことを表す構造内にノードを構築する必要があります。

少しさびていますが、次のようになります。

query:   /* empty */
     | query expression { printNode($2); /* printf()s are in here */ }
;

expression: term { $$ = makeTermNode($1); }
          | expression OR term { $$ = makeOrNode($1, $3); }
          | expression AND term  { $$ = makeAndNode($1, $3); }
;

ノードを保持するデータ構造:

struct Node {
    int nodeType;          /* WORD or operator token like AND, OR */
    node* leftOperand;
    node* rightOperand;    /* will be null if the node is a term */
}

%union 
{
    int number;
    char *string;
    Node *node;
}

アップデート:

C でコーディングしてからしばらく経ったので、疑似コードに頼る必要があります。処理が完了したら、メモリを再利用するためのコードはここにはありません。他の失策についてはお詫び申し上げます。

struct Node *makeTermNode(int word) {
    Node *node = malloc(sizeof struct Node);
    node->nodeType = word;
    node->rightOperand = null;
    node->leftOperand = null;
    return node;
}

WORD トークンは、何らかの文字列がスキャンされたことを示しているだけであることに注意してください。文字の特定のシーケンスは破棄されます。(シーケンスを知りたい場合は、レクサーが WORD トークンの代わりに yytext のコピーを返すようにします。)

struct Node *makeAndNode(struct Node* leftOperand, struct Node *rightOperand) {
    Node *node = malloc(sizeof struct Node);
    node->nodeType = AND;
    node->leftOperand = leftOperand;
    node->rightOperand = rightOperand;
    return node;
}

makeOrNode() についても同様です。あるいは、makeNodeWithOperator(int operator, struct Node* leftOperand, struct Node *rightOperand) だけを記述して、「and」および「or」のケースを処理することもできます。

printAllNodes() を printNode() に変更しました。構築した式ツリー構造のルートから開始し、最初に各部分式の左側を再帰的に訪れ、次に右側を訪れます。次のようになります。

void printNode (struct Node* node) {
    switch (node->nodeType) {
    case WORD:
        printf("%i", node->nodeType);
        return;
    case AND:
    case OR:
        printf("(");
        printNode(node->leftOperand);
        printf("%i", node->nodeType);
        printfNode(node->rightOperand);
        printf(")");
        return;
    }
}
于 2012-04-20T14:34:24.413 に答える