我目前正在使用快乐的解析器生成器。
其他解析器生成器可以给出不错的消息,例如“意外的结束行,预期的‘然后’”。很高兴我只得到当前的令牌和错误的位置。
您能给我一个如何获取上述错误消息的示例吗?
我正在为实验语言进行语义分析.我正在使用Alex和Happy来生成词法分析器和解析器(实际上我正在使用BNFC工具来生成Alex和Happy文件).每当出现语义错误(比如类型错误)时,我都想收到包含行号和列号的错误消息.
似乎我必须在构建符号表或AST时存储行号信息.如果我可以以某种方式访问Happy文件的规则部分中的位置信息,那么我的问题就会解决.
任何有关这方面的建议都将受到高度赞赏.
我尝试实现下面建议的答案,但遗憾的是没有取得任何成功.让我们考虑一个非常简单的语法: -
Expr -> Expr + Term
| Term
Term -> Int
Run Code Online (Sandbox Code Playgroud)
我的词法分析器如下所示.
%wrapper "posn"
$digit = 0-9 -- digits
$alpha = [a-zA-Z] -- alphabetic characters
tokens :-
$white+ ;
"--".* ;
$digit+ { \p s -> L {getPos = p , unPos = Tok_Int (read s) }}
\+ { \p s -> L {getPos = p , unPos = Tok_Plus} }
{
data L a = L{ getPos :: AlexPosn, unPos :: a } deriving (Eq,Show) …Run Code Online (Sandbox Code Playgroud) 我试图在此页面之后从源代码构建GHC .安装依赖项时,我必须安装happy并alex:
$ cabal install alex happy
Resolving dependencies...
Configuring alex-3.2.1...
Configuring happy-1.19.5...
Building happy-1.19.5...
Building alex-3.2.1...
Installed alex-3.2.1
Installed happy-1.19.5
Run Code Online (Sandbox Code Playgroud)
但是在运行时configure我收到一条错误消息:
$ ./configure
...
checking for happy... no
checking for version of happy...
configure: error: Happy version 1.19.4 or later is required to compile GHC.
Run Code Online (Sandbox Code Playgroud)
我在Debian上运行stretch:
$ uname -a
Linux <host> 4.8.0-1-amd64 #1 SMP Debian 4.8.5-1 (2016-10-28) x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
任何人都可以建议一个明显的步骤我可以尝试解决这个问题
为什么这会引发关于减少/减少冲突的警告
root : set1 'X'
| set2 'X' 'X'
set1 : 'A'
| 'B'
set2 : 'B'
| 'C'
Run Code Online (Sandbox Code Playgroud)
但接下来还可以吗?
root : 'A' 'X'
| 'B' 'X'
| 'B' 'X' 'X'
| 'C' 'X' 'X'
Run Code Online (Sandbox Code Playgroud) 阅读Haskell.Happy文档并实现'let'运算符
Exp : let var '=' Exp in Exp { \p -> $6 (($2,$4 p):p) }
Run Code Online (Sandbox Code Playgroud)
docs说它是"一个带有变量值环境的函数,并返回表达式的计算值:"
无法理解语法的实际含义,如何在Haskell中调用这些结构?
编辑:我的意思是这些
\p -> $6 (($2,$4 p):p)
Run Code Online (Sandbox Code Playgroud) 如何为解析if-then [-else]案例制定正确的规则?这是一些语法:
{
module TestGram (tparse) where
}
%tokentype { String }
%token one { "1" }
if { "if" }
then { "then" }
else { "else" }
%name tparse
%%
statement : if one then statement else statement {"if 1 then ("++$4++") else ("++$6++")"}
| if one then statement {"if 1 then ("++$4++")"}
| one {"1"}
{
happyError = error "parse error"
}
Run Code Online (Sandbox Code Playgroud)
该语法正确解析以下表达式:
> tparse ["if","1","then","if","1","then","1","else","1"]
"if 1 then (if 1 then (1) else (1))"
Run Code Online (Sandbox Code Playgroud)
但编译会引发关于转移/减少冲突的警告.happy的文档包含了这种冲突的一个例子:http …
我将如何解析类似的东西
f x y
Run Code Online (Sandbox Code Playgroud)
进入
APPLY (APPLY f x) y
Run Code Online (Sandbox Code Playgroud)
使用快乐?现在我有一条规则说
%left APP
Expr : Expr Expr %prec APP { APPLY $1 $2 }
Run Code Online (Sandbox Code Playgroud)
但这将上述内容解析为
APPLY f (APPLY x y)
Run Code Online (Sandbox Code Playgroud) 当您编写Happy描述时,您必须定义可能出现的所有可能类型的令牌.但是你只能匹配令牌类型,而不是单个令牌值 ......
这有点问题.例如,考虑data关键字.根据Haskell报告,这个标记是"保留".所以我的tokeniser识别它并标记它.但是,请考虑as关键字.现在事实证明这不是一个保留; 这是一个普通的varid.它只在一个上下文中特殊.你可以完全声明一个名为的普通变量as,它很好.
所以这是一个问题:我如何as具体解析?
最初我并没有真正考虑过它.我刚刚定义了一个新的令牌类型,它表示任何文本恰好是的varid令牌as.
...然后我花了大约2个小时试图弄清楚为什么我的语法实际上不起作用.是的,事实证明,由于此令牌类型与现有令牌类型重叠,因此声明顺序非常重要.(!!!)从字面上看,改变声明的顺序使得语法完美解析.
但现在我很担心.我担心as永远不会匹配varid,只能匹配自己.所以说varid将拒绝as令牌的所有语法规则- 这是完全错误的!
解决这个问题的正确方法是什么?
我有以下(严重剥离)快乐的语法
%token
'{' { Langle }
'}' { Rangle }
'..' { DotDot }
'::' { ColonColon }
'@' { At }
mut { Mut }
ident { Ident }
%%
pattern
: binding_mode ident at_pat { error "identifier pattern" }
| expr_path { error "constant expression" }
| expr_path '{' '..' '}' { error "struct pattern" }
binding_mode
: mut { }
| { }
at_pat
: '@' pat { }
| { }
expr_path
: expr_path '::' ident …Run Code Online (Sandbox Code Playgroud) 我正在尝试熟悉Haskell的Happy parser生成器.目前,我有一个文档的例子,但是当我编译程序时,我收到一个错误.这是代码:
{
module Main where
import Data.Char
}
%name calc
%tokentype { Token }
%error { parseError }
%token
let { TokenLet }
in { TokenIn }
int { TokenInt $$ }
var { TokenVar $$ }
'=' { TokenEq }
'+' { TokenPlus }
'-' { TokenMinus }
'*' { TokenTimes }
'/' { TokenDiv }
'(' { TokenOB }
')' { TokenCB }
%%
Exp : let var '=' Exp in Exp { \p -> $6 (($2,$4 …Run Code Online (Sandbox Code Playgroud) 我正在尝试用x = 4和pritn x实现一些语言,使用haskell构建快乐到目前为止我已经定义了这样的语法
terms
: term { [$1] }
| term terms { $1 : $2 }
term
: var '=' int { Assign $1 $3 }
| print var { Print $2 }
Run Code Online (Sandbox Code Playgroud)
当我在类似的东西上运行时
x = 4
print x
y = 5
print y
Run Code Online (Sandbox Code Playgroud)
我明白了
[Assign "x" 4, Print "x", Assign "y" 5, Print "y"]
Run Code Online (Sandbox Code Playgroud)
现在我想做实际的实现,但我不知道如何实现"分配"
虽然我不擅长哈斯克尔,但是从快乐的文档中我看到"让"实现并且得到了一些环境的概念,并通过了评估
Exp : let var '=' Exp in Exp { \p -> $6 (($2,$4 p):p) }
| Exp1 { $1 }
Exp1 …Run Code Online (Sandbox Code Playgroud) 如果我正在使用lambda表达式,那么在生产规则中快速计算表达式的值是不行的.
例如这段代码
Exp : let var '=' Exp in Exp { \p -> $6 (($2,$4 p):p) }
| Exp1 { $1 }
Exp1 : Exp1 '+' Term { \p -> $1 p + $3 p }
| Exp1 '-' Term { \p -> $1 p - $3 p }
| Term { $1 }
Term : Term '*' Factor { \p -> $1 p * $3 p }
| Term '/' Factor { \p -> $1 p `div` $3 p …Run Code Online (Sandbox Code Playgroud)