首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用一元减号扩展Fsyacc的示例语法

使用一元减号扩展Fsyacc的示例语法
EN

Stack Overflow用户
提问于 2011-04-24 06:35:18
回答 2查看 779关注 0票数 1

我试图扩展作为"F#解析语言入门“一部分的示例语法,以支持一元减号(对于像2*-5这样的表达式)。

我遇到了像Samsdram here这样的障碍

基本上,我扩展了.fsy文件头以包括优先级,如下所示:

代码语言:javascript
复制
......
%nonassoc UMINUS
....

然后语法规则是这样的:

代码语言:javascript
复制
...
Expr: 
| MINUS Expr %prec UMINUS   { Negative ($2) }
...

另外,AST的定义:

代码语言:javascript
复制
...
and Expr =
    | Negative of Expr
.....

但是当尝试解析上面提到的表达式时,仍然会得到一个解析器错误。

你知道遗漏了什么吗?我读过F#编译器的源代码,并不清楚他们是如何解决这个问题的,看起来很相似

编辑

优先级是这样排序的:

代码语言:javascript
复制
%left ASSIGN
%left AND OR
%left EQ NOTEQ LT LTE GTE GT
%left PLUS MINUS
%left ASTER SLASH
%nonassoc UMINUS
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-24 10:09:26

在不需要%prec的情况下,成功地实现了优先级。稍微修改了一下starter (更有意义的名字)

代码语言:javascript
复制
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 }

我还将表达式分组到一个变体中,因为我不喜欢启动器的方式。(穿行起来很尴尬)。

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2011-04-24 19:00:31

摘自我的文章Parsing text with Lex and Yacc (2007年10月)中的代码。

我的优先顺序如下:

代码语言:javascript
复制
%left PLUS MINUS
%left TIMES DIVIDE
%nonassoc prec_uminus
%right POWER
%nonassoc FACTORIAL

yacc解析代码是:

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5767421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档