Example #1
0
        ///// <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);
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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());
        }
Example #4
0
        /// <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;
 }