Estoy creando un DSL y utilizando la biblioteca del combinador del analizador de Scala para analizar el DSL. El DSL sigue una sintaxis simple similar a Ruby. Una fuente puede contener una serie de bloques que se ven así:¿Cómo puedo crear un combinador de analizador en el que las terminaciones de línea son importantes?
create_model do
at 0,0,0
end
Los finales de línea son significativos en el DSL, ya que se utilizan efectivamente como terminadores comunicado.
me escribió un analizador Scala que tiene este aspecto:
class ML3D extends JavaTokenParsers {
override val whiteSpace = """[ \t]+""".r
def model: Parser[Any] = commandList
def commandList: Parser[Any] = rep(commandBlock)
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"
def eol: Parser[Any] = """(\r?\n)+""".r
def command: Parser[Any] = commandName~opt(commandLabel)
def commandName: Parser[Any] = ident
def commandLabel: Parser[Any] = stringLiteral
def statementList: Parser[Any] = rep(statement)
def statement: Parser[Any] = functionName~argumentList~eol
def functionName: Parser[Any] = ident
def argumentList: Parser[Any] = repsep(argument, ",")
def argument: Parser[Any] = stringLiteral | constant
def constant: Parser[Any] = wholeNumber | floatingPointNumber
}
Desde finales de línea de asunto, me hicieron caso omiso whiteSpace
de modo que sólo va a tratar espacios y tabulaciones como espacios en blanco (en lugar de tratar nuevas líneas como espacios en blanco, y así ignorarlos).
Esto funciona, a excepción de la declaración "final" para commandBlock
. Como mi archivo de origen contiene una línea nueva, el analizador se queja de que esperaba solo un end
pero obtuvo una nueva línea después de la palabra clave end
.
Así que cambió la definición commandBlock
's a esto:
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"~opt(eol)
(Es decir, he añadido una nueva línea opcional después de "final").
Pero ahora, al analizar el archivo de origen, me sale el siguiente error:
[4.1] failure: `end' expected but `' found
I que esto se debe a que, después de que chupa la nueva línea de salida, el analizador está encontrando una cadena vacía que piensa que no es válido, pero no estoy seguro de por qué lo está haciendo.
¿Algún consejo sobre cómo solucionar esto? Podría extender el analizador incorrecto desde la biblioteca del combinador de analizadores de Scala, por lo que cualquier sugerencia sobre cómo crear una definición de lenguaje con nuevos caracteres de línea significativos también es bienvenida.
Me gusta su interpretación del mensaje de error. Me pregunto si hay una manera de hacer que el analizador imprima lo que intenta igualar a medida que avanza. Eso facilitaría la resolución de problemas. – huynhjl
Puede ajustar cualquier referencia a una producción que aparezca en el lado derecho de otra producción en 'log (...)' y obtendrá un resultado de rastreo siempre que el análisis intente hacer coincidir ese no terminal. Por ejemplo, para registrar un intento particular de emparejar 'modelo', reemplace esa referencia no terminal en una regla con' log (modelo) '. –
Ah, sí, veo el problema ahora - 'end' se leía bajo' functionName', ya que * era * un nombre de función válido. Implementé tus cambios y funciona bien ahora, muchas gracias. – mipadi