2015년 8월 22일 토요일

java로 만드는 계산기 javaCC 사용



java에서 계산기 만들기

https://javacc.java.net/

https://java.net/projects/javacc/downloads/directory/releases/Release%206.1.2

구문 분석에 관련 참고
http://crystalcube.co.kr/149

javacc받아서 압축풀어서 설치

계산기 jj 파일 검색해서 받았습니다.
이걸 바탕으로 수정해나가도록 하겠습니다.
http://read.pudn.com/downloads197/sourcecode/compiler/927244/%E7%A8%8B%E5%BA%8F%E6%BA%90%E7%A0%81%E5%8F%8A%E7%94%9F%E6%88%90%E7%9A%84java%E5%92%8Cclass%E6%96%87%E4%BB%B6/calculator.jj__.htm


makepath.bat 의 내용
set PATH=%PATH%;C:\Program Files\Java\jdk1.8.0_25\bin

build.bat
java -classpath javacc-6.1.2.jar javacc allcalc.jj
javac calculator.java
java calculator




D:\work\개인\Work\android\allcalc>build.bat

D:\work\개인\Work\android\allcalc>java -classpath javacc-6.1.2.jar javacc allcal
c.jj
Java Compiler Compiler Version 6.1_2 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file allcalc.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.

D:\work\개인\Work\android\allcalc>javac calculator.java

D:\work\개인\Work\android\allcalc>java calculator
This is an advanced calculator based on the prior .jj embeded in eclipse
Enter an expression like "2.0+3.4 " we support +,-,*,\,(),sin(),cos(),and number
 with fraction:10+34
44.0
0.1231*23123
2846.4413
231+!2312
Oops.
Lexical error at line 3, column 5.  Encountered: "!" (33), after : ""


jj파일 중 일부 token 정의 하는 부분이있는데 #표시에 대한 설명
|   < NUMBER : <DIGITS> | <DIGITS> "." <DIGITS> | <DIGITS> "." | "."<DIGITS> >
|   < #DIGITS : (["0"-"9"])+ >  

When the "#" is present, the regular expression is referred to as a "private regular expression".
private으로 사용하는 토큰이 됩니다. 즉 어디서나 사용못하고 다른 토큰의 정의를 표현할때 사용한다는 의미입니다.


long 처리
http://www.tutorialspoint.com/java/lang/long_parselong_radix.htm


날짜처리 관련
http://www.yunsobi.com/blog/325


정규식
http://regexr.com/

java 용 변환
http://www.regexplanet.com/advanced/java/index.html


" 처리

http://stackoverflow.com/questions/24156948/javacc-quote-with-escape-character
http://crystalcube.co.kr/111
http://stackoverflow.com/questions/11878392/parsing-strings-with-javacc


지금까지 작업된 소스는 아래와 같습니다.
java에서 testcase로 개발한 소스
주된 내용은 DLValue라는 class 입니다.
float형과 long형의 리턴값을 하나로 관리하기 위한 클래스 입니다.


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import junit.framework.TestCase;


public class CalcTest extends TestCase{
 
 public class DLValue {
  double floatValue;
  long   intValue;
  boolean bIsFloat;
  boolean bIsDate;
  boolean bIsError;
  boolean bIsBitOverflow;
  String errorString;

  public DLValue()
  {
   init();
  }
  
  public DLValue(long value)
  {
   set(value);
  }

  public DLValue(int value)
  {
   set(value);
  }

  public DLValue(float value)
  {
   set(value);
  }

  public DLValue(double value)
  {
   set(value);
  }
  
  public void init()
  {
   floatValue = 0.0;
   intValue = 0;
   bIsFloat = true;
   bIsDate = false;
   bIsError = false;
   errorString = "";
   bIsBitOverflow = false;
  }
  
  public void setLong(boolean value)
  {
   bIsFloat = value;
  }
  public void set(long value)
  {
   intValue = value;
   bIsFloat = false;
  }
  public void set(int value)
  {
   intValue = (long)value;
   bIsFloat = false;
  }

  public void set(float value)
  {
   floatValue = (double)value;
   bIsFloat = true;
  }

  public void set(double value)
  {
   floatValue = value;
   bIsFloat = true;
  }
  public boolean getIsFloat()
  {
   return bIsFloat;
  }
  
  public void sync()
  {
   if( !bIsFloat ){
    floatValue = intValue;
   }else{
    intValue = (long)floatValue;
   }
  }
  
  public void upSync()
  {
   sync();
   if( !bIsFloat ){
    bIsFloat = true;
    bIsDate = false;
   }
  }
  public void up()
  {
   bIsDate = false;
   bIsFloat = true;
  }
  public void down()
  {
   bIsFloat = false;
  }
  public double getFloatValue()
  {
   return floatValue;
  }
  
  public long getIntValue()
  {
   return intValue;
  }
  
  public void print()
  {
   if( bIsError ){
    System.out.println("Error:"+errorString);
    return;
   }
   if( bIsBitOverflow ){
    System.out.println("Overflow:"+errorString);
   }
   if( bIsFloat ){
    System.out.println(getFloatValue());
   }else{
    System.out.println(getIntValue());
    if( bIsDate ){
     SimpleDateFormat dateFormat = new  SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     dateFormat.setTimeZone(TimeZone.getTimeZone( "GMT+0" ));
     Date date = new Date(getIntValue());
     String strDate = dateFormat.format(date);
     System.out.println(strDate);
    }
   }
  }
  
  public DLValue parse(String str)
  {
   long valuelong = 0;
   double valuedouble = 0.0;
   int radix = 10;
   String newstr = str;
   if(str.length() > 2 && str.charAt(0)=='0' && str.charAt(1)=='x' ){
    newstr = str.substring(2,str.length());
    radix = 16;
    newstr = newstr.trim().replaceAll(" ", "");
    newstr = newstr.replaceAll("\\p{Z}", "");
   }else if(str.length()>1 && str.charAt(str.length()-1)=='b'){
    // remove a last 'b' char 
    newstr = str.substring(0,str.length()-1);
    radix = 2;
    newstr = newstr.trim().replaceAll(" ", "");
    newstr = newstr.replaceAll("\\p{Z}", "");
   }
   if( radix == 10 ){
    try{
     valuelong = Long.parseLong(newstr, radix);
     set(valuelong);
     return new DLValue(valuelong);
    }catch(NumberFormatException nfe){
     try{
      valuedouble = Double.parseDouble(newstr);
     }catch(NumberFormatException nfe2){
      errorString = "NumberFormatException";
      bIsError = true;
      return new DLValue(0);
     }
     set(valuedouble);
     return new DLValue(valuedouble);
    }
   }else{
    try{
     valuelong = Long.parseLong(newstr, radix);
    }catch(NumberFormatException nfe2){
     errorString = "NumberFormatException";
     bIsError = true;
     return new DLValue(0);
    }
    set(valuelong);
    return new DLValue(valuelong);
   }
  }
  
  public DLValue function(String type, String input1, String input2)
  {
   if("date".equals(type)){
    SimpleDateFormat dateFormat = new  SimpleDateFormat(input1, java.util.Locale.getDefault());
    dateFormat.setTimeZone(TimeZone.getTimeZone( "GMT+0" ));
    Date date;
    try {
     date = dateFormat.parse(input2);
    } catch (Exception e) {
     errorString = "date function Error";
     bIsError = true;
     return this;
    }
    set(date.getTime());
    bIsDate = true;
   }
   return this;
  }
  public long getFactorial(long number) {
      long factorial = 1;
      for (long i = 1; i <= number; ++i) {
          factorial *= i;
      }
      return factorial;
  }
  public DLValue function(String type)
  {
   if("PI".equals(type)){
    up();
    floatValue = Math.PI;
   }else if("E".equals(type)){
    up();
    floatValue = Math.E;
   }else if("~".equals(type)){
    if( bIsFloat ){
     errorString = "overflow";
     bIsError = true;
     return this;
    }
    intValue = ~intValue; 
   }else if("!".equals(type)){
    if( bIsFloat || (intValue > 20)){
     errorString = "overflow";
     bIsError = true;
     return this;
    }
    intValue = getFactorial(intValue); 
   }
   return this;
  }

  public DLValue function(String type, DLValue input1, DLValue input2)
  {
   sync();
   input1.sync();
   input2.sync();
   if("pow".equals(type)){
    up();
    input1.up();
    input2.up();
    floatValue = Math.pow(input1.getFloatValue(),input2.getFloatValue());
   }else if("atan2".equals(type)){
    up();
    input1.up();
    input2.up();
    floatValue = Math.atan2( input1.getFloatValue(),input2.getFloatValue());
   }else if("max".equals(type)){
    floatValue = Math.max( input1.getFloatValue(),input2.getFloatValue());
    intValue = Math.max( input1.getIntValue(),input2.getIntValue() );
   }else if("min".equals(type)){
    floatValue = Math.min( input1.getFloatValue(),input2.getFloatValue());
    intValue = Math.min( input1.getIntValue(),input2.getIntValue() );
   }else if("hypot".equals(type)){
    up();
    input1.up();
    input2.up();
    floatValue = Math.hypot( input1.getFloatValue(),input2.getFloatValue());
   }
   
   if( !bIsFloat )
   {
    // Integer
    if( floatValue - intValue > 1.0E-16 ) {
     // If difference is greater than 1d, must change type to the float
     up();
    }
   }
   return this;
  }
  
  public DLValue function(String type, DLValue input1)
  {
   boolean isFloat = bIsFloat | input1.getIsFloat();
   boolean onlyInt = false;
   sync();
   input1.sync();
   
   if( isFloat ) {
    upSync();
    input1.upSync();
   }
   
   if("+".equals(type)){
    floatValue = floatValue + input1.getFloatValue();
    intValue = intValue + input1.getIntValue();
   }else if("-".equals(type)){
    floatValue = floatValue - input1.getFloatValue();
    intValue = intValue - input1.getIntValue();
   }else if("*".equals(type)){
    floatValue = floatValue * input1.getFloatValue();
    intValue = intValue * input1.getIntValue();
   }else if("/".equals(type)){
    floatValue = floatValue / input1.getFloatValue();
    intValue = intValue / input1.getIntValue();
   }else if("sin".equals(type)){
    up();
    floatValue = Math.sin( input1.getFloatValue() );
   }else if("cos".equals(type)){
    up();
    floatValue = Math.cos( input1.getFloatValue() );
   }else if("tan".equals(type)){
    up();
    floatValue = Math.tan( input1.getFloatValue() );
   }else if("asin".equals(type)){
    up();
    floatValue = Math.asin( input1.getFloatValue() );
   }else if("acos".equals(type)){
    up();
    floatValue = Math.acos( input1.getFloatValue() );
   }else if("atan".equals(type)){
    up();
    floatValue = Math.atan( input1.getFloatValue() );
   }else if("toRadians".equals(type)){
    up();
    floatValue = Math.toRadians( input1.getFloatValue() );
   }else if("toDegrees".equals(type)){
    up();
    floatValue = Math.toDegrees( input1.getFloatValue() );
   }else if("exp".equals(type)){
    up();
    floatValue = Math.exp( input1.getFloatValue() );
   }else if("log".equals(type)){
    up();
    floatValue = Math.log( input1.getFloatValue() );
   }else if("log10".equals(type)){
    up();
    floatValue = Math.log10( input1.getFloatValue() );
   }else if("sqrt".equals(type)){
    up();
    floatValue = Math.sqrt( input1.getFloatValue() );
   }else if("cbrt".equals(type)){
    up();
    floatValue = Math.cbrt( input1.getFloatValue() );
   }else if("ceil".equals(type)){
    up();
    floatValue = Math.ceil( input1.getFloatValue() );
   }else if("floor".equals(type)){
    up();
    floatValue = Math.floor( input1.getFloatValue() );
   }else if("rint".equals(type)){
    up();
    floatValue = Math.rint( input1.getFloatValue() );
   }else if("abs".equals(type)){
    floatValue = Math.abs( input1.getFloatValue() );
    intValue = Math.abs( input1.getIntValue() );
   }else if("signum".equals(type)){
    up();
    floatValue = Math.signum( input1.getFloatValue() );
   }else if("sinh".equals(type)){
    up();
    floatValue = Math.sinh( input1.getFloatValue() );
   }else if("cosh".equals(type)){
    up();
    floatValue = Math.cosh( input1.getFloatValue() );
   }else if("tanh".equals(type)){
    up();
    floatValue = Math.tanh( input1.getFloatValue() );
   }else if("|".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue | input1.getIntValue();
    onlyInt = true;
   }else if("^".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue ^ input1.getIntValue();
    onlyInt = true;
   }else if("&".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue & input1.getIntValue();
    onlyInt = true;
   }else if(">>".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue >> input1.getIntValue();
    onlyInt = true;
   }else if("<<".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue << input1.getIntValue();
    floatValue = floatValue * Math.pow( 2, input1.getIntValue());
    if( floatValue - intValue > 1.0E-20 ) {
     // If difference is greater than 1d, must change type to the float
     bIsBitOverflow = true;
     errorString = "<<";
    }
    onlyInt = true;
   }else if("%".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue % input1.getIntValue();
    onlyInt = true;
   }
   
   if( !isFloat && !onlyInt )
   {
    // Integer
    if( floatValue - intValue > 1.0E-20 ) {
     // If difference is greater than 1d, must change type to the float
     up();
    }
   }
   
   return this;
  }
 }
 
 public void testDLValue() throws ParseException
 {
  DLValue dlValue;
  dlValue = new DLValue(1);
  assertEquals(dlValue.getIsFloat(),false);
  dlValue.function("+", new DLValue(1.1));
  assertEquals(dlValue.getIsFloat(),true);
  assertEquals(dlValue.getFloatValue(),2.1d);
  dlValue = new DLValue(1);
  dlValue.function("+", new DLValue(100));
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),101l);
  dlValue = new DLValue(100000000000000000l);
  dlValue.function("*", new DLValue(100000000000000000l));
  assertEquals(dlValue.getIsFloat(),true);
  assertEquals(dlValue.getFloatValue(),1.0E34);
  dlValue = new DLValue(6);
  dlValue.function("/", new DLValue(3));
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),2l);
  dlValue = new DLValue();
  dlValue.function("sin", new DLValue(3.141592));
  assertEquals(dlValue.getIsFloat(),true);
  assertTrue(dlValue.getFloatValue()<0.1d);
  dlValue = new DLValue();
  dlValue.function("PI");
  assertEquals(dlValue.getIsFloat(),true);
  assertEquals(dlValue.getFloatValue(),Math.PI);
  dlValue.function("pow", new DLValue(2), new DLValue(10));
  assertEquals(dlValue.getIsFloat(),true);
  assertEquals(dlValue.getFloatValue(),1024d);
  dlValue.parse("0xff");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),255);
  dlValue.parse("0xffffffff");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),4294967295l);
  dlValue.parse("0xffffffffff");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),0xffffffffffl);
  dlValue.parse("0x7fffffffffffffff");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),0x7fffffffffffffffl);
  dlValue.parse("0x7f ff ff ff ff ff ff ff");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),0x7fffffffffffffffl);
  dlValue.parse("1111 1111b");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),0xffl);
  dlValue.parse("1111 1111 1111 b");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),0xfffl);
  dlValue.function("date","yyyy-MM-dd HH:mm:ss","1970-01-01 00:00:00");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),0l);
  dlValue.set(10);
  dlValue.function("~");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),~10l);
  dlValue.set(10);
  dlValue.function("!");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),3628800);
  dlValue.set(20);
  dlValue.function("!");
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),2432902008176640000l);
  dlValue.set(20);
  dlValue.function("<<",new DLValue(2));
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),20<<2);
  dlValue.set(20);
  dlValue.function("%",new DLValue(3));
  assertEquals(dlValue.getIsFloat(),false);
  assertEquals(dlValue.getIntValue(),20%3);
 }
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
 }

}


지금 까지 작업된 완성된 jj 소스를 공개합니다.


// http://read.pudn.com/downloads197/sourcecode/compiler/927244/%E7%A8%8B%E5%BA%8F%E6%BA%90%E7%A0%81%E5%8F%8A%E7%94%9F%E6%88%90%E7%9A%84java%E5%92%8Cclass%E6%96%87%E4%BB%B6/calculator.jj__.htm

options { 
  STATIC = false; 
  UNICODE_INPUT = true;
} 
PARSER_BEGIN(calculator) 
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import java.io.PrintStream ; 
public class calculator {
 public class DLValue {
  double floatValue;
  long   intValue;
  boolean bIsFloat;
  boolean bIsDate;
  boolean bIsError;
  boolean bIsBitOverflow;
  String errorString;

  public DLValue()
  {
   init();
  }
  
  public DLValue(long value)
  {
   set(value);
  }

  public DLValue(int value)
  {
   set(value);
  }

  public DLValue(float value)
  {
   set(value);
  }

  public DLValue(double value)
  {
   set(value);
  }
  
  public void init()
  {
   floatValue = 0.0;
   intValue = 0;
   bIsFloat = true;
   bIsDate = false;
   bIsError = false;
   errorString = "";
   bIsBitOverflow = false;
  }
  
  public void setLong(boolean value)
  {
   bIsFloat = value;
  }
  public void set(long value)
  {
   intValue = value;
   bIsFloat = false;
  }
  public void set(int value)
  {
   intValue = (long)value;
   bIsFloat = false;
  }

  public void set(float value)
  {
   floatValue = (double)value;
   bIsFloat = true;
  }

  public void set(double value)
  {
   floatValue = value;
   bIsFloat = true;
  }
  public boolean getIsFloat()
  {
   return bIsFloat;
  }
  
  public void sync()
  {
   if( !bIsFloat ){
    floatValue = intValue;
   }else{
    intValue = (long)floatValue;
   }
  }
  
  public void upSync()
  {
   sync();
   if( !bIsFloat ){
    bIsFloat = true;
    bIsDate = false;
   }
  }
  public void up()
  {
   bIsDate = false;
   bIsFloat = true;
  }
  public void down()
  {
   bIsFloat = false;
  }
  public double getFloatValue()
  {
   return floatValue;
  }
  
  public long getIntValue()
  {
   return intValue;
  }
  
  public void print()
  {
   if( bIsError ){
    System.out.println("Error:"+errorString);
    return;
   }
   if( bIsBitOverflow ){
    System.out.println("Overflow:"+errorString);
   }
   if( bIsFloat ){
    System.out.println(getFloatValue());
   }else{
    System.out.println(getIntValue());
    if( bIsDate ){
     SimpleDateFormat dateFormat = new  SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     dateFormat.setTimeZone(TimeZone.getTimeZone( "GMT+0" ));
     Date date = new Date(getIntValue());
     String strDate = dateFormat.format(date);
     System.out.println(strDate);
    }
   }
  }
  
  public DLValue parse(String str)
  {
   long valuelong = 0;
   double valuedouble = 0.0;
   int radix = 10;
   String newstr = str;
   if(str.length() > 2 && str.charAt(0)=='0' && str.charAt(1)=='x' ){
    newstr = str.substring(2,str.length());
    radix = 16;
    newstr = newstr.trim().replaceAll(" ", "");
    newstr = newstr.replaceAll("\\p{Z}", "");
   }else if(str.length()>1 && str.charAt(str.length()-1)=='b'){
    // remove a last 'b' char 
    newstr = str.substring(0,str.length()-1);
    radix = 2;
    newstr = newstr.trim().replaceAll(" ", "");
    newstr = newstr.replaceAll("\\p{Z}", "");
   }
   if( radix == 10 ){
    try{
     valuelong = Long.parseLong(newstr, radix);
     set(valuelong);
     return new DLValue(valuelong);
    }catch(NumberFormatException nfe){
     try{
      valuedouble = Double.parseDouble(newstr);
     }catch(NumberFormatException nfe2){
      errorString = "NumberFormatException";
      bIsError = true;
      return new DLValue(0);
     }
     set(valuedouble);
     return new DLValue(valuedouble);
    }
   }else{
    try{
     valuelong = Long.parseLong(newstr, radix);
    }catch(NumberFormatException nfe2){
     errorString = "NumberFormatException";
     bIsError = true;
     return new DLValue(0);
    }
    set(valuelong);
    return new DLValue(valuelong);
   }
  }
  
  public DLValue function(String type, String input1, String input2)
  {
   if("date".equals(type)){
    SimpleDateFormat dateFormat = new  SimpleDateFormat(input1, java.util.Locale.getDefault());
    dateFormat.setTimeZone(TimeZone.getTimeZone( "GMT+0" ));
    Date date;
    try {
     date = dateFormat.parse(input2);
    } catch (Exception e) {
     errorString = "date function Error";
     bIsError = true;
     return this;
    }
    set(date.getTime());
    bIsDate = true;
   }
   return this;
  }
  public long getFactorial(long number) {
      long factorial = 1;
      for (long i = 1; i <= number; ++i) {
          factorial *= i;
      }
      return factorial;
  }
  public DLValue function(String type)
  {
   if("PI".equals(type)){
    up();
    floatValue = Math.PI;
   }else if("E".equals(type)){
    up();
    floatValue = Math.E;
   }else if("~".equals(type)){
    if( bIsFloat ){
     errorString = "overflow";
     bIsError = true;
     return this;
    }
    intValue = ~intValue; 
   }else if("!".equals(type)){
    if( bIsFloat || (intValue > 20)){
     errorString = "overflow";
     bIsError = true;
     return this;
    }
    intValue = getFactorial(intValue); 
   }
   return this;
  }

  public DLValue function(String type, DLValue input1, DLValue input2)
  {
   sync();
   input1.sync();
   input2.sync();
   if("pow".equals(type)){
    up();
    input1.up();
    input2.up();
    floatValue = Math.pow(input1.getFloatValue(),input2.getFloatValue());
   }else if("atan2".equals(type)){
    up();
    input1.up();
    input2.up();
    floatValue = Math.atan2( input1.getFloatValue(),input2.getFloatValue());
   }else if("max".equals(type)){
    floatValue = Math.max( input1.getFloatValue(),input2.getFloatValue());
    intValue = Math.max( input1.getIntValue(),input2.getIntValue() );
   }else if("min".equals(type)){
    floatValue = Math.min( input1.getFloatValue(),input2.getFloatValue());
    intValue = Math.min( input1.getIntValue(),input2.getIntValue() );
   }else if("hypot".equals(type)){
    up();
    input1.up();
    input2.up();
    floatValue = Math.hypot( input1.getFloatValue(),input2.getFloatValue());
   }
   
   if( !bIsFloat )
   {
    // Integer
    if( floatValue - intValue > 1.0E-16 ) {
     // If difference is greater than 1d, must change type to the float
     up();
    }
   }
   return this;
  }
  
  public DLValue function(String type, DLValue input1)
  {
   boolean isFloat = bIsFloat | input1.getIsFloat();
   boolean onlyInt = false;
   sync();
   input1.sync();
   
   if( isFloat ) {
    upSync();
    input1.upSync();
   }
   
   if("+".equals(type)){
    floatValue = floatValue + input1.getFloatValue();
    intValue = intValue + input1.getIntValue();
   }else if("-".equals(type)){
    floatValue = floatValue - input1.getFloatValue();
    intValue = intValue - input1.getIntValue();
   }else if("*".equals(type)){
    floatValue = floatValue * input1.getFloatValue();
    intValue = intValue * input1.getIntValue();
   }else if("/".equals(type)){
    floatValue = floatValue / input1.getFloatValue();
    intValue = intValue / input1.getIntValue();
   }else if("sin".equals(type)){
    up();
    floatValue = Math.sin( input1.getFloatValue() );
   }else if("cos".equals(type)){
    up();
    floatValue = Math.cos( input1.getFloatValue() );
   }else if("tan".equals(type)){
    up();
    floatValue = Math.tan( input1.getFloatValue() );
   }else if("asin".equals(type)){
    up();
    floatValue = Math.asin( input1.getFloatValue() );
   }else if("acos".equals(type)){
    up();
    floatValue = Math.acos( input1.getFloatValue() );
   }else if("atan".equals(type)){
    up();
    floatValue = Math.atan( input1.getFloatValue() );
   }else if("toRadians".equals(type)){
    up();
    floatValue = Math.toRadians( input1.getFloatValue() );
   }else if("toDegrees".equals(type)){
    up();
    floatValue = Math.toDegrees( input1.getFloatValue() );
   }else if("exp".equals(type)){
    up();
    floatValue = Math.exp( input1.getFloatValue() );
   }else if("log".equals(type)){
    up();
    floatValue = Math.log( input1.getFloatValue() );
   }else if("log10".equals(type)){
    up();
    floatValue = Math.log10( input1.getFloatValue() );
   }else if("sqrt".equals(type)){
    up();
    floatValue = Math.sqrt( input1.getFloatValue() );
   }else if("cbrt".equals(type)){
    up();
    floatValue = Math.cbrt( input1.getFloatValue() );
   }else if("ceil".equals(type)){
    up();
    floatValue = Math.ceil( input1.getFloatValue() );
   }else if("floor".equals(type)){
    up();
    floatValue = Math.floor( input1.getFloatValue() );
   }else if("rint".equals(type)){
    up();
    floatValue = Math.rint( input1.getFloatValue() );
   }else if("abs".equals(type)){
    floatValue = Math.abs( input1.getFloatValue() );
    intValue = Math.abs( input1.getIntValue() );
   }else if("signum".equals(type)){
    up();
    floatValue = Math.signum( input1.getFloatValue() );
   }else if("sinh".equals(type)){
    up();
    floatValue = Math.sinh( input1.getFloatValue() );
   }else if("cosh".equals(type)){
    up();
    floatValue = Math.cosh( input1.getFloatValue() );
   }else if("tanh".equals(type)){
    up();
    floatValue = Math.tanh( input1.getFloatValue() );
   }else if("|".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue | input1.getIntValue();
    onlyInt = true;
   }else if("^".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue ^ input1.getIntValue();
    onlyInt = true;
   }else if("&".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue & input1.getIntValue();
    onlyInt = true;
   }else if(">>".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue >> input1.getIntValue();
    onlyInt = true;
   }else if("<<".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue << input1.getIntValue();
    floatValue = floatValue * Math.pow( 2, input1.getIntValue());
    if( floatValue - intValue > 1.0E-20 ) {
     // If difference is greater than 1d, must change type to the float
     bIsBitOverflow = true;
     errorString = "<<";
    }
    onlyInt = true;
   }else if("%".equals(type)){
    if( bIsFloat ){
     errorString = "float type is not support";
     bIsError = true;
     return this;
    }
    intValue = intValue % input1.getIntValue();
    onlyInt = true;
   }
   
   if( !isFloat && !onlyInt )
   {
    // Integer
    if( floatValue - intValue > 1.0E-20 ) {
     // If difference is greater than 1d, must change type to the float
     up();
    }
   }
   
   return this;
  }
 }
 

  DLValue previousValue;
  public static void main(String args[]) throws ParseException { 
     calculator parser = new calculator(System.in);    
    while (true) { 
      System.out.println("This is an advanced calculator based on the prior .jj embeded in eclipse"); 
      System.out.print("Enter an expression like \"2.0+3.4 \" we support +,-,*,\\,(),sin(),cos(),and number with fraction:"); 
      try { 
           parser.Start(System.out); 
      
         
      } catch (Exception e) { 
        System.out.println("NOK."); 
        System.out.println(e.getMessage()); 
        parser.ReInit(System.in); 
      } catch (Error e) { 
        System.out.println("Oops."); 
        System.out.println(e.getMessage()); 
        break; 
      } 
    } 
  } 
} 
/*
 ORDER
 () , function, ~, +, - : Primary
 * / % : 승제 term
 + - : 가감 sum
 << >> : shift bit
 & : and bit
 ^ : xor bit
 | : or bit
 */


PARSER_END(calculator) 
 
SKIP : 
{ 
 " " 
}

TOKEN : /* OPERATORS */ 
{
 < OR_BIT: "|" >
| < XOR_BIT: "^" >
| < AND_BIT: "&" >
| < RSHIFT_BIT: ">>" >
| < LSHIFT_BIT: "<<" >
| < PLUS: "+" > 
| < MINUS: "-" > 
| < MULTIPLY: "*" > 
| < DIVIDE: "/" >   
| < MOD: "%" >
| < NOT: "~" >
|   < LPAREN : "(">    
|   < RPAREN : ")">    
|   < INTEGER_NUMBER : <DIGITS> >    
|   < FLOATING_NUMBER : <DIGITS> "." <DIGITS> | <DIGITS> "." | "."<DIGITS> | <FLOATING_POINT> >  
|   < #DIGITS : (["0"-"9"])+ >  
|   < SIN: "sin" | "SIN" >    
|   < COS: "cos" | "COS" >
|   < TAN: "tan" | "TAN" >
|   < ASIN: "asin" | "ASIN" >
|   < ACOS: "acos" | "ACOS" >
|   < ATAN: "atan" | "ATAN" >
|   < TORADIANS: "toradians" | "TORADIANS" >
|   < TODEGREES: "todegrees" | "TODEGREES" >
|   < EXP: "exp" | "EXP" >
|   < LOG: "log" | "LOG" >
|   < LOG10: "log10" | "LOG10" >
|   < SQRT: "sqrt" | "SQRT" >
|   < CBRT: "cbrt" | "CBRT" >
|   < CEIL: "ceil" | "CEIL" >
|   < FLOOR: "floor" | "FLOOR" >
|   < RINT: "rint" | "RINT" >
|   < ABS: "abs" | "ABS" >
|   < SIGNUM: "signum" | "SIGNUM" >
|   < SINH: "sinh" | "SINH" >
|   < COSH: "cosh" | "COSH" >
|   < TANH: "tanh" | "TANH" >
|   < POW: "pow" | "POW" >
|   < ATAN2: "atan2" | "ATAN2" >
|   < MAX: "max" | "MAX" >
|   < MIN: "min" | "MIN" >
|   < HYPOT: "hypot" | "HYPOT" >
|   < PI: "pi" | "PI" >
|   < MATH_E: "math_e" | "MATH_E" >
|   < DATE: "date" | "DATE" >
|   < FDATE: "fdate" | "FDATE" >
|   < COMMA: "," >
|   < HEX_NUMBER : "0x"(["0"-"9","A"-"F","a"-"f"," "])+ >
|   < BIN_NUMBER : (["1","0"])+(["1","0"," "])*"b" >
|   < STRING : 
      "\"" 
      (
         "\\" ~[]     //any escaped character
      |               //or
        ~["\"","\\"]  //any character except quote or backslash
      )* 
      "\"" >
|   < #FLOATING_POINT : (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
                              | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
                              | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
                              | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
    >
|   < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|   < EOL : "\n" | "\r" | "\r\n" > 
}



void Start(PrintStream printStream)  : 
{} 
{ 
 ( previousValue = or_bit() <EOL> { previousValue.print(); previousValue.init(); } )* <EOF> 
} 

DLValue or_bit() :  
{ 
  DLValue i; 
  DLValue value;
  } 
{ 
 value=xor_bit() ( <OR_BIT>i=xor_bit(){value.function("|",i);} )* 
 {return value;} 
}

DLValue xor_bit() :
{ 
  DLValue i; 
  DLValue value;
  } 
{ 
 value=and_bit() ( <XOR_BIT>i=and_bit(){value.function("^",i);} )* 
 {return value;} 
}

DLValue and_bit() :
{ 
  DLValue i; 
  DLValue value;
  } 
{ 
 value=shift_bit() ( <AND_BIT>i=shift_bit(){value.function("&",i);} )* 
 {return value;} 
}

DLValue shift_bit() :
{ 
  DLValue i; 
  DLValue value;
  } 
{ 
 value=sum() ( <RSHIFT_BIT>i=sum(){value.function(">>",i);} | <LSHIFT_BIT>i=sum(){value.function("<<",i);} )* 
 {return value;} 
}

DLValue  sum() :  
{ 
  DLValue i; 
  DLValue value;
  } 
{ 
 value=term() ( <PLUS>i=term(){value.function("+",i);} | <MINUS>i=term(){value.function("-",i); } )* 
 {return value;} 
} 


DLValue term() :  
{ 
  DLValue i; 
  DLValue value; 
} 
{ 
 value = Primary()(<MULTIPLY>i = Primary(){ value.function("*",i); } | <DIVIDE>i = Primary(){ value.function("/",i); } | <MOD>i = Primary(){ value.function("%",i); })* 
 { return value ;} 
}

String string() :  
{
 Token t ; 
}
{
 t=<STRING> { return new String(t.image); }
}

DLValue Primary() :  
{ 
  Token t ; 
  String a,b ;
  DLValue value,value2;
}
{
 t=<BIN_NUMBER> { return new DLValue().parse(t.image); }
|
 t=<HEX_NUMBER> { return new DLValue().parse(t.image); }
|
 t=<INTEGER_NUMBER> { return new DLValue().parse(t.image); }
|
 t=<FLOATING_NUMBER>{ return new DLValue(Double.parseDouble( t.image )) ; } 
|
 <PI>{ return new DLValue().function("PI"); }
|
 <MATH_E>{ return new DLValue().function("E"); }
|
 <LPAREN> value=or_bit() <RPAREN>{ return value ; } 
|
 <NOT> value=Primary() { return value.function("~"); } 
|
 <PLUS> value=Primary(){ return value; } 
| 
 <MINUS> value=Primary(){ return value.function("*",new DLValue(-1)) ; } 
| 
 <SIN><LPAREN>value=or_bit()<RPAREN>{ return value.function("sin",value); }  
|    
 <COS><LPAREN>value=or_bit()<RPAREN>{ return value.function("cos",value); } 
|
 <TAN><LPAREN>value=or_bit()<RPAREN>{ return value.function("tan",value); } 
|
 <ASIN><LPAREN>value=or_bit()<RPAREN>{ return value.function("asin",value); } 
|
 <ACOS><LPAREN>value=or_bit()<RPAREN>{ return value.function("acos",value); } 
|
 <ATAN><LPAREN>value=or_bit()<RPAREN>{ return value.function("atan",value); }
|
 <TORADIANS><LPAREN>value=or_bit()<RPAREN>{ return value.function("toRadians",value); }
|
 <TODEGREES><LPAREN>value=or_bit()<RPAREN>{ return value.function("toDegrees",value); }
|
 <EXP><LPAREN>value=or_bit()<RPAREN>{ return value.function("exp",value); }
|
 <LOG><LPAREN>value=or_bit()<RPAREN>{ return value.function("log",value); }
|
 <LOG10><LPAREN>value=or_bit()<RPAREN>{ return value.function("log10",value); }
|
 <SQRT><LPAREN>value=or_bit()<RPAREN>{ return value.function("sqrt",value); }
|
 <CBRT><LPAREN>value=or_bit()<RPAREN>{ return value.function("cbrt",value); }
|
 <CEIL><LPAREN>value=or_bit()<RPAREN>{ return value.function("ceil",value); }
|
 <FLOOR><LPAREN>value=or_bit()<RPAREN>{ return value.function("floor",value); }
|
 <RINT><LPAREN>value=or_bit()<RPAREN>{ return value.function("rint",value); }
|
 <ABS><LPAREN>value=or_bit()<RPAREN>{ return value.function("abs",value); }
|
 <SIGNUM><LPAREN>value=or_bit()<RPAREN>{ return value.function("signum",value); }
|
 <SINH><LPAREN>value=or_bit()<RPAREN>{ return value.function("sinh",value); }
|
 <COSH><LPAREN>value=or_bit()<RPAREN>{ return value.function("cosh",value); }
|
 <TANH><LPAREN>value=or_bit()<RPAREN>{ return value.function("tanh",value); }
|
 <POW><LPAREN>value=or_bit()<COMMA>value2=or_bit()<RPAREN>{ return value.function("pow",value,value2); }
|
 <ATAN2><LPAREN>value=or_bit()<COMMA>value2=or_bit()<RPAREN>{ return value.function("atan2",value,value2); }
|
 <MAX><LPAREN>value=or_bit()<COMMA>value2=or_bit()<RPAREN>{ return value.function("max",value,value2); }
|
 <MIN><LPAREN>value=or_bit()<COMMA>value2=or_bit()<RPAREN>{ return value.function("min",value,value2); }
|
 <HYPOT><LPAREN>value=or_bit()<COMMA>value2=or_bit()<RPAREN>{ return value.function("hypot",value,value2); }
|    
 <DATE><LPAREN>a=string()<RPAREN>{ return new DLValue().function("date", "\"yyyy-MM-dd HH:mm:ss\"", a); } 
|
 <FDATE><LPAREN>a=string()<COMMA>b=string()<RPAREN>{ return new DLValue().function("date", a, b); } 
}

실행 화면입니다.



D:\work\개인\Work\android\allcalc>java -classpath javacc-6.1.2.jar javacc allcal
c.jj
Java Compiler Compiler Version 6.1_2 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file allcalc.jj . . .
Note: UNICODE_INPUT option is specified. Please make sure you create the parser/
lexer using a Reader with the correct character encoding.
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.

D:\work\개인\Work\android\allcalc>javac calculator.java

D:\work\개인\Work\android\allcalc>java calculator
This is an advanced calculator based on the prior .jj embeded in eclipse
Enter an expression like "2.0+3.4 " we support +,-,*,\,(),sin(),cos(),and number
 with fraction:PI*1<<6+80
Error:float type is not support
1<<6*PI+80
Error:float type is not support
(1<<6)*PI+80
281.06192982974676




댓글 없음:

댓글 쓰기