我想让一个解析器为let-in-expression语言感到高兴。例如,我想解析以下字符串:
let x = 4 in x*x
在大学里我们研究属性语法,我想用这个技巧直接计算解析后的let-in-expression的值。所以在happy文件中,我将解析函数的数据类型设置为Int,并创建了一个名为 env 的新属性。此属性是从String到Int的函数,它将变量名称与值相关联。参考我的例子:
env "x" = 4
现在我把这里放在快乐文件下面,那里有我的语法:
{
module Parser where
import Token
import Lexer
}
%tokentype { Token }
%token
let { TLet }
in { TIn }
int { TInt $$ }
var { TVar $$ }
'=' { TEq }
'+' { TPlus }
'-' { TMinus }
'*' { TMul }
'/' { TDiv }
'(' { TOB }
')' { TCB }
%name parse
%attributetype { Int }
%attribute env { String -> Int }
%error { parseError }
%%
Exp : let var '=' Exp in Exp
{
$4.env = $$.env;
$2.env = (\_ -> 0);
$6.env = (\str -> if str == $2 then $4 else 0);
$$ = $6;
}
| Exp1
{
$1.env = $$.env;
$$ = $1;
}
Exp1 : Exp1 '+' Term
{
$1.env = $$.env;
$2.env = $$.env;
$$ = $1 + $3;
}
| Exp1 '-' Term
{
$1.env = $$.env;
$2.env = $$.env;
$$ = $1 - $3;
}
| Term
{
$1.env = $$.env;
$$ = $1;
}
Term : Term '*' Factor
{
$1.env = $$.env;
$2.env = $$.env;
$$ = $1 * $3;
}
| Term '/' Factor
{
$1.env = $$.env;
$2.env = $$.env;
$$ = div $1 $3;
}
| Factor
{
$1.env = $$.env;
$$ = $1;
}
Factor
: int
{
$$ = $1;
}
| var
{
$$ = $$.env $1;
}
| '(' Exp ')'
{
$1.env = $$.env;
$$ = $1;
}
{
parseError :: [Token] -> a
parseError _ = error "Parse error"
}
当我加载从上面的快乐文件生成的haskell文件时,我收到以下错误:
Ambiguous occurrence `Int'
It could refer to either `Parser.Int', defined at parser.hs:271:6
or `Prelude.Int',
imported from `Prelude' at parser.hs:2:8-13
(and originally defined in `GHC.Types')
我不知道为什么我得到这个,因为我没有在我喜欢的文件中定义类型Parser.Int。我试图用Prelude.Int替换Int,但是我得到了其他错误。
我该如何解决?如果我做的不是最佳的话,我还可以提供一些一般的提示吗?
答案 0 :(得分:0)
请参阅属性类型的快乐解释:http://www.haskell.org/happy/doc/html/sec-AtrributeGrammarsInHappy.html
你的专栏:
%attributetype { Int }
声明名为Int
的类型。这就是造成歧义的原因。