递归下降的带变量的表达式解析器

×可以将错误报告补充的更详细,比如突出显示表达式中的错误位置,方便用户发现错误并改正。

×可以使解析器能够计算字符串。

a = "one"

b = "two"

c = a+b

结果应该是"onetwo"

×这个例子测试用例

A= 10/4

A-B

C=A*(F-21)

*findVar()只接受变量的第一个字母。

×vars[] 26个字母变量。每个数组项对应一个变量,保存变量值,根据字面的ascii数值取数组中的值。



package com.johnchensz.parser;

import com.johnchensz.*;

public class Parser {
	final int NONE = 0;
	final int DELIMITER = 1;
	final int VARIABLE = 2;
	final int NUMBER = 3;
	
	final int SYNTAX = 0;
	final int UNBALPARENS = 1; //unbalparens
	final int NOEXP = 2;
	final int DIVBYZERO = 3;
	
	final String EOE = "\0";
	
	private String exp;
	private int expIdx;
	private String token;
	private int tokType;
	
	private double vars[] = new double[26];
	
	public double evaluate(String expstr) throws ParserException
	{
		double result;
		exp = expstr;
		expIdx = 0;
		
		getToken();
		if(token.equals(EOE))
			handleError(NOEXP);
		
		result = evalExp1();
		
		if(!token.equals(EOE))
			handleError(SYNTAX);
		
		return result;
	}
	
	private double evalExp1() throws ParserException
	{
		double result;
		int varIdx;
		int ttokType;
		String temptoken;
		
		if(tokType==VARIABLE) {
			temptoken = new String(token);
			ttokType = tokType;
			
			varIdx = Character.toUpperCase(token.charAt(0))-'A';
			
			getToken();
			if(!token.equals("=")){
				putBack();
				token = new String(temptoken);
				tokType = ttokType;
			} else {
				getToken();
				result = evalExp2();
				vars[varIdx] = result;
				return result;
				
			}
		}
		return evalExp2();
	}
	private double evalExp2() throws ParserException
	{
		char op;
		double result;
		double partialResult;
		
		result = evalExp3();
		
		while ((op=token.charAt(0))=='+' || op=='-') {
			getToken();
			partialResult = evalExp3();
			switch(op) {
			case '-':
				result = result - partialResult;
				break;
			case '+':
				result = result + partialResult;
				break;
			}
		}
		return result;
	}
	
	private double evalExp3() throws ParserException
	{
		char op;
		double result;
		double partialResult;
		
		result = evalExp4();
		
		while((op=token.charAt(0))=='*'||op=='/'||op=='%'){
			getToken();
			partialResult = evalExp4();
			switch(op){
			case '*':
				result = result * partialResult;
				break;
			case '/':
				if(partialResult ==0.0)
					handleError(DIVBYZERO);
				result = result / partialResult;
				break;
			case '%':
				if(partialResult == 0.0)
					handleError(DIVBYZERO);
				result = result % partialResult;
				break;
			}
		}
		return result;
	}
	
	private double evalExp4() throws ParserException
	{
		double result;
		double partialResult;
		double ex;
		int t;
		
		result = evalExp5();
		
		if(token.equals("^")){
			getToken();
			partialResult = evalExp4();
			ex = result;
			if (partialResult == 0.0){
				result = 1.0;
			} else {
				for (t=(int)partialResult-1;t>0;t--)
					result = result * ex;
			}
		}
		return result;
	}
	
	private double evalExp5() throws ParserException
	{
		double result;
		String op;
		
		op="";
		if((tokType==DELIMITER)&& token.equals("+")||token.equals("-")) {
			op = token;
			getToken();
		}
		result = evalExp6();
		
		if(op.equals("-"))
			result = -result;
		
		return result;
	}
	
	private double evalExp6() throws ParserException
	{
		double result=0.0;
		
		if(token.equals("(")){
			getToken();
			result = evalExp2();
			if(!token.equals(")"))
				handleError(UNBALPARENS);
			getToken();
		} else 
			result = atom();
		
		return result;
	}
	
	private double atom() throws ParserException {
		double result = 0.0;
		
		switch(tokType) {
		case NUMBER:
			try {
				result = Double.parseDouble(token);
			}catch (NumberFormatException exc) {
				handleError(SYNTAX);
			}
			getToken();
			break;
		case VARIABLE:
			result = findVar(token);
			getToken();
			break;
		default:
			handleError(SYNTAX);
			break;
				
		}
		return result;
	}
	
	private double findVar(String vname) throws ParserException {
		if(!Character.isLetter(vname.charAt(0))){
			handleError(SYNTAX);
			return 0.0;
		}
		return vars[Character.toUpperCase(vname.charAt(0))-'A'];
	}
	
	private void putBack(){
		if(token==EOE)
			return;
		
		for(int i=0;i<token.length();i++)
			expIdx--;
	}
	
	private void handleError(int error) throws ParserException {
		String[] err = {
				"Syntax Error",
				"Unbalanced Parentheses",
				"No Expression Present",
				"Division by Zero"
		};
		
		throw new ParserException(err[error]);
	}
	
	private void getToken() {
		tokType = NONE;
		token = "";
		
		if (expIdx == exp.length()){
			token = EOE;
			return;
		}
		while (expIdx < exp.length() && Character.isWhitespace(exp.charAt(expIdx)))
				++expIdx;
		
		if(expIdx == exp.length()){
			token = EOE;
			return;
		}
		
		if (isDelim(exp.charAt(expIdx))) {
			token += exp.charAt(expIdx);
			expIdx++;
			tokType = DELIMITER;
		} else if (Character.isLetter(exp.charAt(expIdx))){
			while(!isDelim(exp.charAt(expIdx))){
				token += exp.charAt(expIdx);
				expIdx++;
				if(expIdx>=exp.length())
					break;
			}
			tokType = VARIABLE;
		} else if (Character.isDigit(exp.charAt(expIdx))){
			while(!isDelim(exp.charAt(expIdx))){
				token+=exp.charAt(expIdx);
				expIdx++;
				if(expIdx>=exp.length())
					break;
			}
			tokType = NUMBER;
		} else {
			token = EOE;
			return;
		}
	}
	
	private boolean isDelim(char c){
		if ((" +-/*%^=()").indexOf(c)!= -1)
			return true;
		return false;
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值