javacc5.0 implementation of four calculator scripts

Keywords: Java calculator

options{
 STATIC=false;
 LEXER_CLASS="ExpCalcParserTokenManager";
}
PARSER_BEGIN(ExpCalcParser)
import java.io.*;
import java.io.PrintStream; 
import java.math.BigDecimal;

public class ExpCalcParser{
	private static final int DEF_DIV_SCALE = 16;//Result precision set to 16 bits
	private String exp;
	
	public static ExpCalcParser createExpressionParser(String s) {
      SimpleCharStream scs = new SimpleCharStream(new StringReader(s), 1, 1, s.length());
      ExpCalcParserTokenManager token_source = new ExpCalcParserTokenManager(scs);
      return new ExpCalcParser(token_source);
	}
	public static void main(String args[]) throws ParseException{
		String exp = "1/0.0";
		ExpCalcParser parser = createExpressionParser(exp);
		System.out.println(parser.calculator());
	}

}
PARSER_END(ExpCalcParser)

SKIP : 
{
	<(" ")>
}
TOKEN : { < EOL: "\n" | "\r" | "\r\n" > } 
TOKEN : 
{
	<#DIGITS : (["0"-"9"])+ >
	|
	<NUMBER : <DIGITS> | <DIGITS>"."<DIGITS>>
	|
	<ADD : "+" >
	|
	<SUBTRACT : "-" >
	|
	<MULTIPLY : "*" >
	|
	<DIVIDE : "/" >
	|
	<POW : "^">
	|
	<LEFT_PAR : "(" >
	|
	<RIGHT_PAR : ")" >
}
public String calculator(): 
{
	String result = "";
}
{
	(result = Expression())*
	 { return result; } 
}
String Expression() :
{
	String i;
	String value;
}
{
	value = Term()
	(
		<ADD>
		i=Term()
		{ 
		if("Infinity".equals(value) || "Infinity".equals(i)){ return "Infinity";}
		if("NaN".equals(value) || "Infinity".equals(i)) {return "NaN";}
		if("Divisor cannot be 0".equals(value) || "Divisor cannot be 0".equals(i)) {return "Divisor cannot be 0";}
		value = new BigDecimal(value).add(new BigDecimal(i)).stripTrailingZeros().toPlainString();
		}
		|
		<SUBTRACT>
		i=Term()
		{
		if("Infinity".equals(value) || "Infinity".equals(i)){ return "Infinity";}
		if("NaN".equals(value) || "Infinity".equals(i)) {return "NaN";}
		if("Divisor cannot be 0".equals(value) || "Divisor cannot be 0".equals(i)) {return "Divisor cannot be 0";}
		 value = new BigDecimal(value).subtract(new BigDecimal(i)).stripTrailingZeros().toPlainString();
		}
	)*
	{return value;}
}
String Term() :
{
	String i;
	String value;
}
{
	value = Pow()
	(
		<MULTIPLY>
		i = Pow()
		
		{
			if("Infinity".equals(value) || "Infinity".equals(i)){return "Infinity";}
			if("NaN".equals(value) || "Infinity".equals(i)) {return "NaN";}
			if("Divisor cannot be 0".equals(value) || "Divisor cannot be 0".equals(i)) {return "Divisor cannot be 0";}
			value = new BigDecimal(value).multiply(new BigDecimal(i)).stripTrailingZeros().toPlainString();
		}
		|
		<DIVIDE>
		i = Pow()
		{
			if(i.matches("[-+]?0+\\.?0*?")) {//Whether divisor is 0
				return "Divisor cannot be 0";
			}
			if("Infinity".equals(value) || "Infinity".equals(i)){ return "Infinity";}
			if("NaN".equals(value) || "Infinity".equals(i)) {return "NaN";}
			if("Divisor cannot be 0".equals(value) || "Divisor cannot be 0".equals(i)) {return "Divisor cannot be 0";}
			try {
				//Divisibility
				value = new BigDecimal(value).divide(new BigDecimal(i)).stripTrailingZeros().toPlainString();
			}catch(Exception e) {
				//Non divisibility
				value = new BigDecimal(value).divide(new BigDecimal(i),DEF_DIV_SCALE,BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
			}
		}	
	)*
	{return value;}
}

String Pow() : 
{
	String i;
	String value;
}
{
	value = Primary()
	(
		<POW>
		i = Primary()
		{
			if("Infinity".equals(value) || "Infinity".equals(i)){ return "Infinity";}
			if("NaN".equals(value) || "Infinity".equals(i)) {return "NaN";}
			if("Divisor cannot be 0".equals(value) || "Divisor cannot be 0".equals(i)) {return "Divisor cannot be 0";}
			try {
				 //No exception for BigDecimal
				 value = new BigDecimal(Math.pow(Double.parseDouble(value),Double.parseDouble(i))).toPlainString();
			 }catch(Exception e) {
				 //Infinite BigDecimal throw exception
				 value = new Double(Math.pow(Double.parseDouble(value),Double.parseDouble(i))).toString();
			 }
		}
	)*
	{return value;}
}

String Primary() :
{
	Token t;
	String value;
}
{
	t=<NUMBER>
	{return t.image;}
	|
	<LEFT_PAR> value = Expression() <RIGHT_PAR>
	{ return value;}
	|
	<SUBTRACT> value = Primary()
	{return new BigDecimal("0").subtract(new BigDecimal(value)).stripTrailingZeros().toPlainString();}
	|
	<ADD> value = Primary()
	{return value;}
	
}

This script is saved as ExpCalcParser.jj. Extract the javacc package and put it in bin directory, as shown below:

Then create a new directory expcalc in the bin directory, press ctrl+shift, right-click, open the cmd window in the bin directory, and enter the command: JavaCC - debug_parser: true - output_directory:. \ \ expcalcparser.jj, as shown below:

 

Then the generated class appears in expcalc, which can be used directly, as shown in the figure:

 

Copy the generated class into your application, and you can parse the expression. Call the method and get the calculation result as follows:

 

Posted by Hangston on Sat, 04 Jan 2020 08:58:17 -0800