///// <summary> ///// 単純文字列、書式付文字列、文字列式のうち、文字列式を取り扱う。 ///// 終端記号が正しいかどうかは呼び出し元で調べること ///// </summary> ///// <param name="st"></param> ///// <returns></returns> //public static IOperandTerm ReduceStringTerm(WordCollection wc, TermEndWith endWith) //{ // IOperandTerm term = reduceTerm(wc, false, endWith, VariableCode.__NULL__); // if (term.GetOperandType() != typeof(string)) // throw new CodeEE("式の結果が文字列ではありません"); // return term; //} public static IOperandTerm ReduceIntegerTerm(WordCollection wc, TermEndWith endwith) { IOperandTerm term = reduceTerm(wc, false, endwith, VariableCode.__NULL__); if (term == null) { throw new CodeEE("構文を式として解釈できません"); } if (term.GetOperandType() != typeof(Int64)) { throw new CodeEE("式の結果が数値ではありません"); } return(term); }
/// <summary> /// カンマで区切られた引数を一括して取得。 /// return時にはendWithの次の文字がCurrentになっているはず。終端の適切さの検証はExpressionParserがが行う。 /// 呼び出し元はCodeEEを適切に処理すること /// </summary> /// <returns></returns> public static IOperandTerm[] ReduceArguments(WordCollection wc, ArgsEndWith endWith, bool isDefine) { if (wc == null) { throw new ExeEE("空のストリームを渡された"); } List <IOperandTerm> terms = new List <IOperandTerm>(); TermEndWith termEndWith = TermEndWith.EoL; switch (endWith) { case ArgsEndWith.EoL: termEndWith = TermEndWith.Comma; break; //case ArgsEndWith.RightBracket: // termEndWith = TermEndWith.RightBracket_Comma; // break; case ArgsEndWith.RightParenthesis: termEndWith = TermEndWith.RightParenthesis_Comma; break; } TermEndWith termEndWith_Assignment = termEndWith | TermEndWith.Assignment; while (true) { Word word = wc.Current; switch (word.Type) { case '\0': if (endWith == ArgsEndWith.RightBracket) { throw new CodeEE("'['に対応する']'が見つかりません"); } if (endWith == ArgsEndWith.RightParenthesis) { throw new CodeEE("'('に対応する')'が見つかりません"); } goto end; case ')': if (endWith == ArgsEndWith.RightParenthesis) { wc.ShiftNext(); goto end; } throw new CodeEE("構文解析中に予期しない')'を発見しました"); case ']': if (endWith == ArgsEndWith.RightBracket) { wc.ShiftNext(); goto end; } throw new CodeEE("構文解析中に予期しない']'を発見しました"); } if (!isDefine) { terms.Add(ReduceExpressionTerm(wc, termEndWith)); } else { terms.Add(ReduceExpressionTerm(wc, termEndWith_Assignment)); if (terms[terms.Count - 1] == null) { throw new CodeEE("関数定義の引数は省略できません"); } if (wc.Current is OperatorWord) { //=がある wc.ShiftNext(); IOperandTerm term = reduceTerm(wc, false, termEndWith, VariableCode.__NULL__); if (term == null) { throw new CodeEE("'='の後に式がありません"); } if (term.GetOperandType() != terms[terms.Count - 1].GetOperandType()) { throw new CodeEE("'='の前後で型が一致しません"); } terms.Add(term); } else { if (terms[terms.Count - 1].GetOperandType() == typeof(Int64)) { terms.Add(new NullTerm(0)); } else { terms.Add(new NullTerm("")); } } } if (wc.Current.Type == ',') { wc.ShiftNext(); } } end: IOperandTerm[] ret = new IOperandTerm[terms.Count]; terms.CopyTo(ret); return(ret); }
/// <summary> /// 解析器の本体 /// </summary> /// <param name="wc"></param> /// <param name="allowKeywordTo">TOキーワードが見つかっても良いか</param> /// <param name="endWith">終端記号</param> /// <returns></returns> private static IOperandTerm reduceTerm(WordCollection wc, bool allowKeywordTo, TermEndWith endWith, VariableCode varCode) { TermStack stack = new TermStack(); //int termCount = 0; int ternaryCount = 0; OperatorCode formerOp = OperatorCode.NULL; bool varArg = varCode != VariableCode.__NULL__; do { Word token = wc.Current; switch (token.Type) { case '\0': goto end; case '"': //LiteralStringWT stack.Add(((LiteralStringWord)token).Str); break; case '0': //LiteralIntegerWT stack.Add(((LiteralIntegerWord)token).Int); break; case 'F': //FormattedStringWT stack.Add(ToStrFormTerm((StrFormWord)token)); break; case 'A': //IdentifierWT { string idStr = (((IdentifierWord)token).Code); if (idStr.Equals("TO", Config.SCVariable)) { if (allowKeywordTo) { goto end; } else { throw new CodeEE("TOキーワードはここでは使用できません"); } } else if (idStr.Equals("IS", Config.SCVariable)) { throw new CodeEE("ISキーワードはここでは使用できません"); } stack.Add(reduceIdentifier(wc, idStr, varCode)); continue; } case '=': //OperatorWT { if (varArg) { throw new CodeEE("変数の引数の読み取り中に予期しない演算子を発見しました"); } OperatorCode op = ((OperatorWord)token).Code; if (op == OperatorCode.Assignment) { if ((endWith & TermEndWith.Assignment) == TermEndWith.Assignment) { goto end; } throw new CodeEE("式中で代入演算子'='が使われています(等価比較には'=='を使用してください)"); } if (formerOp == OperatorCode.Equal || formerOp == OperatorCode.Greater || formerOp == OperatorCode.Less || formerOp == OperatorCode.GreaterEqual || formerOp == OperatorCode.LessEqual || formerOp == OperatorCode.NotEqual) { if (op == OperatorCode.Equal || op == OperatorCode.Greater || op == OperatorCode.Less || op == OperatorCode.GreaterEqual || op == OperatorCode.LessEqual || op == OperatorCode.NotEqual) { ParserMediator.Warn("(構文上の注意)比較演算子が連続しています。", GlobalStatic.Process.GetScaningLine(), 0, false, false); } } stack.Add(op); formerOp = op; if (op == OperatorCode.Ternary_a) { ternaryCount++; } else if (op == OperatorCode.Ternary_b) { if (ternaryCount > 0) { ternaryCount--; } else { throw new CodeEE("対応する'?'のない'#'です"); } } break; } case '(': wc.ShiftNext(); IOperandTerm inTerm = reduceTerm(wc, false, TermEndWith.RightParenthesis, VariableCode.__NULL__); if (inTerm == null) { throw new CodeEE("かっこ\"(\"~\")\"の中に式が含まれていません"); } stack.Add(inTerm); if (wc.Current.Type != ')') { throw new CodeEE("対応する')'のない'('です"); } //termCount++; wc.ShiftNext(); continue; case ')': if ((endWith & TermEndWith.RightParenthesis) == TermEndWith.RightParenthesis) { goto end; } throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); case ']': if ((endWith & TermEndWith.RightBracket) == TermEndWith.RightBracket) { goto end; } throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); case ',': if ((endWith & TermEndWith.Comma) == TermEndWith.Comma) { goto end; } throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); case 'M': throw new ExeEE("マクロ解決失敗"); default: throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); } //termCount++; wc.ShiftNext(); } while (!varArg); end: if (ternaryCount > 0) { throw new CodeEE("'?'と'#'の数が正しく対応していません"); } return(stack.ReduceAll()); }
/// <summary> /// 数式または文字列式。CALLの引数などを扱う。nullを返すことがある。 /// return時にはendWithの文字がCurrentになっているはず。終端の適切さの検証は呼び出し元が行う。 /// </summary> /// <param name="st"></param> /// <returns></returns> public static IOperandTerm ReduceExpressionTerm(WordCollection wc, TermEndWith endWith) { IOperandTerm term = reduceTerm(wc, false, endWith, VariableCode.__NULL__); return(term); }
/// <summary> /// 解析器の本体 /// </summary> /// <param name="wc"></param> /// <param name="allowKeywordTo">TOキーワードが見つかっても良いか</param> /// <param name="endWith">終端記号</param> /// <returns></returns> private static IOperandTerm reduceTerm(WordCollection wc, bool allowKeywordTo, TermEndWith endWith, VariableCode varCode) { TermStack stack = new TermStack(); //int termCount = 0; int ternaryCount = 0; OperatorCode formerOp = OperatorCode.NULL; bool varArg = varCode != VariableCode.__NULL__; do { Word token = wc.Current; switch (token.Type) { case '\0': goto end; case '"'://LiteralStringWT stack.Add(((LiteralStringWord)token).Str); break; case '0'://LiteralIntegerWT stack.Add(((LiteralIntegerWord)token).Int); break; case 'F'://FormattedStringWT stack.Add(ToStrFormTerm((StrFormWord)token)); break; case 'A'://IdentifierWT { string idStr = (((IdentifierWord)token).Code); if (idStr.Equals("TO", Config.SCVariable)) { if (allowKeywordTo) goto end; else throw new CodeEE("TOキーワードはここでは使用できません"); } else if (idStr.Equals("IS", Config.SCVariable)) throw new CodeEE("ISキーワードはここでは使用できません"); stack.Add(reduceIdentifier(wc, idStr, varCode)); continue; } case '='://OperatorWT { if (varArg) throw new CodeEE("変数の引数の読み取り中に予期しない演算子を発見しました"); OperatorCode op = ((OperatorWord)token).Code; if (op == OperatorCode.Assignment) { if ((endWith & TermEndWith.Assignment) == TermEndWith.Assignment) goto end; throw new CodeEE("式中で代入演算子'='が使われています(等価比較には'=='を使用してください)"); } if (formerOp == OperatorCode.Equal || formerOp == OperatorCode.Greater || formerOp == OperatorCode.Less || formerOp == OperatorCode.GreaterEqual || formerOp == OperatorCode.LessEqual || formerOp == OperatorCode.NotEqual) { if (op == OperatorCode.Equal || op == OperatorCode.Greater || op == OperatorCode.Less || op == OperatorCode.GreaterEqual || op == OperatorCode.LessEqual || op == OperatorCode.NotEqual) { ParserMediator.Warn("(構文上の注意)比較演算子が連続しています。", GlobalStatic.Process.GetScaningLine(), 0, false, false); } } stack.Add(op); formerOp = op; if (op == OperatorCode.Ternary_a) ternaryCount++; else if (op == OperatorCode.Ternary_b) { if (ternaryCount > 0) ternaryCount--; else throw new CodeEE("対応する'#'のない'?'です"); } break; } case '(': wc.ShiftNext(); IOperandTerm inTerm = reduceTerm(wc, false, TermEndWith.RightParenthesis, VariableCode.__NULL__); if (inTerm == null) throw new CodeEE("かっこ\"(\"~\")\"の中に式が含まれていません"); stack.Add(inTerm); if (wc.Current.Type != ')') throw new CodeEE("対応する')'のない'('です"); //termCount++; wc.ShiftNext(); continue; case ')': if ((endWith & TermEndWith.RightParenthesis) == TermEndWith.RightParenthesis) goto end; throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); case ']': if ((endWith & TermEndWith.RightBracket) == TermEndWith.RightBracket) goto end; throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); case ',': if ((endWith & TermEndWith.Comma) == TermEndWith.Comma) goto end; throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); case 'M': throw new ExeEE("マクロ解決失敗"); default: throw new CodeEE("構文解釈中に予期しない記号'" + token.Type + "'を発見しました"); } //termCount++; wc.ShiftNext(); } while (!varArg); end: if (ternaryCount > 0) throw new CodeEE("\'?\'と\'#\'の数が正しく対応していません"); return stack.ReduceAll(); }
///// <summary> ///// 単純文字列、書式付文字列、文字列式のうち、文字列式を取り扱う。 ///// 終端記号が正しいかどうかは呼び出し元で調べること ///// </summary> ///// <param name="st"></param> ///// <returns></returns> //public static IOperandTerm ReduceStringTerm(WordCollection wc, TermEndWith endWith) //{ // IOperandTerm term = reduceTerm(wc, false, endWith, VariableCode.__NULL__); // if (term.GetOperandType() != typeof(string)) // throw new CodeEE("式の結果が文字列ではありません"); // return term; //} public static IOperandTerm ReduceIntegerTerm(WordCollection wc, TermEndWith endwith) { IOperandTerm term = reduceTerm(wc, false, endwith, VariableCode.__NULL__); if (term == null) throw new CodeEE("構文を式として解釈できません"); if (term.GetOperandType() != typeof(Int64)) throw new CodeEE("式の結果が数値ではありません"); return term; }
/// <summary> /// 数式または文字列式。CALLの引数などを扱う。nullを返すことがある。 /// return時にはendWithの文字がCurrentになっているはず。終端の適切さの検証は呼び出し元が行う。 /// </summary> /// <param name="st"></param> /// <returns></returns> public static IOperandTerm ReduceExpressionTerm(WordCollection wc, TermEndWith endWith) { IOperandTerm term = reduceTerm(wc, false, endWith, VariableCode.__NULL__); return term; }