JavaCC Problema - Código generado no encuentra todos los errores de análisis
-
19-09-2019 - |
Pregunta
Acaba de comenzar con JavaCC. Pero tengo un comportamiento extraño con ella. Quiero verificar la entrada int forma de fichas (letras y números) wich se concatenan con los signos (+, -, /) y al que se puede contener paréntesis. Espero que era comprensible:)
En el método principal es una cadena, que debe producir un error, ya que tiene una abertura pero dos paréntesis de cierre, pero no obtiene una excepción de análisis -> ¿Por qué
¿Alguien tiene una idea de por qué no consigo la excepción?
he tenido problemas con la recursividad y la opción que queda entra en conflicto con mi intento inicial, pero logró obtener más de ellos. Tal vez hay introduje el problema?!
Oh - y tal vez mi solución no es muy bueno - ignorar este hecho ... o mejor, dar un consejo ;-)
Archivo: CodeParser.jj
options {
STATIC=false;
}
PARSER_BEGIN(CodeParser)
package com.testing;
import java.io.StringReader;
import java.io.Reader;
public class CodeParser {
public CodeParser(String s)
{
this((Reader)(new StringReader(s)));
}
public static void main(String args[])
{
try
{
/** String has one open, but two closing parenthesis --> should produce parse error */
String s = "A+BC+-(2XXL+A/-B))";
CodeParser parser = new CodeParser(s);
parser.expression();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
PARSER_END(CodeParser)
TOKEN:
{
<code : ("-")?(["A"-"Z", "0"-"9"])+ >
| <op : ("+"|"/") >
| <not : ("-") >
| <lparenthesis : ("(") >
| <rparenthesis : (")") >
}
void expression() :
{
}
{
negated_expression() | parenthesis_expression() | LOOKAHEAD(2) operator_expression() | <code>
}
void negated_expression() :
{
}
{
<not>parenthesis_expression()
}
void parenthesis_expression() :
{
}
{
<lparenthesis>expression()<rparenthesis>
}
void operator_expression() :
{
}
{
<code><op>expression()
}
Editar - 11/16/2009
Ahora me di antlr intentarlo.
He cambiado algunos términos para adaptarse mejor a mi dominio del problema. Se me ocurrió el siguiente código (usando las respuestas en este sitio), lo que parece hacer el trabajo ahora:
grammar Code;
CODE : ('A'..'Z'|'0'..'9')+;
OP : '+'|'/';
start : terms EOF;
terms : term (OP term)*;
term : '-'? CODE
| '-'? '(' terms ')';
Y, por cierto ... ANTLRWORKS es una gran herramienta para la depuración / visualización! me ha ayudado mucho.
Otros detalles adicionales
Por encima de código coincide con cosas como:
(-Z19+-Z07+((FV+((M005+(M272/M276))/((M278/M273/M642)+-M005)))/(FW+(M005+(M273/M278/M642)))))+(-Z19+-Z07+((FV+((M005+(M272/M276))/((M278/M273/M642/M651)+-M005)))/(FW+(M0))))
Solución
¿Qué dice kgregory es la respuesta correcta. Esto se puede ver si se construye la gramática con la opción DEBUG_PARSER y luego ejecute:
$ javacc -debug_parser -output_directory=com/testing/ CodeParser.jj && javac com/testing/*.java && java -cp . com.testing.CodeParser Java Compiler Compiler Version 5.0 (Parser Generator) (type "javacc" with no arguments for help) Reading from file CodeParser.jj . . . File "TokenMgrError.java" is being rebuilt. File "ParseException.java" is being rebuilt. File "Token.java" is being rebuilt. File "SimpleCharStream.java" is being rebuilt. Parser generated successfully. Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 1> Consumed token: <<op>: "+" at line 1 column 2> Call: expression Call: operator_expression Consumed token: <<code>: "BC" at line 1 column 3> Consumed token: <<op>: "+" at line 1 column 5> Call: expression Call: negated_expression Consumed token: <"-" at line 1 column 6> Call: parenthesis_expression Consumed token: <"(" at line 1 column 7> Call: expression Call: operator_expression Consumed token: <<code>: "2XXL" at line 1 column 8> Consumed token: <<op>: "+" at line 1 column 12> Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 13> Consumed token: <<op>: "/" at line 1 column 14> Call: expression Consumed token: <<code>: "-B" at line 1 column 15> Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression Consumed token: <")" at line 1 column 17> Return: parenthesis_expression Return: negated_expression Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression
Vea eso? La última ficha que se consume es el segundo al último carácter - la segunda a la última paréntesis derecho.
Si desea que la excepción, de nuevo, como kgregory dijo, se podría añadir una nueva producción de alto nivel llamado "archivo" o "datos" o algo y al final con un token. De esta manera cualquier colgando parens como esto podría causar un error. Aquí está una gramática que hace eso:
options { STATIC=false; } PARSER_BEGIN(CodeParser) package com.testing; import java.io.StringReader; import java.io.Reader; public class CodeParser { public CodeParser(String s) { this((Reader)(new StringReader(s))); } public static void main(String args[]) { try { /** String has one open, but two closing parenthesis --> should produce parse error */ String s = "A+BC+-(2XXL+A/-B))"; CodeParser parser = new CodeParser(s); parser.file(); } catch(Exception e) { e.printStackTrace(); } } } PARSER_END(CodeParser) TOKEN: { <code : ("-")?(["A"-"Z", "0"-"9"])+ > | <op : ("+"|"/") > | <not : ("-") > | <lparenthesis : ("(") > | <rparenthesis : (")") > } void file() : {} { expression() <EOF> } void expression() : { } { negated_expression() | parenthesis_expression() | LOOKAHEAD(2) operator_expression() | <code> } void negated_expression() : { } { <not>parenthesis_expression() } void parenthesis_expression() : { } { <lparenthesis>expression()<rparenthesis> } void operator_expression() : { } { <code><op>expression() }
Y una ejecución de ejemplo:
$ javacc -debug_parser -output_directory=com/testing/ CodeParser.jj && javac com/testing/*.java && java -cp . com.testing.CodeParser Java Compiler Compiler Version 5.0 (Parser Generator) (type "javacc" with no arguments for help) Reading from file CodeParser.jj . . . File "TokenMgrError.java" is being rebuilt. File "ParseException.java" is being rebuilt. File "Token.java" is being rebuilt. File "SimpleCharStream.java" is being rebuilt. Parser generated successfully. Call: file Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 1> Consumed token: <<op>: "+" at line 1 column 2> Call: expression Call: operator_expression Consumed token: <<code>: "BC" at line 1 column 3> Consumed token: <<op>: "+" at line 1 column 5> Call: expression Call: negated_expression Consumed token: <"-" at line 1 column 6> Call: parenthesis_expression Consumed token: <"(" at line 1 column 7> Call: expression Call: operator_expression Consumed token: <<code>: "2XXL" at line 1 column 8> Consumed token: <<op>: "+" at line 1 column 12> Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 13> Consumed token: <<op>: "/" at line 1 column 14> Call: expression Consumed token: <<code>: "-B" at line 1 column 15> Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression Consumed token: <")" at line 1 column 17> Return: parenthesis_expression Return: negated_expression Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression Return: file com.testing.ParseException: Encountered " ")" ") "" at line 1, column 18. Was expecting: <EOF> at com.testing.CodeParser.generateParseException(CodeParser.java:354) at com.testing.CodeParser.jj_consume_token(CodeParser.java:238) at com.testing.CodeParser.file(CodeParser.java:34) at com.testing.CodeParser.main(CodeParser.java:22)
Voila! Una excepción.
Otros consejos
Desde el de Java CC FAQ :
4.7 añadí una especificación LOOKAHEAD y la advertencia se fue; ¿significa que solucionó el problema?
No. JavaCC no informará advertencias de conflicto opción si utiliza una especificación LOOKAHEAD. El ausencia de una advertencia no quiere decir que has resuelto el problema correctamente, sólo significa que agregó una especificación LOOKAHEAD .
Me gustaría empezar por tratar de deshacerse del conflicto sin necesidad de utilizar una búsqueda hacia delante en primer lugar.
El problema es que usted no recibe el error cuando se utiliza el analizador, correcto? No es que el generador de análisis afirma que la gramática es incorrecta (que parece ser la discusión en la otra respuesta).
Si ese es el caso, entonces sospecho que está viendo el problema porque el analizador coincide correctamente el expresión de producción, a continuación, pasa por alto la entrada posterior. No he utilizado JavaCC durante mucho tiempo, pero IIRC que no generará un error por no llegar al final de la secuencia.
La mayoría de las gramáticas tienen una producción de alto nivel explícito para que coincida con el archivo completo, buscando algo como esto (estoy seguro de que la sintaxis es incorrecta, como ya he dicho, ha sido un largo tiempo):
input : ( expression ) *
O, es probable que haya un token de EOF que se puede utilizar, si se desea procesar sólo una sola expresión.