1

「F#Parsed Language Starter」の一部として提供されているサンプル文法を拡張して、単項マイナス(2 * -5などの式の場合)をサポートしようとしました。

ここでSamsdramのようなブロックをヒットしました

基本的に、次のように.fsyファイルのヘッダーを拡張して優先順位を含めました。

......
%nonassoc UMINUS
....

そして、そのような文法の規則:

...
Expr: 
| MINUS Expr %prec UMINUS   { Negative ($2) }
...

また、ASTの定義:

...
and Expr =
    | Negative of Expr
.....

ただし、上記の式を解析しようとすると、パーサーエラーが発生します。

何が欠けているのかアイデアはありますか?F#コンパイラのソースコードを読みましたが、これをどのように解決するかは明確ではありませんが、非常に似ているようです

編集

優先順位は次のように順序付けられます。

%left ASSIGN
%left AND OR
%left EQ NOTEQ LT LTE GTE GT
%left PLUS MINUS
%left ASTER SLASH
%nonassoc UMINUS
4

2 に答える 2

0

遊んで、を必要とせずに優先順位を機能させることができました%prec。スターターを少し変更しました(より意味のある名前)

Prog:
    | Expression EOF { $1 }

Expression:
    | Additive { $1 }

Additive:
    | Multiplicative { $1 }
    | Additive PLUS  Multiplicative { Plus($1, $3)  }
    | Additive MINUS Multiplicative { Minus($1, $3) }

Multiplicative:
    | Unary { $1 }
    | Multiplicative ASTER Unary { Times($1, $3)  }
    | Multiplicative SLASH Unary { Divide($1, $3) }

Unary:
    | Value { $1 }
    | MINUS Value { Negative($2) }

Value:
    | FLOAT { Value(Float($1)) }
    | INT32 { Value(Integer($1)) }
    | LPAREN Expression RPAREN { $2 }

また、スターターのやり方が気に入らなかったので、式を1つのバリアントにグループ化しました。(それを歩くのは厄介でした)。

type Value =
    | Float   of Double
    | Integer of Int32
    | Expression of Expression

and Expression =
    | Value of Value
    | Negative of Expression
    | Times  of Expression * Expression
    | Divide of Expression * Expression
    | Plus  of Expression * Expression
    | Minus of Expression * Expression

and Equation =
    | Equation of Expression
于 2011-04-24T02:09:25.530 に答える
0

私の記事Parsing text with Lex and Yacc (2007 年 10 月) からコードを取得します。

私の優先順位は次のようになります。

%left PLUS MINUS
%left TIMES DIVIDE
%nonassoc prec_uminus
%right POWER
%nonassoc FACTORIAL

yacc 解析コードは次のとおりです。

expr:
| NUM                          { Num(float_of_string $1) }
| MINUS expr %prec prec_uminus { Neg $2 }
| expr FACTORIAL               { Factorial $1 }
| expr PLUS expr               { Add($1, $3) }
| expr MINUS expr              { Sub($1, $3) }
| expr TIMES expr              { Mul($1, $3) }
| expr DIVIDE expr             { Div($1, $3) }
| expr POWER expr              { Pow($1, $3) }
| OPEN expr CLOSE              { $2 }
;

同等に見えます。問題は、私の場合ではUMINUSなく、大文字で使用することではないと思いますprec_uminusか?

もう 1 つのオプションはexpr、優先レベルごとに 1 つずつ、いくつかの相互に再帰的な部分に分割することです。

于 2011-04-24T11:00:31.343 に答える