o1i*_*ver 5 grammar parsing haskell happy
所以我试图为单行语句实现一个非常简单的语法:
# Grammar
c : Character c [a-z0-9-]
(v) : Vowel (= [a,e,u,i,o])
(c) : Consonant
(?) : Any character (incl. number)
(l) : Any alpha char (= [a-z])
(n) : Any integer (= [0-9])
(c1-c2) : Range from char c1 to char c2
(c1,c2,c3) : List including chars c1, c2 and c3
Examples:
h(v)(c)no(l)(l)jj-k(n)
h(v)(c)no(l)(l)(a)(a)(n)
h(e-g)allo
h(e,f,g)allo
h(x,y,z)uul
h(x,y,z)(x,y,z)(x,y,z)(x,y,z)uul
Run Code Online (Sandbox Code Playgroud)
我正在使用Happy parser生成器(http://www.haskell.org/happy/),但由于某种原因,似乎存在一些歧义问题.
错误消息是:"shift/reduce conflicts:1"
我认为模棱两可是这两行:
| lBracket char rBracket { (\c -> case c of
'v' -> TVowel
'c' -> TConsonant
'l' -> TLetter
'n' -> TNumber) $2 }
| lBracket char hyphen char rBracket { TRange $2 $4 }
Run Code Online (Sandbox Code Playgroud)
一个例子是:"(a)"vs"(az)"
词法分析器将为这两种情况提供以下内容:
(a) : [CLBracket, CChar 'a', CRBracket]
(a-z) : [CLBracket, CChar 'a', CHyphen, CChar 'z', CRBracket]
Run Code Online (Sandbox Code Playgroud)
我不明白的是LL [2]解析器是如何模糊的.
如果它有帮助,这里是整个Happy语法定义:
{
module XHappyParser where
import Data.Char
import Prelude hiding (lex)
import XLexer
import XString
}
%name parse
%tokentype { Character }
%error { parseError }
%token
lBracket { CLBracket }
rBracket { CRBracket }
hyphen { CHyphen }
question { CQuestion }
comma { CComma }
char { CChar $$ }
%%
xstring : tokens { XString (reverse $1) }
tokens : token { [$1] }
| tokens token { $2 : $1 }
token : char { TLiteral $1 }
| hyphen { TLiteral '-' }
| lBracket char rBracket { (\c -> case c of
'v' -> TVowel
'c' -> TConsonant
'l' -> TLetter
'n' -> TNumber) $2 }
| lBracket question rBracket { TAny }
| lBracket char hyphen char rBracket { TRange $2 $4 }
| lBracket listitems rBracket { TList $2 }
listitems : char { [$1] }
| listitems comma char { $1 ++ [$3] }
{
parseError :: [Character] -> a
parseError _ = error "parse error"
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
这是歧义之处:
token : [...]
| lBracket char rBracket
| [...]
| lBracket listitems rBracket
listitems : char
| [...]
Run Code Online (Sandbox Code Playgroud)
您的解析器可以接受(v)和TString [TVowel],TString [TList ['v']]更不用说该case表达式中缺少的字符了。
解决这个问题的一种可能的方法是修改你的语法,使列表至少有两个项目,或者对元音、辅音等有一些不同的表示法。
| 归档时间: |
|
| 查看次数: |
307 次 |
| 最近记录: |