/// <summary>
        /// 戻り値と引数の数・型の完全一致が必要
        /// </summary>
        /// <param name="call"></param>
        /// <returns>一致ならtrue</returns>
        internal bool MatchType(CalledFunction call)
        {
            FunctionLabelLine label = call.TopLabel;

            if (label.IsError)
            {
                return(false);
            }
            if (RetType != label.MethodType)
            {
                return(false);
            }
            if (ArgTypeList.Length != label.Arg.Length)
            {
                return(false);
            }
            for (int i = 0; i < ArgTypeList.Length; i++)
            {
                VariableToken vToken = label.Arg[i].Identifier;
                if (vToken.IsReference)
                {
                    UserDifinedFunctionDataArgType type = UserDifinedFunctionDataArgType.__Ref;
                    type += vToken.Dimension;
                    if (vToken.IsInteger)
                    {
                        type |= UserDifinedFunctionDataArgType.Int;
                    }
                    else
                    {
                        type |= UserDifinedFunctionDataArgType.Str;
                    }
                    if (ArgTypeList[i] != type)
                    {
                        return(false);
                    }
                }
                else
                {
                    if (vToken.IsInteger && ArgTypeList[i] != UserDifinedFunctionDataArgType.Int)
                    {
                        return(false);
                    }
                    if (vToken.IsString && ArgTypeList[i] != UserDifinedFunctionDataArgType.Str)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemple #2
0
        public static UserDefinedFunctionData Create(WordCollection wc, bool dims, ScriptPosition sc)
        {
            string dimtype = dims ? "#FUNCTION" : "#FUNCTIONS";
            UserDefinedFunctionData ret = new UserDefinedFunctionData();

            ret.TypeIsStr = dims;
            IdentifierWord idw     = null;
            string         keyword = dimtype;

            while (!wc.EOL && (idw = wc.Current as IdentifierWord) != null)
            {
                wc.ShiftNext();
                keyword = idw.Code;
                if (Config.ICVariable)
                {
                    keyword = keyword.ToUpper();
                }
                switch (keyword)
                {
                case "CONST":
                case "REF":
                case "DYNAMIC":
                case "STATIC":
                case "GLOBAL":
                case "SAVEDATA":
                case "CHARADATA":
                    throw new CodeEE(dims + "中では" + keyword + "キーワードは指定できません", sc);

                default:
                    ret.Name = keyword;
                    goto whilebreak;
                }
            }
whilebreak:
            if (ret.Name == null)
            {
                throw new CodeEE(keyword + "の後に有効な識別子が指定されていません", sc);
            }
            if (wc.EOL || wc.Current.Type != '(')
            {
                throw new CodeEE("識別子の後に引数定義がありません", sc);
            }
            string errMes   = "";
            int    errLevel = -1;

            GlobalStatic.IdentifierDictionary.CheckUserLabelName(ref errMes, ref errLevel, true, ret.Name);
            if (errLevel == 0)            //関数と変数の両方からチェック エラーメッセージが微妙だがひとまず気にしない
            {
                GlobalStatic.IdentifierDictionary.CheckUserVarName(ref errMes, ref errLevel, ret.Name);
            }
            if (errLevel >= 0)
            {
                if (errLevel >= 2)
                {
                    throw new CodeEE(errMes, sc);
                }
                ParserMediator.Warn(errMes, sc, errLevel);
            }
            List <UserDifinedFunctionDataArgType> argList = new List <UserDifinedFunctionDataArgType>();
            UserDifinedFunctionDataArgType        argType = UserDifinedFunctionDataArgType.Null;

            int state = 0;

            //0=初期状態 1=カンマ括弧閉じ待ち 2=カンマ直後
            //3=REF後INTorSTR待ち 4=':'or','待ち 5=':'or '0'or ','待ち
            while (true)            // REF INT STR 0 '*' ',' ')' のみで構成されるはず
            {
                wc.ShiftNext();
                switch (wc.Current.Type)
                {
                case '\0':
                    throw new CodeEE("括弧が閉じられていません", sc);

                case ')':
                    if (state == 0 || state == 1)
                    {
                        goto argend;
                    }
                    if (state == 4 || state == 5)
                    {
                        if ((int)(argType & UserDifinedFunctionDataArgType.__Dimention) == 0)
                        {
                            throw new CodeEE("REF引数は配列変数でなければなりません", sc);
                        }
                        state = 2;
                        argList.Add(argType);
                        goto argend;
                    }
                    throw new CodeEE("予期しない括弧です", sc);

                case '0':
                    if (((LiteralIntegerWord)wc.Current).Int != 0)
                    {
                        goto argerr;
                    }
                    if (state == 5)
                    {
                        state = 4;
                        continue;
                    }
                    goto argerr;

                case ':':
                    if (state == 4 || state == 5)
                    {
                        state = 5;
                        argType++; if ((int)(argType & UserDifinedFunctionDataArgType.__Dimention) > 3)
                        {
                            throw new CodeEE("REF引数は4次元以上の配列にできません", sc);
                        }
                        continue;
                    }
                    goto argerr;

                case ',':
                    if (state == 1)
                    {
                        state = 2;
                        continue;
                    }
                    if (state == 4 || state == 5)
                    {
                        if ((int)(argType & UserDifinedFunctionDataArgType.__Dimention) == 0)
                        {
                            throw new CodeEE("REF引数は配列変数でなければなりません", sc);
                        }
                        state = 2;
                        argList.Add(argType);
                        continue;
                    }
                    goto argerr;

                case 'A':
                {
                    string str = ((IdentifierWord)wc.Current).Code;
                    if (Config.ICVariable)
                    {
                        str = str.ToUpper();
                    }
                    if (str == "REF")
                    {
                        if (state == 0 || state == 2)
                        {
                            state = 3;
                            continue;
                        }
                        goto argerr;
                    }
                    else if (str == "INT" || str == "STR")
                    {
                        if (str == "INT")
                        {
                            argType = UserDifinedFunctionDataArgType.Int;
                        }
                        else
                        {
                            argType = UserDifinedFunctionDataArgType.Str;
                        }
                        if (state == 0 || state == 2)
                        {
                            state = 1;
                            argList.Add(argType);
                            continue;
                        }
                        if (state == 3)
                        {
                            argType = argType | UserDifinedFunctionDataArgType.__Ref;
                            state   = 4;
                            continue;
                        }
                        goto argerr;
                    }
                    else
                    {
                        goto argerr;
                    }
                }

                default:
                    goto argerr;
                }
            }
argend:
            wc.ShiftNext();
            if (!wc.EOL)
            {
                throw new CodeEE("宣言の後に余分な文字があります", sc);
            }
            ret.ArgList = new UserDifinedFunctionDataArgType[argList.Count];
            argList.CopyTo(ret.ArgList);
            return(ret);

argerr:
            if (!wc.EOL)
            {
                throw new CodeEE("引数の解析中に予期しないトークン" + wc.Current.ToString() + "を発見しました", sc);
            }
            throw new CodeEE("引数の解析中にエラーが発生しました", sc);
        }