/// <summary> /// Check if parse point reach end point or not. /// </summary> /// <param name="statement">input</param> /// <param name="data"></param> /// <returns>true:reach end point , false:not reach end point.</returns> private bool isExit(string statement , ParsedData data) { return statement.Length <= data.INDEX; }
/// <summary> /// /// </summary> /// <param name="statement">input expression's statement</param> /// <param name="data"></param> /// <returns></returns> private ParsedData factor(string statement, ParsedData data) { var token = statement.ElementAt(data.INDEX); if(token == Token.Parenthesis.BEGIN ) { data.INDEX++; if(isExit(statement,data)) { throw new SyntaxException("'('と')'の対応が合いません。",data.INDEX); } var rExpr = expr(statement, data); if (isExit(statement, rExpr)) { throw new SyntaxException(")の対応が合わず、終端に到達しました。",data.INDEX); } if (statement.ElementAt(rExpr.INDEX) != Token.Parenthesis.END) { throw new SyntaxException(")が合わない",data.INDEX); } rExpr.INDEX++; return rExpr; } else { string strNumber = ""; if (isMinusSign(token)) { data.INDEX = data.INDEX + 1; token = statement.ElementAt(data.INDEX); strNumber = Token.Num.MINUS.ToString(); } // 数字が一文字以上連続している場合は、数字として認識する。 if (!isNumber(token)) throw new SyntaxException("????",data.INDEX); strNumber += token.ToString(); var idxBegin = data.INDEX; var idxEnd = idxBegin; for (int idx = idxBegin + 1; idx < statement.Length; idx++ ) { var numWrk = statement.ElementAt(idxEnd + 1); if (!isNumber(numWrk)) break; idxEnd++; strNumber += numWrk.ToString(); } try { var number = long.Parse(strNumber); idxEnd++; return new ParsedData(number, idxEnd, data.MESSAGE); } catch(OverflowException ex) { throw new ParseOverflowException(ex.Message, idxBegin, strNumber); } } }
/// <summary> /// /// </summary> /// <param name="statement">input expression's statement</param> /// <param name="data"></param> /// <returns></returns> private ParsedData expr(string statement , ParsedData data) { var rLeft = term(statement , data); if (isExit(statement, rLeft)) { return rLeft; } while (true) { var tokenCurrent = statement.ElementAt(rLeft.INDEX); if (tokenCurrent == Token.Operator.ADD) { var rRight = term(statement, new ParsedData(rLeft.NUMBER, rLeft.INDEX + 1, rLeft.MESSAGE)); rLeft.INDEX = rRight.INDEX; rLeft.NUMBER = rLeft.NUMBER + rRight.NUMBER; } else if (tokenCurrent == Token.Operator.SUB) { var rRight = term(statement, new ParsedData(rLeft.NUMBER, rLeft.INDEX + 1, rLeft.MESSAGE)); rLeft.INDEX = rRight.INDEX; rLeft.NUMBER = rLeft.NUMBER - rRight.NUMBER; } else { break; } if (isExit(statement, rLeft)) break; } return rLeft; }
/// <summary> /// /// </summary> /// <param name="statement">input expression's statement</param> /// <param name="data"></param> /// <returns></returns> private ParsedData term(string statement, ParsedData data) { var rLeft = factor(statement, data); if (isExit(statement, rLeft)) { return rLeft; } while (true) { var token = statement.ElementAt(rLeft.INDEX); if (token == Token.Operator.MUL) { var rRight = factor(statement, new ParsedData(rLeft.NUMBER, rLeft.INDEX + 1, rLeft.MESSAGE)); rLeft.INDEX = rRight.INDEX; rLeft.NUMBER = rLeft.NUMBER * rRight.NUMBER; } else if (token == Token.Operator.DIV) { var rRight = factor(statement, new ParsedData(rLeft.NUMBER, rLeft.INDEX + 1, rLeft.MESSAGE)); rLeft.INDEX = rRight.INDEX; rLeft.NUMBER = rLeft.NUMBER / rRight.NUMBER; } else { break; } if (isExit(statement, rLeft)) break; } return rLeft; }
/// <summary> /// 計算機の入力式を解析する実行部 /// </summary> /// <param name="statement"></param> /// <returns></returns> private ParserResult parse_exec( string statement) { var data = new ParsedData(0, 0, ""); var result = expr(statement,data); // Check Syntax Accept Condition if (isExit(statement, result)) { return new ParserResult(result.NUMBER, result.MESSAGE); } else { //statementの終端に達する前に解析終了しました。 //文法エラーが発生しています。 throw new SyntaxException(string.Format("{0}文字目近辺で異常終了しました。",result.INDEX),result.INDEX); } }