1

そのため、byacc/j の if then else と while の定義に問題があります。誰か助けてくれませんか?以下はinput.yです。yacc エラーを理解できません。では、12 のルールが削減されたことがないことは明らかですが、どうすればよいでしょうか?

%{
import java.lang.Math;
import java.io.*;
import java.util.StringTokenizer;
%}

/* YACC Declarations */
%token NUM
%left '-' '+'
%left '*' '/'
%left NEG /* negation--unary minus */
%right '^' /* exponentiation */
%token IF ELSE WHILE EXIT
%token EQ LE GE NE
%token STRING NUM ID

%%

PROGRAM: OPS
;

OPS:    OP
|       OPS OP
;

OP1:    '{' OPS '}'
|       EXPR ';'
|       IF '(' EXPR ')' OP1 ELSE OP1
|       WHILE '(' EXPR ')' OP1
|       EXIT ';'
;

OP2:    IF '(' EXPR ')' OP
|       IF '(' EXPR ')' OP1 ELSE OP2
|       WHILE '(' EXPR ')' OP2
;

OP:     OP1 | OP2 ;

EXPR:   EXPR1
|       ID '=' EXPR

EXPR1:  EXPR2
|       EXPR1 EQ EXPR2
|       EXPR1 LE EXPR2
|       EXPR1 GE EXPR2
|       EXPR1 NE EXPR2
|       EXPR1 '>' EXPR2
|       EXPR1 '<' EXPR2
;

EXPR2: TERM
|       EXPR2 '+' TERM
|       EXPR2 '-' TERM
;

TERM:   VAL
|       TERM '*' VAL
|       TERM '/' VAL
;

VAL:    NUM
|       '-' VAL
|       '!' VAL
|       '(' EXPR ')'
|       ID
|       ID '(' ARGS ')'
;

ARGS:
|       ARG
|       ARGS ',' ARG
;

ARG:    EXPR
|       STRING
;


input: /* empty string */
 | input line
 ;

line: '\n'
 | exp '\n' { System.out.println(" " + $1.dval + " "); }
 ;

exp: NUM { $$ = $1; }
 | exp '+' exp { $$ = new ParserVal($1.dval + $3.dval); }
 | exp '-' exp { $$ = new ParserVal($1.dval - $3.dval); }
 | exp '*' exp { $$ = new ParserVal($1.dval * $3.dval); }
 | exp '/' exp { $$ = new ParserVal($1.dval / $3.dval); }
 | '-' exp %prec NEG { $$ = new ParserVal(-$2.dval); }
 | exp '^' exp { $$ = new ParserVal(Math.pow($1.dval, $3.dval)); }
 | '(' exp ')' { $$ = $2; }
 ;
%%

String ins;
StringTokenizer st;

void yyerror(String s)
{
 System.out.println("par:"+s);
}

boolean newline;
int yylex()
{
String s;
int tok;
Double d;
 //System.out.print("yylex ");
 if (!st.hasMoreTokens())
 if (!newline)
 {
 newline=true;
 return '\n'; //So we look like classic YACC example
 }
 else
 return 0;
 s = st.nextToken();
 //System.out.println("tok:"+s);
 try
 {
 d = Double.valueOf(s);/*this may fail*/
 yylval = new ParserVal(d.doubleValue()); //SEE BELOW
 tok = NUM;
 }
 catch (Exception e)
 {
 tok = s.charAt(0);/*if not float, return char*/
 }
 return tok;
}

void dotest()
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 System.out.println("BYACC/J Calculator Demo");
 System.out.println("Note: Since this example uses the StringTokenizer");
 System.out.println("for simplicity, you will need to separate the items");
 System.out.println("with spaces, i.e.: '( 3 + 5 ) * 2'");
 while (true)
 {
 System.out.print("expression:");
 try
 {
 ins = in.readLine();
 }
 catch (Exception e)
 {
 }
 st = new StringTokenizer(ins);
 newline=false;
 yyparse();
 }
}

public static void main(String args[])
{
 Parser par = new Parser(false);
 par.dotest();
}
4

2 に答える 2

1

.y ファイルに 2 つの独立した文法があるようです: PROGRAMinput. ディレクティブがないため%start、最初の ( PROGRAM) が文法と見なされます。この文法はinputその後の記号を参照しないため、それらはすべて役に立ちません。構文解析時に還元することはできませんPROGRAM

ファイルに含めることができる文法は 1 つだけです。不要な文法は削除 (またはコメントアウト) してください。

于 2012-09-19T18:17:51.687 に答える
0

yacc (OPS) の末尾再帰について忘れていましたが、以下は単純化されているようです。

OPS:    OP RESTOPS
;

RESTOPS: OPS
|      
;

OP:    '{' OPS '}'
|       IF '(' EXPR ')' OP ELSEOP
|       WHILE '(' EXPR ')' OP
|       EXIT ';'
|       EXPR ';'
;

ELSEOP: ELSE OP
|
;
于 2012-06-17T23:14:59.923 に答える