0

フォームの評価と表現を試みています

#SomeFunc[expr][expr]expr

expr は、特定の文字から構成される文字列または上記の関数のいずれかです。したがって、これは次のようになります

#SomeFunc[#SomeFunc[#SomeFunc[nm^2][nn]][nm]][n]...

問題は、次の形式でトークンにブレーキをかけた場合です。

"#"SomeFunc    {yylval.fn=F_some; return FUNC;}
m|n|ms         {return TEXT;}
"^"            {yylval.fn=F_pow;  return FUNC;}
[1-9]+         {yylval=atoi(yytext); return NUMBER;}

次のようなものがある場合、文法の構築に問題があります

#SomeFunc[#SomeFunc[nm^2][nn]][n]

calc:
      | calc expr EOL { eval($2); }

expr: TEXT {$$= add it to ast-leaf }
      | FUNC '[' expr ']' '[' expr ']' {$$= add ast(func,$3,$6) }
      | expr expr {$$= add to ast('*',$1,$2 }

文法が間違っているのか、ASTの実装が間違っているのか、よくわかりません。

nm の場合、expr は expr expr になり、n*m の値を返すため、論理に欠陥があることがわかりました。これはまだ nm です。これは無限ループを引き起こしますか?そのような式をどのように解析すればよいですか。

石を投げないでください。バイソン初心者

後で編集 して、AST といくつかのリンクされたリストの背後にあるコードをクリーンアップしてテストすることができました。唯一の問題は文法のままです。

%union { struct ast *a; char *strval; int ival; } 
%type <a> exp fact 
%token <strval> ISU 
%token <ival> NUMBER 
%token FUNC POW 
%token EOL OP CP 

%% 

calclist: | calclist exp EOL { printf("result >",eval($2));}; 

exp: fact | exp fact {$$ = newast('*', $1,$2);} ; 

fact: FUNC OP exp CP OP exp CP { $$ = newast('/',$3,$6);}
    | ISU POW NUMBER { $$ = newnum($1, $3);}
    | ISU { $$ = newnum($1,1);};  

この文法は、Frac[m^2][m^4] node / node K m^4 node K m^4 のような expr では失敗します。

4

2 に答える 2

0

説明から、「^2」が有効な expr であることが期待されますが、lex ルールは「^」の場合は FUNC を返し、「2」の場合は NUMBER を返しますが、文法では、唯一のルールで FUNC の後に「[」が続く必要があります。あなたにはそれがあり、NUMBER にはルールがありません。おそらく「expr : NUMBER」というルールが必要ですが、「^2」に一致させるには「expr: FUNC expr」というルールも必要になるため、代わりに「^」に別の値を返させたいと思うかもしれません。トークン。

于 2009-10-12T02:07:22.257 に答える
0

基本的な形式のみを表現するために文法を単純化しましたが、必ずしもそれらを組み合わせる方法を表現する必要はありません。(実験を簡単にするために、生成されたレクサーも削除しました。そのため、私の場合、すべての関数は「f」と呼ばれ、「2」である限り、任意の数字を使用できます。)

これは、さまざまなテストケースでうまくいくようです: 私のルールはすべてcalc再帰のままであることに注意してください。

cat subcity.y && yacc subcity.y && cc -w y.tab.c -ly 
%%
calc: | calc expr '\n';
expr: | expr form
      | expr operator form;
form: mns | '[' expr ']' | digit | 'f';
mns: 'm' | 'n' | 's';
digit: '2';
operator: '^' | '+' |  '-' | '*' | '/';
%%
int yylex(void) { int c; while ((c = getchar()) == ' ') continue; return c; }
int main(int ac, char **av) { if (yyparse() != 0) printf("parse error\n"); }

それはうまくいくようです:

$ ./a.out
f[ f[ f[nm^2] [nn]] [nm]] [n]
f[f[2]] [f[f[nm^2]f]]
f[f[nm^2][nn]][n]
f[m^2][m^2] n / n 2 m^2 n 2 n^2
$ 

初めての文法で何が気に入らなかったのかよくわかりませんでしたが、これが何かのヒントになれば幸いです。このようなものは、確かに私が始めるものです。あなたの文法が、演算子によって接続されていない隣接する式を特徴としているという事実は、少し奇妙です。一部の言語で文字列が連結される方法のように、終端記号ではより一般的です。このケースを排除するために演算子を発明する人もいます。

于 2009-10-12T01:34:38.110 に答える