我正在与Javacc合作为Pascal子集构建解析器。
这是我的代码:
PARSER_BEGIN(Pascal)
import java.io.*;
public class Pascal {
public static void main(String args[]) throws ParseException,IOException {
Pascal parser = new Pascal(new FileInputStream(args[0]));
parser.Programa();
}
}
PARSER_END(Pascal)
SKIP :
{
" "
| "\t"
| "\n"
| "\r"
}
TOKEN :
{
<PROGRAM: "program">
| <INTEIRO: "integer">
| <REAL: "real">
| <VAR: "var">
| <OF: "of">
| <FUNCTION: "function">
| <PROCEDURE: "procedure">
| <LBRACE:"(">
| <RBRACE: ")">
| <SEMI: ";">
| <PTS: ":">
| <BEGIN: "begin">
| <END: "end">
| <ATRIB: ":=">
| <ARRAY: "array">
| <LBRACKETS: "[">
| <RBRACKETS: "]">
| <IF: "if">
| <THEN: "then">
| <ELSE: "else">
| <NOT: "not">
| <PLUS: "+">
| <MINUS: "-">
| <WHILE: "while">
| <DO: "do">
}
TOKEN :
{
<OPERADOR_MULTIPLICATIVO: ("*"|"/"|"div"|"mod"|"and")>
|
<OPERADOR_ADITIVO: ("+"| "-" | "or")>
|
<OPERADOR_RELACIONAL: ("=" | "<>" | "<" | "<=" | ">=" | ">")>
|
<ID: ["a"-"z","A"-"Z"] ( ["a"-"z","A"-"Z","0"-"9"])*>
|
<DIGT: ["0"-"9"] (["0"-"9"])*>
}
void Programa () :
{}
{ <PROGRAM> <ID> <LBRACE> Lista_de_identificadores() <RBRACE> <SEMI>
Declaracoes()
Declara_subprogram()
Enunciado_composto()
<EOF>
}
// lista_de_identificadores
void Lista_de_identificadores():
{}
{
<ID> Lista2()
}
void Lista2():
{}
{
("," <ID> Lista2())?
}
//declarações
void Declaracoes():
{}
{
(<VAR> Lista_de_identificadores() <PTS> Tipo() <SEMI>)*
}
// tipo
void Tipo():
{}
{
(Tipo_padrao() | <ARRAY> <LBRACKETS> <DIGT> <RBRACKETS> <OF> Tipo_padrao())
}
//tipo_padrao
void Tipo_padrao():
{}
{
(<INTEIRO> | <REAL>)
}
//declarações_de_subprogramas
void Declara_subprogram():
{}
{
(Subprogram() <SEMI>)*
}
//declaração_de_subprograma
void Subprogram():
{}
{
Cabecalho_subprogram()
Declaracoes()
Enunciado_composto()
}
//cabeçalho_de_subprograma
void Cabecalho_subprogram():
{}
{
(<FUNCTION> <ID> Argumentos() <PTS> Tipo_padrao() <SEMI>) | (<PROCEDURE> <ID> Argumentos())
}
//argumentos
void Argumentos():
{}
{
(<LBRACE> Lista_parametros() <RBRACE>)?
}
//lista_de_parâmetros
void Lista_parametros():
{}
{
Lista_de_identificadores() <PTS> Tipo() Lista_parametros2()
}
void Lista_parametros2():
{}
{
(<SEMI> Lista_de_identificadores() <PTS> Tipo() Lista_parametros2())?
}
//enunciado_composto
void Enunciado_composto():
{}
{
<BEGIN> Enunciados_opcionais() <END>
}
//enunciados_opcionais
void Enunciados_opcionais():
{}
{
(Lista_enunciados())?
}
//lista_de_enunciados
void Lista_enunciados():
{}
{
Enunciado() (<SEMI> Enunciado())*
}
void Enunciado():
{}
{
LOOKAHEAD(5)(Variavel() <ATRIB> Expressao()) | (Chamada_procedimento()) | (Enunciado_composto()) | (<IF> Expressao() <THEN> Enunciado() <ELSE> Enunciado()) | (<WHILE> Expressao() <DO> Enunciado())
}
void Variavel():
{}
{
LOOKAHEAD(2)(<ID>) | (<ID> <LBRACKETS> Expressao() <RBRACKETS>)
}
void Chamada_procedimento():
{}
{
LOOKAHEAD(2)(<ID>) | (<ID> <LBRACE> Lista_expressoes() <RBRACE>)
}
void Lista_expressoes():
{}
{
Expressao() Lista_expressoes2()
}
void Lista_expressoes2():
{}
{
("," Expressao() Lista_expressoes2())?
}
void Expressao():
{}
{
LOOKAHEAD(2)Expressao_simples() | Expressao_simples() <OPERADOR_RELACIONAL> Expressao_simples()
}
void Expressao_simples():
{}
{
LOOKAHEAD(3)(Termo() Expressao_simples2()) | (Sinal() Termo() Expressao_simples2())
}
void Expressao_simples2():
{}
{
(<OPERADOR_ADITIVO> Termo() Expressao_simples2())?
}
void Termo():
{}
{
Fator() Termo2()
}
void Termo2():
{}
{
(<OPERADOR_MULTIPLICATIVO> Fator() Termo2())?
}
void Fator():
{}
{
LOOKAHEAD(2)(<ID>) | (<ID> <LBRACE> Lista_expressoes() <RBRACE>) | (<DIGT>) | (<LBRACE> Expressao() <RBRACE>) | (<NOT> Fator())
}
void Sinal():
{}
{
(<PLUS> | <MINUS>)
}
这是输入程序:
program exemplo (input, output, test);
var x, y: integer;
function mdc (a, b: integer): integer;
begin
if b = 0 then mdc := a
else mdc := mdc (b, a mod b)
end;
begin
read(x, y);
write(mdc(x,y));
end;
Javacc返回:
Exception in thread "main" ParseException: Encountered " <OPERADOR_RELACIONAL> "= "" at line 5, column 14.
Was expecting one of:
"then" ...
<OPERADOR_MULTIPLICATIVO> ...
<OPERADOR_ADITIVO> ...
<OPERADOR_MULTIPLICATIVO> ...
<OPERADOR_ADITIVO> ...
<OPERADOR_ADITIVO> ...
<OPERADOR_MULTIPLICATIVO> ...
<OPERADOR_ADITIVO> ...
at Pascal.generateParseException(Pascal.java:984)
at Pascal.jj_consume_token(Pascal.java:865)
at Pascal.Enunciado(Pascal.java:270)
at Pascal.Lista_enunciados(Pascal.java:235)
at Pascal.Enunciados_opcionais(Pascal.java:223)
at Pascal.Enunciado_composto(Pascal.java:211)
at Pascal.Subprogram(Pascal.java:137)
at Pascal.Declara_subprogram(Pascal.java:127)
at Pascal.Programa(Pascal.java:20)
at Pascal.main(Pascal.java:9)
问题是,我无法理解为什么Javacc期待这些论点并调用&#34; =&#34;他所处的位置错了。关于这个具体情境的工作部分是这一部分(几乎是完整的代码):
void Enunciado():
{}
{
LOOKAHEAD(5)(Variavel() <ATRIB> Expressao()) | (Chamada_procedimento()) | (Enunciado_composto()) | (<IF> Expressao() <THEN> Enunciado() <ELSE> Enunciado()) | (<WHILE> Expressao() <DO> Enunciado())
}
void Variavel():
{}
{
LOOKAHEAD(2)(<ID>) | (<ID> <LBRACKETS> Expressao() <RBRACKETS>)
}
void Chamada_procedimento():
{}
{
LOOKAHEAD(2)(<ID>) | (<ID> <LBRACE> Lista_expressoes() <RBRACE>)
}
void Lista_expressoes():
{}
{
Expressao() Lista_expressoes2()
}
void Lista_expressoes2():
{}
{
("," Expressao() Lista_expressoes2())?
}
void Expressao():
{}
{
LOOKAHEAD(2)Expressao_simples() | Expressao_simples() <OPERADOR_RELACIONAL> Expressao_simples()
}
void Expressao_simples():
{}
{
LOOKAHEAD(3)(Termo() Expressao_simples2()) | (Sinal() Termo() Expressao_simples2())
}
void Expressao_simples2():
{}
{
(<OPERADOR_ADITIVO> Termo() Expressao_simples2())?
}
void Termo():
{}
{
Fator() Termo2()
}
void Termo2():
{}
{
(<OPERADOR_MULTIPLICATIVO> Fator() Termo2())?
}
void Fator():
{}
{
LOOKAHEAD(2)(<ID>) | (<ID> <LBRACE> Lista_expressoes() <RBRACE>) | (<DIGT>) | (<LBRACE> Expressao() <RBRACE>) | (<NOT> Fator())
}
有人可以弄清楚错误在哪里?我已经尝试了很多东西,但现在看起来对我来说很好(事实上并非如此)。 感谢。
编辑:具有相同名称但最终编号为2的函数用于消除左递归。
答案 0 :(得分:2)
问题是你使用LOOKAHEAD的方式是行不通的。例如,你有
LOOKAHEAD(2)Expressao_simples()
| Expressao_simples() <OPERADOR_RELACIONAL> Expressao_simples()
这就是说,如果下两个输入令牌与Expressao_simples
一致,则采用第一种选择,否则采取第二种选择。显然,在第二种替代方案可能成功的任何情况下,接下来的两个代币也将与第一种替代方案一致,因此将选择第一种代币。
相反,您可以将选择推迟到以后
Expressao_simples()
(
<OPERADOR_RELACIONAL> Expressao_simples()
)?
答案 1 :(得分:1)
我没有可用于测试的特定解析器/生成器,
但似乎奇怪的是解析器似乎与'= '
有关
作为单一的标记。我先调查一下。
如果这没有揭示问题,那么下一步要调查
是您对Expressao_simples
的定义。
我担心调查此类问题的最简单方法有点 痛苦 - 暂时将语法剥离到最简单的情况,请参阅 如果解析器接受了它,如果是,则扩展语法并重新测试 直到你发现问题为止。
换句话说,首先将PROGRAM定义为
PROGRAM : "a" "=" "b"
如果解析器接受了,请尝试
PROGRAM : IDENTIFIER "=" IDENTIFIER
然后
PROGRAM : IDENTIFIER RELATIONALOPERATOR IDENTIFIER
然后
PROGRAM : SIMPLEEXPRESSION RELATIONALOPERATOR SIMPLEEXPRESSION
等。最终,您应该找到导致问题的构造。
我会说“祝你好运!”,但你真的不需要它,只需要很多耐心 和简单的测试用例。