2011-06-27 30 views
5

所以我想實現一個行語句一個非常簡單的語法:語法含糊不清:爲什麼? (問題是:「(一)」與「(AZ)」)

# 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 

我現在用的是快樂解析器發生器(HTTP ://www.haskell.org/happy/),但由於某種原因,似乎存在一些模棱兩可的問題。

的錯誤信息是: 「移/減小衝突: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)中」 與「(AZ)」

詞法分析器將給出兩種情況如下:

(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" 

} 

謝謝!

回答

4

這裏的歧義:

token : [...] 
     | lBracket char rBracket 
     | [...] 
     | lBracket listitems rBracket 

listitems : char 
      | [...] 

解析器可以接受(v)TString [TVowel]TString [TList ['v']],更不用說缺少的字符在case表達。

解決它會修改你的語法所以名單至少有兩個項目,或有元音,輔音一些不同的記號,等

+0

謝謝......解決了這個問題(無論如何,在這種情況下列表中只有一個項目是無用的,所以我刪除了它們)。但你的意思是什麼? – o1iver

+0

@ o1iver:只有你可能想添加一個默認情況來處理不是'v,c,?,l,n'之一的單個字符來表示比「非窮舉模式」更有意義的錯誤表達」。 – hammar

+0

是的,我確實有過,但我不確定。如果發生這種情況,我想我會拋出一個錯誤......雖然我想我將不得不更好地瞭解有關錯誤處理的快樂文檔!再次感謝... – o1iver

3

這個問題似乎是:

| lBracket char rBracket 
... 
| lBracket listitems rBracket 

或更清晰的語法:

(c) 

可以是一個TVowel,TConsonant,TLetter,TNumber(你知道)或單從TList。

正如快樂手冊所言,換班通常不是問題。你可以優先強制行爲/刪除警告,如果你願意。

+0

感謝的一種可能的方式!我在找錯地方。問題似乎是單身人士列表與特殊字符(「(v)」,「(n)」等)。謝謝! – o1iver