如何用Jflex在Bison中表达语法规则

问题描述 投票:0回答:1

我一直在尝试制作一个从词法分析器(jflex)获取标记的解析器,并且我使用 Java 和 bison 作为解析器。这是到目前为止我的解析器代码:

%define api.prefix {EXAMPLE}
%define api.parser.class {EXAMPLE}
%define api.parser.public
%define parse.error verbose

%code imports{
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.io.IOException;
}

%code {
  public static void main(String args[]) throws IOException {
    EXAMPLELexer lexer = new EXAMPLELexer(System.in);
    EXAMPLE parser = new EXAMPLE(lexer);
    if(parser.parse()){
      System.out.println("VALID FROM PARSER");
    }
    else{
      System.out.println("ERROR FROM PARSER");
    }
      
    return;
  }
}

/* Bison Declarations */
%token <Integer> NUM
%type exp
%%

input: line | input line;
line: '\n'
| exp '\n' { System.out.println($exp); }
| error '\n'
;
exp:
 NUM { $$ = $1; }
| exp '=' exp { if ($1.intValue() != $3.intValue()) yyerror("calc: error: " + $1 + " != " + $3); }
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
| exp '*' exp { $$ = $1 * $3; }
| exp '/' exp { $$ = $1 / $3; }
| '-' exp %prec NEG { $$ = -$2; }
| exp '^' exp { $$ = (int) Math.pow($1, $3); }
| '(' exp ')' { $$ = $2; }
| '(' error ')' { $$ = 1111; }
| '!' { $$ = 0; return YYERROR; }
| '-' error { $$ = 0; return YYERROR; }

%%

class EXAMPLELexer implements EXAMPLE.Lexer {
  InputStreamReader it;
  Yylex yylex;

  public EXAMPLELexer(InputStream is){
    it = new InputStreamReader(is);
    yylex = new Yylex(it);
  }

  @Override
  public void yyerror (String s){
   
  }

  @Override
  public Object getLVal() {
    return null;
  }

  @Override
  public int yylex () throws IOException{
    return yylex.yylex();
  }
}

当我尝试使用 jflex 和 bison 命令时,我得到以下信息: $$ of ‘exp’ has no declared type, same with $1, $3

请帮忙,我已经被这个问题困扰了一段时间了! (p.s 我已经尝试过 %union{} ,不幸的是,它只是引发了更多错误,如果您有任何实际可以使用它的示例代码,我很乐意学习,因为似乎缺乏 Java 文档和 bison 与 Jflex 合作。)

java parsing bison lex jflex
1个回答
0
投票

exp 没有声明类型。 此外,代币 NEG 并未声明。

%token <String> NEG
%type<Object> exp

词法分析器接口需要在 %code lexer { } 中声明;块,在 %% 解析器结束标记之前。

按照您的文件示例,这里是 example.y

%language "Java"
%define api.prefix {EXAMPLE}
%define api.parser.class {EXAMPLE}
%define api.parser.public
%define parse.error verbose

%code imports{
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.io.IOException;
}

%code {
  public static void main(String args[]) throws IOException {
    EXAMPLELexer lexer = new EXAMPLELexer(System.in);
    EXAMPLE parser = new EXAMPLE(lexer);
    if(parser.parse()){
      System.out.println("VALID FROM PARSER");
    }
    else{
      System.out.println("ERROR FROM PARSER");
    }
      
    return;
  }
}

/* Bison Declarations */
%token <Integer> NUM
%token <String> NEG
%type<Object> exp
%%

input: line | input line;
line: '\n'
| exp '\n' { System.out.println($exp); }
| error '\n'
;
exp:
 NUM { $$ = Integer.parseInt($1); }
| exp '=' exp { if ($1.intValue() != $3.intValue()) yyerror("calc: error: " + $1 + " != " + $3); }
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
| exp '*' exp { $$ = $1 * $3; }
| exp '/' exp { $$ = $1 / $3; }
| '-' exp %prec NEG { $$ = -$2; }
| exp '^' exp { $$ = (int) Math.pow($1, $3); }
| '(' exp ')' { $$ = $2; }
| '(' error ')' { $$ = 1111; }
| '!' { $$ = 0; return YYERROR; }
| '-' error { $$ = 0; return YYERROR; }

%code lexer {

private EXAMPLELexer lexer;

private Object yylval;

public YYLexer (EXAMPLELexer elexer)
{
    lexer = elexer;
}

@Override
public void yyerror (String s) {

}

@Override
public Object getLVal() {
    return yylval;
}

@Override
public int yylex () throws IOException {
    int v = lexer.scan();
    yylval = lexer.getValue();
    return v;
}

};

%%

这是示例的开始。jf

import java.util.*;
import java.io.InputStreamReaader;

import static EXAMPLE.*;

%%

%class EXAMPLELexer 
%integer
%unicode

%{

EXAMPLELexer(InputStream ios) {
    this (new InputStreamReader(ios));
}
    String lexeme;

    private void setValue(String val)
    {
        lexeme = val;
    }

    public String getValue()
    {
        return lexeme;
    }

%}

INTNUM = ([0-9]*)

%%

{INTNUM} { setValue( yytext() ); return EXAMPLE.Lexer.NUM; }
© www.soinside.com 2019 - 2024. All rights reserved.