Расширение примера грамматики для Fsyacc с одинарным минусом - PullRequest
1 голос
/ 24 апреля 2011

Я попытался расширить пример грамматики, которая входит в состав "F # Parsed Language Starter", для поддержки унарного минуса (для выражений типа 2 * -5).

Я попал в блок, как Samsdram здесь

По сути, я расширил заголовок файла .fsy, включив в него приоритет следующим образом:

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

, а затем правила грамматики, например, так:

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

также, определение AST:

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

, но все равно выдается ошибка синтаксического анализатора при попытке проанализировать вышеупомянутое выражение.

Есть идеи, чего не хватает?Я прочитал исходный код компилятора F #, и не ясно, как они это решают, похоже, очень похоже

EDIT

Приоритеты упорядочены следующим образом:

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

Ответы [ 2 ]

0 голосов
/ 24 апреля 2011

Взяв код из моей статьи Синтаксический анализ текста с помощью Lex и Yacc (октябрь 2007 г.).

Мои приоритеты выглядят так:

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

и код синтаксического анализа yaccis:

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 в моем случае?

Другой вариант - разделить expr на несколько взаимно-рекурсивных частей, по одной для каждого приоритета.уровень.

0 голосов
/ 24 апреля 2011

Поиграл и сумел заставить работать старшинство без необходимости %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 }

Я также сгруппировал выражения в один вариант, так как мне не понравилось, как это делал стартер. (было неловко ходить по нему).

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
...