2008-11-02 8 views
6

que estoy haciendo ejercicios analizador de combinadores de Cay Horstmann, me pregunto cuál es la mejor manera de distinguir entre cadenas que representan los números y las cadenas que representan las variables en un comunicado partido:analizadores combinator Scala - Distinguir entre cadenas de números y cadenas de variables

def factor: Parser[ExprTree] = (wholeNumber | "(" ~ expr ~ ")" | ident) ^^ { 
    case a: wholeNumber => Number(a.toInt) 
    case a: String => Variable(a) 
} 

La segunda línea allí, "case a: wholeNumber" no es legal. Pensé en una expresión regular, pero no he encontrado la manera de que funcione con "caso".

Respuesta

6

Lo dividiría un poco e insertaría el análisis de caso en el |. Esta es una de las ventajas de combinadores y análisis realmente LL (*) en general:

def factor: Parser[ExprTree] = (wholeNumber ^^ { Number(_.toInt) } 
           | "(" ~> expr <~ ")" 
           | ident ^^ { Variable(_) }) 

Me disculpo si no está familiarizado con la sintaxis de los guiones. Básicamente significa "sustituir el parámetro n por el valor de la función adjunta". Por lo tanto, { Variable(_) } es equivalente a { x => Variable(x) }.

Otro poco de magia de sintaxis aquí es los operadores ~> y <~ en lugar de ~. Estos operadores significan que el análisis sintáctico de ese término debe incluir la sintaxis de ambas parens, pero el resultado debe determinarse únicamente por el resultado de expr. Por lo tanto, "(" ~> expr <~ ")" coincide exactamente con lo mismo que "(" ~ expr ~ ")", pero no requiere el análisis de caso adicional para recuperar el valor de resultado interno de expr.

+0

¡Excelente! Tuve que cambiar {Number (_. ToInt)} a {x: String => Number (x)} porque obtuve "error: tipo de parámetro faltante para la función expandida", entonces funcionó como un amuleto. Todavía tiene curiosidad si hay una forma de resolverlo en clase de caso. –

+0

Bueno, en realidad el caso solo define una función parcial. Te permite hacer una coincidencia de patrones en la entrada, que es realmente la razón por la cual es útil. También podría haber escrito mi respuesta usando funciones parciales (caso), simplemente no era necesario. :-) (lo hubiera sido, excepto para ~> y <~) –

+0

Si quiere decir que coinciden en todo el término, creo que la respuesta es "no, no hay forma de hacerlo". A menos que el método 'wholeNumber' devuelva un analizador con un tipo de componente diferente de String, realmente no hay forma de diferenciarlo de' ident' o incluso "(" ~> expr <~ ")". –

Cuestiones relacionadas