刚开始使用JavaCC。但我对它有一种奇怪的行为。我想验证以符号(+, - ,/)连接的标记(字母和数字)形式的输入,并且可以包含括号。 我希望这是可以理解的:)
在main方法中是一个字符串,它应该产生一个错误,因为它有一个开口但有两个右括号,但我没有得到一个解析异常 - >为什么呢?
有没有人知道为什么我没有得到例外?
我在最初的尝试中遇到了左递归和选择冲突,但设法克服了它们。也许在那里我介绍了这个问题?!
哦 - 也许我的解决方案不是很好 - 忽略这个事实......或者更好,给一些建议;-)
文件: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()
}
编辑 - 2009年11月16日
现在我试试了ANTLR。
我更改了一些字词以更好地匹配我的问题域。我想出了以下代码(使用本网站上的答案),现在似乎正在开展工作:
grammar Code;
CODE : ('A'..'Z'|'0'..'9')+;
OP : '+'|'/';
start : terms EOF;
terms : term (OP term)*;
term : '-'? CODE
| '-'? '(' terms ')';
顺便说一下...... ANTLRWORKS是一个很好的调试/可视化工具!帮助了我很多。
其他信息
以上代码与以下内容匹配:
(-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))))
答案 0 :(得分:3)
kgregory所说的是正确的答案。如果使用DEBUG_PARSER选项构建语法然后运行它,则可以看到这一点:
$ 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
看到了吗?消耗的最后一个标记是倒数第二个字符 - 倒数第二个到右括号。
如果您想要例外,再次像kgregory所说的那样,您可以添加一个名为“file”或“data”或类似内容的新顶级产品,并以令牌结束它。这样任何像这样悬挂的parens都会导致错误。这是一个语法:
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() }
示例运行:
$ 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)
瞧!例外。
答案 1 :(得分:1)
问题是你在使用解析器时没有收到错误,对吗?并不是解析器生成器声称语法不正确(这似乎是另一个答案中的讨论)。
如果是这种情况,那么我怀疑你看到了这个问题,因为解析器正确匹配表达式生产,然后忽略后续输入。我已经很长时间没有使用过JavaCC了,但是它并没有因为没有到达流末端而引发错误。
大多数语法都有明确的顶级制作来匹配整个文件,看起来像这样(我确定语法错误,正如我所说,已经很长时间了):
input : ( expression ) *
或者,如果您只想处理一个表达式,可能会使用EOF令牌。
答案 2 :(得分:0)
来自Java CC FAQ:
4.7我添加了LOOKAHEAD规范并且警告消失了;这是否意味着我解决了这个问题?
没有。如果您使用LOOKAHEAD规范,JavaCC将不会报告选择冲突警告。 缺少警告并不意味着您已正确解决问题,仅表示您添加了LOOKAHEAD规范。
我首先试图摆脱冲突,而不是先使用先行。