2011-06-27 18 views
5

Así que estoy tratando de poner en práctica una gramática muy simple para las declaraciones de una sola línea:Ambigüedad gramatical: ¿por qué? (Problema es: "(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 

Estoy utilizando el generador de feliz analizador (http : //www.haskell.org/happy/) pero por alguna razón parece haber algún problema de ambigüedad.

El mensaje de error es: "cambio/reducir los conflictos: 1"

Creo que la ambigüedad es con estas dos líneas:

| 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 de ejemplo es: "(a)" Vs "(az)"

el lexer daría la siguiente para los dos casos:

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

Lo que no entiendo es cómo esto puede ser ambiguo con un analizador LL [2].

En caso de que ayuda aquí es la definición completa de la gramática feliz:

{ 

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" 

} 

Gracias!

Respuesta

4

Aquí está la ambigüedad:

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

listitems : char 
      | [...] 

Su analizador podía aceptar (v) ya que tanto TString [TVowel] y TString [TList ['v']], por no hablar de los personajes que faltan en que case expresión.

Una posible manera de resolverlo sería modificar su gramática tan listas son al menos dos artículos, o tienen alguna notación diferente para las vocales, las consonantes, etc.

+0

Gracias ... eso resolvió el problema (de todos modos, las listas con un elemento son inútiles en este caso, así que las eliminé). Pero, ¿qué quieres decir con la declaración del caso? – o1iver

+0

@ o1iver: solo que probablemente quiera agregarle un caso predeterminado para manejar caracteres individuales que no son uno de 'v, c,?, L, n' para señalar un error más significativo que" Patrones no exhaustivos en el caso expresión". – hammar

+0

sí, ya lo tenía antes, pero no estaba seguro. Creo que lanzaré un error si eso sucede ... Aunque supongo que tendré que echar un vistazo a los documentos de Happy relacionados con el manejo de errores en general. Gracias de nuevo... – o1iver

3

El problema parece ser:

| lBracket char rBracket 
... 
| lBracket listitems rBracket 

o en la sintaxis más limpia:

(c) 

puede ser un TVowel, TConsonant, tletter, TNumber (como saben) o un producto único TList.

Como dice el manual feliz, la reducción de desplazamiento generalmente no es un problema. Puedes priorizarnos para forzar el comportamiento/eliminar la advertencia si lo deseas.

+0

Gracias! Estaba buscando en el lugar equivocado. El problema realmente parece ser la lista singleton frente a los caracteres especiales ("(v)", "(n)", etc ...). ¡Gracias! – o1iver

Cuestiones relacionadas