所以我试图为单行语句实现一个非常简单的语法:
# 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
我正在使用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 }
一个例子是:“(a)”vs“(a-z)”
词法分析器将为这两种情况提供以下内容:
(a) : [CLBracket, CChar 'a', CRBracket]
(a-z) : [CLBracket, CChar 'a', CHyphen, CChar 'z', CRBracket]
我不明白的是LL [2]解析器是如何模糊的。
如果它有帮助,那么整个快乐语法定义:
{
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"
}
谢谢!
答案 0 :(得分:4)
这是歧义:
token : [...]
| lBracket char rBracket
| [...]
| lBracket listitems rBracket
listitems : char
| [...]
您的解析器可以(v)
和TString [TVowel]
同时接受TString [TList ['v']]
,更不用说case
表达式中缺少的字符。
解决问题的一种可能方法是修改你的语法,使列表至少有两个项目,或者对元音,辅音等有不同的表示法。
答案 1 :(得分:3)
问题似乎是:
| lBracket char rBracket
...
| lBracket listitems rBracket
或更清晰的语法:
(c)
可以是TVowel,TConsonant,TLetter,TNumber(如您所知)或单身TList。
正如快乐手册所说,减少班次通常不是问题。如果你愿意,你可以优先强制行为/删除警告。