2011-06-27 6 views
5

Così sto cercando di implementare un piuttosto semplice grammatica per le dichiarazioni di una sola riga:Ambiguità grammaticale: perché? (Problema è: "(a)" vs "(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 

Sto usando il generatore Felice parser (http : //www.haskell.org/happy/) ma per qualche ragione sembra esserci un problema di ambiguità.

Il messaggio di errore è: "shift/ridurre i conflitti: 1"

Credo che l'ambiguità è con queste due righe:

| lBracket char rBracket    { (\c -> case c of 
               'v' -> TVowel 
               'c' -> TConsonant 
               'l' -> TLetter 
               'n' -> TNumber) $2 } 
    | lBracket char hyphen char rBracket { TRange $2 $4    } 

Un caso ad esempio è: "(a)" vs "(az)"

il lexer darebbe la seguente per i due casi:

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

Quello che non capisco è come questo possa essere ambiguo con un parser LL [2].

In caso aiuta Ecco l'intera definizione della grammatica Felice:

{ 

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" 

} 

Grazie!

risposta

4

Ecco l'ambiguità:

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

listitems : char 
      | [...] 

il parser potrebbe accettare (v) sia come TString [TVowel] e TString [TList ['v']], per non parlare dei caratteri mancanti in quel case espressione.

Un modo per risolverlo sarebbe quella di modificare la grammatica in modo liste sono almeno due prodotti, o hanno qualche notazione diversa per le vocali, le consonanti, ecc

+0

Grazie ... che ha risolto il problema (le liste con un articolo sono comunque inutili in questo caso, quindi le ho rimosse). Ma cosa intendi con la dichiarazione del caso? – o1iver

+0

@ o1iver: Solo che probabilmente si desidera aggiungere un caso predefinito per gestire singoli caratteri che non sono uno di 'v, c,?, L, n' per segnalare un errore più significativo di" Modelli non esaustivi in ​​caso espressione". – hammar

+0

sì, l'ho già avuto, ma non ero sicuro. Penso che mi limiterò a lanciare un errore se ciò accadrà ... Anche se penso che dovrò dare un'occhiata migliore ai documenti Happy riguardanti la gestione degli errori in generale! Grazie ancora... – o1iver

3

Il problema sembra essere:

| lBracket char rBracket 
... 
| lBracket listitems rBracket 

o nella sintassi più pulito:

(c) 

può essere un TVowel, TConsonant, Tletter, tNumero (come sapete) o un Singleton TList.

Come dice il manuale felice, lo spostamento ridotto di solito non è un problema. Puoi avere la precedenza per forzare il comportamento/rimuovere l'avviso, se lo desideri.

+0

Grazie! Stavo cercando nel posto sbagliato. Il problema sembra essere la lista dei singleton rispetto ai caratteri speciali ("(v)", "(n)", ecc ...). Grazie! – o1iver

Problemi correlati