A Very Simple Example Scanner

付録の Scanner の例を bison マニュアルの中間記法電卓で確認

CUP ファイルは、

import java_cup.runtime.*;

terminal         SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD, EXPON, EOL, LPAREN, RPAREN;
terminal         UMINUS;
terminal Integer NUMBER;


non terminal Object  input, line;
non terminal Integer exp;

precedence left  MINUS, PLUS;
precedence left  TIMES, DIVIDE;
precedence left  UMINUS;
precedence right EXPON;

input   ::=
          | input line
          ;

line    ::= EOL
          | exp:e EOL {: System.out.println("\t" + e); :}
          | error EOL
          ;

exp     ::= NUMBER:n              {: RESULT = n; :}
          | exp:e1 PLUS   exp:e2  {: RESULT = new Integer(e1.intValue() + e2.intValue()); :}
          | exp:e1 MINUS  exp:e2  {: RESULT = new Integer(e1.intValue() - e2.intValue()); :}
          | exp:e1 TIMES  exp:e2  {: RESULT = new Integer(e1.intValue() * e2.intValue()); :}
          | exp:e1 DIVIDE exp:e2  {: RESULT = new Integer(e1.intValue() / e2.intValue()); :}
          | MINUS exp:e           {: RESULT = new Integer(-e.intValue()); :}
            %prec UMINUS
          | exp:e1 EXPON exp:e2   {: RESULT = new Integer((int)Math.pow(e1.doubleValue(), e2.doubleValue())); :}
          | LPAREN exp:e RPAREN   {: RESULT = e; :}
          ;

Java ファイル(scanner クラス)は、

import java_cup.runtime.*;

public class scanner implements Scanner {
  /* single lookahead character */
  protected static int next_char;

  /* advance input by one character */
  protected static void advance()
    throws java.io.IOException
    { next_char = System.in.read(); }

  /* initialize the scanner */
  public static void init()
    throws java.io.IOException
    { advance(); }

  /* recognize and return the next complete token */
  public Symbol next_token()
    throws java.io.IOException
    {
      for (;;)
        switch (next_char)
          {
            case '0': case '1': case '2': case '3': case '4': 
            case '5': case '6': case '7': case '8': case '9': 
              /* parse a decimal integer */
              int i_val = 0;
              do {
                i_val = i_val * 10 + (next_char - '0');
                advance();
              } while (next_char >= '0' && next_char <= '9');
            return new Symbol(sym.NUMBER, new Integer(i_val));

            case ';': advance(); return new Symbol(sym.SEMI);
            case '+': advance(); return new Symbol(sym.PLUS);
            case '-': advance(); return new Symbol(sym.MINUS);
            case '*': advance(); return new Symbol(sym.TIMES);
            case '/': advance(); return new Symbol(sym.DIVIDE);
            case '%': advance(); return new Symbol(sym.MOD);
            case '^': advance(); return new Symbol(sym.EXPON);
            case '(': advance(); return new Symbol(sym.LPAREN);
            case ')': advance(); return new Symbol(sym.RPAREN);
            case '\n':advance(); return new Symbol(sym.EOL);

            case -1: return new Symbol(sym.EOF);

            default: 
              /* in this simple scanner we just ignore everything else */
              advance();
            break;
          }
    }
};

Java ファイルは、

import java.io.*;
   
class Main {
    static public void main(String argv[]) {    
        parser p;

        try {
            p = new parser(new scanner());
            Object result = p.parse().value;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

で、

4 + 5 - (34/(8*3+-3))
-56 + 2
3 ^ 2

を標準入力から入力すると、

	8
	-54
	9