/// <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> /// カンマで区切られた引数を一括して取得。 /// return時にはendWithの次の文字がCurrentになっているはず。終端の適切さの検証はExpressionParserがが行う。 /// 呼び出し元はCodeEEを適切に処理すること /// </summary> /// <returns></returns> public static IOperandTerm[] ReduceArguments(WordCollection wc, ArgsEndWith endWith, bool isDefine) { 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; }