2011-06-27 24 views
5

Yani tek satırlık ifadeleri için oldukça basit dilbilgisi uygulamak çalışıyorum:Dilbilgisi muğlaklığı: neden? (Sorundur: "(a)" "(az)" vs)

# 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 

Ben Mutlu ayrıştırıcı jeneratör kullanıyorum (http : //www.haskell.org/happy/) ama bir sebepten dolayı bazı belirsizlik problemleri var gibi görünüyor.

hata mesajı şöyledir: "shift/çatışmaları azaltmak: 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    } 

bir örnek durumdur: "(a)" vs Ben belirsizlik bu iki çizgi ile olduğunu düşünüyorum

"(az)"

lexer verecekti iki durum için aşağıdaki:

(a) : [CLBracket, CChar 'a', CRBracket] 
(a-z) : [CLBracket, CChar 'a', CHyphen, CChar 'z', CRBracket] 

Anlamadığım şey, bunun bir LL [2] ayrıştırıcısıyla nasıl belirsiz olabileceğidir.

{ 

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" 

} 

teşekkür ederiz: burada yardımcı durumda

tüm Mutlu dilbilgisi tanımıdır!

cevap

4

İşte belirsizlik var:

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

listitems : char 
      | [...] 

Sizin ayrıştırıcı değil case ifadede eksik karakterleri söz, TString [TVowel] ve TString [TList ['v']] hem de (v) kabul edebilirim.

vb listelediği en az iki ürün vardır böylece dilbilgisi değiştirmek veya ünlülerin, ünsüzler için bazı farklı gösterim yapılmadı olacaktır

+0

Teşekkürler ... problemi çözdüm (bir öğe olan listeler zaten bu durumda işe yaramaz, bu yüzden onları kaldırdım). Ama durum beyanı ile ne demek istiyorsun? – o1iver

+0

@ o1iver: Yalnızca, "v, c,?, L, n" olmayan tek karakterleri işlemek için varsayılan bir durum eklemek isteyebilirsiniz. ifadesi". – hammar

+0

evet bunu daha önce yaptım, ama emin değildim. Sanırım bu bir hata yaparsam ... Eğer sanırım genel olarak hataların ele alınması ile ilgili mutlu dokümanlara daha iyi bakmam gerekecek! Tekrar teşekkürler... – o1iver

3

sorun olarak görünmektedir:

| lBracket char rBracket 
... 
| lBracket listitems rBracket 

veya temizleyici sözdiziminde

:

(c) 

bir TVowel, TConsonant, tletter, TNumber (bildiğiniz gibi) ya da bir tekil tlist olabilir.

Mutlu el kitabının dediği gibi, vardiya küçültme genellikle bir sorun değildir. İsterseniz davranışı zorlamak/uyarmayı kaldırmak için öncelikli olabilirsiniz.

+0

Teşekkür çözme olası bir yolu! Yanlış yere bakıyordum. Sorun, tekil liste vs özel chars ("(v)", "(n)", vs ...) gibi görünüyor. Teşekkür ederim! – o1iver