bison マニュアルの多機能電卓

自前 Scanner で

%{

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

class Obj {
  public String name;
  public int    type;
  public double val;

  Obj(String s, int t, double v) {
    name = s; type = t; val = v;
  }
}

public class Test {

%}

%token NUM
%type <Double> exp NUM
%token <Obj> VAR FNCT   /* 変数と関数 */

%right '='
%left '-' '+'
%left '*' '/'
%left NEG     /* negation--単項マイナス */
%right '^'    /* べき乗関数        */

%%

input:    /* 空 */
        | input line
;

line:     '\n'
        | exp   '\n' { System.out.println("\t" + $1); }
        | error '\n' { yyErrorFlag = 0; }
;

exp:      NUM                { $$ = new Double($1.doubleValue());  }
        | VAR                { $$ = new Double($1.val);            }
        | VAR '=' exp        { $$ = new Double($3.doubleValue()); $1.val = $3.doubleValue(); }
        | FNCT '(' exp ')'   { $$ = new Double(func($1.name, $3.doubleValue()));        }
        | exp '+' exp        { $$ = new Double($1.doubleValue() + $3.doubleValue());    }
        | exp '-' exp        { $$ = new Double($1.doubleValue() - $3.doubleValue());    }
        | exp '*' exp        { $$ = new Double($1.doubleValue() * $3.doubleValue());    }
        | exp '/' exp        { $$ = new Double($1.doubleValue() / $3.doubleValue());    }
        | '-' exp  %prec NEG { $$ = new Double(-$2.doubleValue());        }
        | exp '^' exp        { $$ = new Double(Math.pow($1.doubleValue(), $3.doubleValue())); }
        | '(' exp ')'        { $$ = new Double($2.doubleValue());         }
;

%%

  private static Map sym = new HashMap();

  private static void init_table() {
    putsym("sin",  FNCT);
    putsym("cos",  FNCT);
    putsym("atan", FNCT);
    putsym("ln",   FNCT);
    putsym("exp",  FNCT);
    putsym("sqrt", FNCT);
  }

  public static Obj putsym(String sym_name, int sym_type) {
    Obj x = new Obj(sym_name, sym_type, 0);
    sym.put(sym_name, x);

    return x;
  }

  public static Obj getsym(String sym_name) {
    if (sym.containsKey(sym_name)) {
      return (Obj)sym.get(sym_name);
    } else {
      return null;
    }
  }

  private double func(String sym_name, double v) {
    if (sym_name == "sin") {
      return Math.sin(v);
    } else if (sym_name == "cos") {
      return Math.cos(v);
    } else if (sym_name == "atan") {
      return Math.atan(v);
    } else if (sym_name == "ln") {
      return Math.log(v);
    } else if (sym_name == "exp") {
      return Math.exp(v);
    } else if (sym_name == "sqrt") {
      return Math.sqrt(v);
    } else {
      return 0;
    }
  }

  public static void main (String args []) {
    init_table();

    Scanner scanner = new Scanner();
    try {
      new Test().yyparse(scanner);
    } catch (IOException ie) { ie.printStackTrace(); }
      catch (yyException ye) { System.err.println(ye); }
  }

}


class Scanner implements Test.yyInput {
  private int ch = 0;

  public Scanner() {
  }

  public boolean advance() throws IOException {
    return true;
  }

  public int token() {
    value = null;
    int n = 0;
    char[] buf = new char[100];

    for (;;) {
      int c = getch();
      if (c < 0)
        return 0;
      else if (c == ' ' || c == '\t')
        ;
      else if (Character.isDigit((char)c) || c == '.') {
        while (Character.isDigit((char)c) || c == '.') {
          buf[n++] = (char)c;
          if (c == '.') break;
          c = getch();
        }
        if (c == '.') {
          c = getch();
          while (Character.isDigit((char)c)) {
            buf[n++] = (char)c;
            c = getch();
          }
        }
        ungetch(c);
        if (n == 1 && buf[0] == '.') {
          return '.';
        } else {
          value = new Double(new String(buf, 0, n));
          return Test.NUM;
        }
      } else if (Character.isJavaIdentifierStart((char)c)) {
        buf[n++] = (char)c;
        c = getch();
        while (Character.isJavaIdentifierPart((char)c)) {
          buf[n++] = (char)c;
          c = getch();
        }
        ungetch(c);
  
        String sym = new String(buf, 0, n);
        Obj s = Test.getsym(sym);
        if (s == null) {
          s = Test.putsym(sym, Test.VAR);
        }
        value = s;
        return s.type;
      }
      else
        return c;
    }
  }

  protected Object value;

  public Object value() {
    return value;
  }

  private int getch() {
    int c = ch;
    if (c != 0) {
      ch = 0;
      return c;
    }
    try {
      return System.in.read();
    } catch (java.io.IOException e) {
      throw new Error(e.getMessage());
    }
  }

  private void ungetch(int c) { ch = c; }
}

で、

pi = 3.141592653589
	3.141592653589
sin(pi)
	7.932657934721266E-13
alpha = beta1 = 2.3
	2.3
alpha
	2.3
ln(alpha)
	0.8329091229351039
exp(ln(beta1))
	2.3

「char[] buf = new char[100];」は直した方が良いけど…