0

我正在尝试为简单的语言编写一个解析器,但我到了不知道如何处理这个问题的地步。这是我的.jj 文件

options
{
  STATIC = false;
  LOOKAHEAD=2;
  //DEBUG_LOOKAHEAD = true;
  DEBUG_TOKEN_MANAGER=true;
  FORCE_LA_CHECK = true;
  DEBUG_PARSER = true;
  JDK_VERSION = "1.7";
}

PARSER_BEGIN(Parser)
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException; 

public class Parser{
  private static BufferedWriter bufferFileWriter;
  private static FileWriter fWriter;

  public static void main(String args []) throws ParseException, IOException
  {
    Parser parser = new Parser(System.in);
    fWriter = new FileWriter("result", true);
    bufferFileWriter  = new BufferedWriter(fWriter);
    parser.program();

    // TO DO
  }
}
PARSER_END(Parser)

SKIP :
{
    " "
  | "\r"
  | "\t"
  | "\n"
}

TOKEN : /* OPERATORS */
{
    < PLUS : "+" >
  | < MINUS : "-" >
  | < MULTIPLY : "*" >
  | < DIVIDE : "/" >
  | < MODULO : "%" >
  | < ASSIG : ":=" >
  | < EQUAL : "==" >
  | < DIFF : "!=" >
  | < SMALLER : "<" >
  | < GRATER : ">" >
  | < S_OR_EQU: "<=" >
  | < G_OR_EQU: "=>" > 
}

TOKEN :  /*KEY WORDS FROM LANGUAGE */
{
    < VAR: "VAR">
  | < BEGIN : "BEGIN" >
  | < END : "END" >
  | < IF : "IF" >
  | < ELSE : "ELSE" >
  | < THEN : "THEN" >
  | < WHILE: "WHILE" >
  | < DO : "DO" >
  | < READ : "READ" >
  | < WRITE : "WRITE" >
  | < SEMICOL : ";" >
}

TOKEN :
{
    < VALUE : < ID > | < NUMBER > >
  | < NUMBER : (< DIGIT >)+ >
  | < #DIGIT : [ "0"-"9" ] >
  | < ID : (["a"-"z"])+ >
}

void program():
{}
{
  varDeclarations()< BEGIN > commands() < END >   
}

void varDeclarations():
{}
{
  < VAR >
  {
    System.out.println("past VAR token");
  }

  (< ID >
  )+
}
void commands():
{}
{ 
  (LOOKAHEAD(3)
    command())+
}

void command():
{
  Token t;
}
{
  assign()
    |< IF >condition()< THEN >commands()< ELSE >commands()< END >
    |< WHILE >condition()< DO >commands()< END >
    |< READ >
    t=< ID >
    {
      try
      {
        fWriter.append("LOAD "+t.image);
        System.out.println("LOAD "+t.image);
      }
      catch(IOException e)
      {
      };
    }
    < SEMICOL >

    |< WRITE >
        t = < VALUE >< SEMICOL >

}
void assign():
{
  Token t;
}
{
  t=< ID >
  {
  }
  < ASSIG >expression(t)< SEMICOL >
}
void condition():
{}
{
    < VALUE > condOperator() < VALUE >
}
void condOperator():
{}
{
  < EQUAL > | < DIFF > | < SMALLER > | < S_OR_EQU > | < GRATER > | < G_OR_EQU >
}
Token operator():
{
  Token tok;
}
{
  tok=< PLUS >
  {
    System.out.println(tok.image);
    return tok;
  }
  |tok=< MINUS >
  {
    System.out.println(tok.image);
    return tok;
  }
  |tok=< MULTIPLY >
  {
    System.out.println(tok.image);
    return tok;
  }
  |tok=< DIVIDE >
  {
    System.out.println(tok.image);
    return tok;
  }
  |tok=< MODULO >
  {
    System.out.println(tok.image);
    return tok;
  }
} 
void expression(Token writeTo):
{
  Symbol s;
  Token t1, t2, t3;
}
{
  t1 = < VALUE >
  t2 = operator()
  t3 = < VALUE >
  < SEMICOL >
{
  if(t2.image.equals("+"))
  {
    try
    {   
      fWriter.append("ADD "+t1.image+" "+t2.image);
      System.out.println("ADD "+t1.image+" "+t2.image);
    }catch(IOException e)
    {
    }
  }
}
}

此时写入文件并不重要。

这是我要解析的文本:

VAR
a b
BEGIN
  READ a ;
  READ b ;
  WHILE a != b DO
    IF a < b THEN (* a <-> b *)
      a := a + b ;
      b := a - b ;
      a := a - b ;
    ELSE
    END
    a := a - b ;
  END
  WRITE a ;
END

这是我从调试器得到的输出:

mother-ship $ java Parser test
Call:   program
Call:   varDeclarations

如您所见,解析器输入了 varDeclaration 方法,但为什么他不能将令牌与单词 VAR 匹配?
我将不胜感激任何帮助。

@Theodore 我按照你的建议做了,但是没有用。也许我以错误的方式编译和执行程序?这是我的控制台的副本:

$javacc Parser.jj  
Java Compiler Compiler Version 5.0 (Parser Generator)  
(type "javacc" with no arguments for help)  
Reading from file Parser.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.  
$ javac *.java  
$ java Parser VAR a  
Call:   program  
Call:   varDeclarations
4

1 回答 1

1

我让您的解析器识别“VAR”关键字没有问题。问题是“a”被标记为“VALUE”标记,而解析器在“VAR”关键字之后需要一个“ID”标记。(见下面的输入和输出。)

VALUE' has precedence over the rule forID`的规则,因为是第一。(参见常见问题解答中的问题 3.3。)

您可能应该做的是将您现在VALUE拥有的规则替换为以下规则。

void Value() : {} { <ID> | <NUMBER> }

输入:

VAR
a

输出:

Call:   program
  Call:   varDeclarations
Current character : V (86) at line 1 column 1
   Possible string literal matches : { "VAR" } 
Current character : A (65) at line 1 column 2
   Possible string literal matches : { "VAR" } 
Current character : R (82) at line 1 column 3
   No more string literal token matches are possible.
   Currently matched the first 3 characters as a "VAR" token.
****** FOUND A "VAR" MATCH (VAR) ******

    Consumed token: <"VAR" at line 1 column 1>
past VAR token
Skipping character : \n (10)
Current character : a (97) at line 2 column 1
   No string literal matches possible.
   Starting NFA to match one of : { <VALUE> }
Current character : a (97) at line 2 column 1
   Currently matched the first 1 characters as a <VALUE> token.
   Possible kinds of longer matches : { <VALUE>, <ID> }
Current character : \n (10) at line 2 column 2
   Currently matched the first 1 characters as a <VALUE> token.
   Putting back 1 characters into the input stream.
****** FOUND A <VALUE> MATCH (a) ******

  Return: varDeclarations
Return: program
Exception in thread "main" tokenNotMatched.ParseException: Encountered " <VALUE> "a "" at line     2, column 1.
Was expecting:
   <ID> ...
于 2013-06-05T18:49:50.707 回答