Beispiel #1
0
        private static CaseExpression reduceCaseExpression(WordCollection wc)
        {
            CaseExpression ret = new CaseExpression();
            IdentifierWord id  = wc.Current as IdentifierWord;

            if ((id != null) && (id.Code.Equals("IS", Config.SCVariable)))
            {
                wc.ShiftNext();
                ret.CaseType = CaseExpressionType.Is;
                OperatorWord opWT = wc.Current as OperatorWord;
                if (opWT == null)
                {
                    throw new CodeEE("ISキーワードの後に演算子がありません");
                }

                OperatorCode op = opWT.Code;
                if (!OperatorManager.IsBinary(op))
                {
                    throw new CodeEE("ISキーワードの後の演算子が2項演算子ではありません");
                }
                wc.ShiftNext();
                ret.Operator = op;
                ret.LeftTerm = reduceTerm(wc, false, TermEndWith.Comma, VariableCode.__NULL__);
                if (ret.LeftTerm == null)
                {
                    throw new CodeEE("ISキーワードの後に式がありません");
                }
                Type type = ret.LeftTerm.GetOperandType();
                return(ret);
            }
            ret.LeftTerm = reduceTerm(wc, true, TermEndWith.Comma, VariableCode.__NULL__);
            if (ret.LeftTerm == null)
            {
                throw new CodeEE("CASEの引数は省略できません");
            }
            id = wc.Current as IdentifierWord;
            if ((id != null) && (id.Code.Equals("TO", Config.SCVariable)))
            {
                ret.CaseType = CaseExpressionType.To;
                wc.ShiftNext();
                ret.RightTerm = reduceTerm(wc, true, TermEndWith.Comma, VariableCode.__NULL__);
                if (ret.RightTerm == null)
                {
                    throw new CodeEE("TOキーワードの後に式がありません");
                }
                id = wc.Current as IdentifierWord;
                if ((id != null) && (id.Code.Equals("TO", Config.SCVariable)))
                {
                    throw new CodeEE("TOキーワードが2度使われています");
                }
                if (ret.LeftTerm.GetOperandType() != ret.RightTerm.GetOperandType())
                {
                    throw new CodeEE("TOキーワードの前後の型が一致していません");
                }
                return(ret);
            }
            ret.CaseType = CaseExpressionType.Normal;
            return(ret);
        }
Beispiel #2
0
 public DefineMacro(string key, WordCollection wc, int argcount)
 {
     Keyword           = key;
     Statement         = wc;
     ArgCount          = argcount;
     Statement.Pointer = 0;
     HasArguments      = argcount != 0;
     if (Statement.Collection.Count == 1)
     {
         IDWord = Statement.Current as IdentifierWord;
     }
     IsNull = wc.Collection.Count == 0;
 }
Beispiel #3
0
        public static VariableToken ReduceVariableIdentifier(WordCollection wc, string idStr)
        {
            string subId = null;

            if (wc.Current.Type == '@')
            {
                wc.ShiftNext();
                IdentifierWord subidWT = wc.Current as IdentifierWord;
                if (subidWT == null)
                {
                    throw new CodeEE("@の使い方が不正です");
                }
                wc.ShiftNext();
                subId = subidWT.Code;
            }
            return(GlobalStatic.IdentifierDictionary.GetVariableToken(idStr, subId, true));
        }
Beispiel #4
0
        public static StrForm FromWordToken(StrFormWord wt)
        {
            StrForm ret = new StrForm();

            ret.strs = wt.Strs;
            IOperandTerm[] termArray = new IOperandTerm[wt.SubWords.Length];
            for (int i = 0; i < wt.SubWords.Length; i++)
            {
                SubWord             SWT     = wt.SubWords[i];
                TripleSymbolSubWord tSymbol = SWT as TripleSymbolSubWord;
                if (tSymbol != null)
                {
                    switch (tSymbol.Code)
                    {
                    case '*':
                        termArray[i] = NameTarget;
                        continue;

                    case '+':
                        termArray[i] = CallnameMaster;
                        continue;

                    case '=':
                        termArray[i] = CallnamePlayer;
                        continue;

                    case '/':
                        termArray[i] = NameAssi;
                        continue;

                    case '$':
                        termArray[i] = CallnameTarget;
                        continue;
                    }
                    throw new ExeEE("何かおかしい");
                }
                WordCollection wc      = null;
                IOperandTerm   operand = null;
                YenAtSubWord   yenat   = SWT as YenAtSubWord;
                if (yenat != null)
                {
                    wc = yenat.Words;
                    if (wc != null)
                    {
                        operand = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.EoL);
                        if (!wc.EOL)
                        {
                            throw new CodeEE("三項演算子\\@の第一オペランドが異常です");
                        }
                    }
                    else
                    {
                        operand = new SingleTerm(0);
                    }
                    IOperandTerm left  = new StrFormTerm(StrForm.FromWordToken(yenat.Left));
                    IOperandTerm right = null;
                    if (yenat.Right == null)
                    {
                        right = new SingleTerm("");
                    }
                    else
                    {
                        right = new StrFormTerm(StrForm.FromWordToken(yenat.Right));
                    }
                    termArray[i] = new FunctionMethodTerm(formatYenAt, new IOperandTerm[] { operand, left, right });
                    continue;
                }
                wc      = SWT.Words;
                operand = ExpressionParser.ReduceExpressionTerm(wc, TermEndWith.Comma);
                if (operand == null)
                {
                    if (SWT is CurlyBraceSubWord)
                    {
                        throw new CodeEE("{}の中に式が存在しません");
                    }
                    else
                    {
                        throw new CodeEE("%%の中に式が存在しません");
                    }
                }
                IOperandTerm second = null;
                SingleTerm   third  = null;
                wc.ShiftNext();
                if (!wc.EOL)
                {
                    second = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.Comma);

                    wc.ShiftNext();
                    if (!wc.EOL)
                    {
                        IdentifierWord id = wc.Current as IdentifierWord;
                        if (id == null)
                        {
                            throw new CodeEE("','の後にRIGHT又はLEFTがありません");
                        }
                        if (string.Equals(id.Code, "LEFT", Config.SCVariable))//標準RIGHT
                        {
                            third = new SingleTerm(1);
                        }
                        else if (!string.Equals(id.Code, "RIGHT", Config.SCVariable))
                        {
                            throw new CodeEE("','の後にRIGHT又はLEFT以外の単語があります");
                        }
                        wc.ShiftNext();
                    }
                    if (!wc.EOL)
                    {
                        throw new CodeEE("RIGHT又はLEFTの後に余分な文字があります");
                    }
                }
                if (SWT is CurlyBraceSubWord)
                {
                    if (operand.GetOperandType() != typeof(Int64))
                    {
                        throw new CodeEE("{}の中の式が数式ではありません");
                    }
                    termArray[i] = new FunctionMethodTerm(formatCurlyBrace, new IOperandTerm[] { operand, second, third });
                    continue;
                }
                if (operand.GetOperandType() != typeof(string))
                {
                    throw new CodeEE("%%の中の式が文字列式ではありません");
                }
                termArray[i] = new FunctionMethodTerm(formatPercent, new IOperandTerm[] { operand, second, third });
            }
            ret.terms = termArray;
            return(ret);
        }
Beispiel #5
0
        //#define FOO (~~)     id to wc
        //#define BAR($1) (~~)     idwithargs to wc(replaced)
        //#diseble FOOBAR
        //#dim piyo, i
        //#dims puyo, j
        //static List<string> keywordsList = new List<string>();

        private void analyzeSharpDefine(StringStream st, ScriptPosition position)
        {
            //LexicalAnalyzer.SkipWhiteSpace(st);呼び出し前に行う。
            string srcID = LexicalAnalyzer.ReadSingleIdentifier(st);

            if (srcID == null)
            {
                throw new CodeEE("置換元の識別子がありません", position);
            }
            if (Config.ICVariable)
            {
                srcID = srcID.ToUpper();
            }

            //ここで名称重複判定しないと、大変なことになる
            string errMes   = "";
            int    errLevel = -1;

            idDic.CheckUserMacroName(ref errMes, ref errLevel, srcID);
            if (errLevel >= 0)
            {
                ParserMediator.Warn(errMes, position, errLevel);
                if (errLevel >= 2)
                {
                    noError = false;
                    return;
                }
            }

            bool hasArg = st.Current == '(';//引数を指定する場合には直後に(が続いていなければならない。ホワイトスペースも禁止。
            //1808a3 代入演算子許可(関数宣言用)
            WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment);

            if (wc.EOL)
            {
                //throw new CodeEE("置換先の式がありません", position);
                //1808a3 空マクロの許可
                DefineMacro nullmac = new DefineMacro(srcID, new WordCollection(), 0);
                idDic.AddMacro(nullmac);
                return;
            }

            List <string> argID = new List <string>();

            if (hasArg)            //関数型マクロの引数解析
            {
                wc.ShiftNext();    //'('を読み飛ばす
                if (wc.Current.Type == ')')
                {
                    throw new CodeEE("関数型マクロの引数を0個にすることはできません", position);
                }
                while (!wc.EOL)
                {
                    IdentifierWord word = wc.Current as IdentifierWord;
                    if (word == null)
                    {
                        throw new CodeEE("置換元の引数指定の書式が間違っています", position);
                    }
                    word.SetIsMacro();
                    string id = word.Code;
                    if (argID.Contains(id))
                    {
                        throw new CodeEE("置換元の引数に同じ文字が2回以上使われています", position);
                    }
                    argID.Add(id);
                    wc.ShiftNext();
                    if (wc.Current.Type == ',')
                    {
                        wc.ShiftNext();
                        continue;
                    }
                    if (wc.Current.Type == ')')
                    {
                        break;
                    }
                    throw new CodeEE("置換元の引数指定の書式が間違っています", position);
                }
                if (wc.EOL)
                {
                    throw new CodeEE("')'が閉じられていません", position);
                }

                wc.ShiftNext();
            }
            if (wc.EOL)
            {
                throw new CodeEE("置換先の式がありません", position);
            }
            WordCollection destWc = new WordCollection();

            while (!wc.EOL)
            {
                destWc.Add(wc.Current);
                wc.ShiftNext();
            }
            if (hasArg)            //関数型マクロの引数セット
            {
                while (!destWc.EOL)
                {
                    IdentifierWord word = destWc.Current as IdentifierWord;
                    if (word == null)
                    {
                        destWc.ShiftNext();
                        continue;
                    }
                    for (int i = 0; i < argID.Count; i++)
                    {
                        if (string.Equals(word.Code, argID[i], Config.SCVariable))
                        {
                            destWc.Remove();
                            destWc.Insert(new MacroWord(i));
                            break;
                        }
                    }
                    destWc.ShiftNext();
                }
                destWc.Pointer = 0;
            }
            if (hasArg)            //1808a3 関数型マクロの封印
            {
                throw new CodeEE("関数型マクロは宣言できません", position);
            }
            DefineMacro mac = new DefineMacro(srcID, destWc, argID.Count);

            idDic.AddMacro(mac);
        }
        public static UserDefinedFunctionData Create(WordCollection wc, bool dims, ScriptPosition sc)
        {
            var dimtype = dims ? "#FUNCTION" : "#FUNCTIONS";
            var ret     = new UserDefinedFunctionData();

            ret.TypeIsStr = dims;
            IdentifierWord idw     = null;
            var            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);
            }
            var errMes   = "";
            var 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);
            }
            var argList = new List <UserDifinedFunctionDataArgType>();
            var argType = UserDifinedFunctionDataArgType.Null;

            var 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':
                {
                    var str = ((IdentifierWord)wc.Current).Code;
                    if (Config.ICVariable)
                    {
                        str = str.ToUpper();
                    }
                    if (str == "REF")
                    {
                        if (state == 0 || state == 2)
                        {
                            state = 3;
                            continue;
                        }
                        goto argerr;
                    }
                    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;
                }

                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 + "を発見しました", sc);
            }
            throw new CodeEE("引数の解析中にエラーが発生しました", sc);
        }
Beispiel #7
0
        public static UserDefinedVariableData Create(WordCollection wc, bool dims, bool isPrivate, ScriptPosition sc)
        {
            string dimtype = dims ? "#DIM" : "#DIMS";
            UserDefinedVariableData ret = new UserDefinedVariableData();

            ret.TypeIsStr = dims;

            IdentifierWord idw           = null;
            bool           staticDefined = false;

            ret.Const = false;
            string        keyword  = dimtype;
            List <string> keywords = new List <string>();

            while (!wc.EOL && (idw = wc.Current as IdentifierWord) != null)
            {
                wc.ShiftNext();
                keyword = idw.Code;
                if (Config.ICVariable)
                {
                    keyword = keyword.ToUpper();
                }
                //TODO ifの数があたまわるい なんとかしたい
                switch (keyword)
                {
                case "CONST":
                    if (ret.CharaData)
                    {
                        throw new CodeEE(keyword + "とCHARADATAキーワードは同時に指定できません", sc);
                    }
                    if (ret.Global)
                    {
                        throw new CodeEE(keyword + "とGLOBALキーワードは同時に指定できません", sc);
                    }
                    if (ret.Save)
                    {
                        throw new CodeEE(keyword + "とSAVEDATAキーワードは同時に指定できません", sc);
                    }
                    if (ret.Reference)
                    {
                        throw new CodeEE(keyword + "とREFキーワードは同時に指定できません", sc);
                    }
                    if (!ret.Static)
                    {
                        throw new CodeEE(keyword + "とDYNAMICキーワードは同時に指定できません", sc);
                    }
                    if (ret.Const)
                    {
                        throw new CodeEE(keyword + "キーワードが二重に指定されています", sc);
                    }
                    ret.Const = true;
                    break;

                case "REF":
                    //throw new CodeEE("未実装の機能です", sc);
                    //if (!isPrivate)
                    //	throw new CodeEE("広域変数の宣言に" + keyword + "キーワードは指定できません", sc);
                    if (staticDefined && ret.Static)
                    {
                        throw new CodeEE(keyword + "とSTATICキーワードは同時に指定できません", sc);
                    }
                    if (ret.CharaData)
                    {
                        throw new CodeEE(keyword + "とCHARADATAキーワードは同時に指定できません", sc);
                    }
                    if (ret.Global)
                    {
                        throw new CodeEE(keyword + "とGLOBALキーワードは同時に指定できません", sc);
                    }
                    if (ret.Save)
                    {
                        throw new CodeEE(keyword + "とSAVEDATAキーワードは同時に指定できません", sc);
                    }
                    if (ret.Const)
                    {
                        throw new CodeEE(keyword + "とCONSTキーワードは同時に指定できません", sc);
                    }
                    if (ret.Reference)
                    {
                        throw new CodeEE(keyword + "キーワードが二重に指定されています", sc);
                    }
                    ret.Reference = true;
                    ret.Static    = true;
                    break;

                case "DYNAMIC":
                    if (!isPrivate)
                    {
                        throw new CodeEE("広域変数の宣言に" + keyword + "キーワードは指定できません", sc);
                    }
                    if (ret.CharaData)
                    {
                        throw new CodeEE(keyword + "とCHARADATAキーワードは同時に指定できません", sc);
                    }
                    if (ret.Const)
                    {
                        throw new CodeEE(keyword + "とCONSTキーワードは同時に指定できません", sc);
                    }
                    if (staticDefined)
                    {
                        if (ret.Static)
                        {
                            throw new CodeEE("STATICとDYNAMICキーワードは同時に指定できません", sc);
                        }
                        else
                        {
                            throw new CodeEE(keyword + "キーワードが二重に指定されています", sc);
                        }
                    }
                    staticDefined = true;
                    ret.Static    = false;
                    break;

                case "STATIC":
                    if (!isPrivate)
                    {
                        throw new CodeEE("広域変数の宣言に" + keyword + "キーワードは指定できません", sc);
                    }
                    if (ret.CharaData)
                    {
                        throw new CodeEE(keyword + "とCHARADATAキーワードは同時に指定できません", sc);
                    }
                    if (staticDefined)
                    {
                        if (!ret.Static)
                        {
                            throw new CodeEE("STATICとDYNAMICキーワードは同時に指定できません", sc);
                        }
                        else
                        {
                            throw new CodeEE(keyword + "キーワードが二重に指定されています", sc);
                        }
                    }
                    if (ret.Reference)
                    {
                        throw new CodeEE(keyword + "とREFキーワードは同時に指定できません", sc);
                    }
                    staticDefined = true;
                    ret.Static    = true;
                    break;

                case "GLOBAL":
                    if (isPrivate)
                    {
                        throw new CodeEE("ローカル変数の宣言に" + keyword + "キーワードは指定できません", sc);
                    }
                    if (ret.CharaData)
                    {
                        throw new CodeEE(keyword + "とCHARADATAキーワードは同時に指定できません", sc);
                    }
                    if (ret.Reference)
                    {
                        throw new CodeEE(keyword + "とREFキーワードは同時に指定できません", sc);
                    }
                    if (ret.Const)
                    {
                        throw new CodeEE(keyword + "とCONSTキーワードは同時に指定できません", sc);
                    }
                    if (staticDefined)
                    {
                        if (ret.Static)
                        {
                            throw new CodeEE("STATICとGLOBALキーワードは同時に指定できません", sc);
                        }
                        else
                        {
                            throw new CodeEE("DYNAMICとGLOBALキーワードは同時に指定できません", sc);
                        }
                    }
                    ret.Global = true;
                    break;

                case "SAVEDATA":
                    if (isPrivate)
                    {
                        throw new CodeEE("ローカル変数の宣言に" + keyword + "キーワードは指定できません", sc);
                    }
                    if (staticDefined)
                    {
                        if (ret.Static)
                        {
                            throw new CodeEE("STATICとSAVEDATAキーワードは同時に指定できません", sc);
                        }
                        else
                        {
                            throw new CodeEE("DYNAMICとSAVEDATAキーワードは同時に指定できません", sc);
                        }
                    }
                    if (ret.Reference)
                    {
                        throw new CodeEE(keyword + "とREFキーワードは同時に指定できません", sc);
                    }
                    if (ret.Const)
                    {
                        throw new CodeEE(keyword + "とCONSTキーワードは同時に指定できません", sc);
                    }
                    if (ret.Save)
                    {
                        throw new CodeEE(keyword + "キーワードが二重に指定されています", sc);
                    }
                    ret.Save = true;
                    break;

                case "CHARADATA":
                    if (isPrivate)
                    {
                        throw new CodeEE("ローカル変数の宣言に" + keyword + "キーワードは指定できません", sc);
                    }
                    if (ret.Reference)
                    {
                        throw new CodeEE(keyword + "とREFキーワードは同時に指定できません", sc);
                    }
                    if (ret.Const)
                    {
                        throw new CodeEE(keyword + "とCONSTキーワードは同時に指定できません", sc);
                    }
                    if (staticDefined)
                    {
                        if (ret.Static)
                        {
                            throw new CodeEE(keyword + "とSTATICキーワードは同時に指定できません", sc);
                        }
                        else
                        {
                            throw new CodeEE(keyword + "とDYNAMICキーワードは同時に指定できません", sc);
                        }
                    }
                    if (ret.Global)
                    {
                        throw new CodeEE(keyword + "とGLOBALキーワードは同時に指定できません", sc);
                    }
                    if (ret.CharaData)
                    {
                        throw new CodeEE(keyword + "キーワードが二重に指定されています", sc);
                    }
                    ret.CharaData = true;
                    break;

                default:
                    ret.Name = keyword;
                    goto whilebreak;
                }
            }
whilebreak:
            if (ret.Name == null)
            {
                throw new CodeEE(keyword + "の後に有効な変数名が指定されていません", sc);
            }
            string errMes   = "";
            int    errLevel = -1;

            if (isPrivate)
            {
                GlobalStatic.IdentifierDictionary.CheckUserPrivateVarName(ref errMes, ref errLevel, ret.Name);
            }
            else
            {
                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 <int> sizeNum = new List <int>();

            if (wc.EOL)            //サイズ省略
            {
                if (ret.Const)
                {
                    throw new CodeEE("CONSTキーワードが指定されていますが初期値が設定されていません");
                }
                sizeNum.Add(1);
            }
            else if (wc.Current.Type == ',')            //サイズ指定
            {
                while (!wc.EOL)
                {
                    if (wc.Current.Type == '=')                    //サイズ指定解読完了&初期値指定
                    {
                        break;
                    }
                    if (wc.Current.Type != ',')
                    {
                        throw new CodeEE("書式が間違っています", sc);
                    }
                    wc.ShiftNext();
                    if (ret.Reference)                    //参照型の場合は要素数不要
                    {
                        sizeNum.Add(0);
                        if (wc.EOL)
                        {
                            break;
                        }
                        if (wc.Current.Type == ',')
                        {
                            continue;
                        }
                    }
                    if (wc.EOL)
                    {
                        throw new CodeEE("カンマの後に有効な定数式が指定されていません", sc);
                    }
                    IOperandTerm arg      = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.Comma_Assignment);
                    SingleTerm   sizeTerm = arg.Restructure(null) as SingleTerm;
                    if ((sizeTerm == null) || (sizeTerm.GetOperandType() != typeof(Int64)))
                    {
                        throw new CodeEE("カンマの後に有効な定数式が指定されていません", sc);
                    }
                    if (ret.Reference)                    //参照型には要素数指定不可(0にするか書かないかどっちか
                    {
                        if (sizeTerm.Int != 0)
                        {
                            throw new CodeEE("参照型変数にはサイズを指定できません(サイズを省略するか0を指定してください)", sc);
                        }

                        continue;
                    }
                    else if ((sizeTerm.Int <= 0) || (sizeTerm.Int > 1000000))
                    {
                        throw new CodeEE("ユーザー定義変数のサイズは1以上1000000以下でなければなりません", sc);
                    }
                    sizeNum.Add((int)sizeTerm.Int);
                }
            }


            if (wc.Current.Type != '=')            //初期値指定なし
            {
                if (ret.Const)
                {
                    throw new CodeEE("CONSTキーワードが指定されていますが初期値が設定されていません");
                }
            }
            else            //初期値指定あり
            {
                if (((OperatorWord)wc.Current).Code != OperatorCode.Assignment)
                {
                    throw new CodeEE("予期しない演算子を発見しました");
                }
                if (ret.Reference)
                {
                    throw new CodeEE("参照型変数には初期値を設定できません");
                }
                if (sizeNum.Count >= 2)
                {
                    throw new CodeEE("多次元変数には初期値を設定できません");
                }
                if (ret.CharaData)
                {
                    throw new CodeEE("キャラ型変数には初期値を設定できません");
                }
                int size = 0;
                if (sizeNum.Count == 1)
                {
                    size = sizeNum[0];
                }
                wc.ShiftNext();
                IOperandTerm[] terms = ExpressionParser.ReduceArguments(wc, ArgsEndWith.EoL, false);
                if (terms.Length == 0)
                {
                    throw new CodeEE("配列の初期値は省略できません");
                }
                if (size > 0)
                {
                    if (terms.Length > size)
                    {
                        throw new CodeEE("初期値の数が配列のサイズを超えています");
                    }
                    if (ret.Const && terms.Length != size)
                    {
                        throw new CodeEE("定数の初期値の数が配列のサイズと一致しません");
                    }
                }
                if (dims)
                {
                    ret.DefaultStr = new string[terms.Length];
                }
                else
                {
                    ret.DefaultInt = new Int64[terms.Length];
                }

                for (int i = 0; i < terms.Length; i++)
                {
                    if (terms[i] == null)
                    {
                        throw new CodeEE("配列の初期値は省略できません");
                    }
                    terms[i] = terms[i].Restructure(GlobalStatic.EMediator);
                    SingleTerm sTerm = terms[i] as SingleTerm;
                    if (sTerm == null)
                    {
                        throw new CodeEE("配列の初期値には定数のみ指定できます");
                    }
                    if (dims != sTerm.IsString)
                    {
                        throw new CodeEE("変数の型と初期値の型が一致していません");
                    }
                    if (dims)
                    {
                        ret.DefaultStr[i] = sTerm.Str;
                    }
                    else
                    {
                        ret.DefaultInt[i] = sTerm.Int;
                    }
                }
                if (sizeNum.Count == 0)
                {
                    sizeNum.Add(terms.Length);
                }
            }
            if (!wc.EOL)
            {
                throw new CodeEE("書式が間違っています", sc);
            }

            if (sizeNum.Count == 0)
            {
                sizeNum.Add(1);
            }

            ret.Private   = isPrivate;
            ret.Dimension = sizeNum.Count;
            if (ret.Const && ret.Dimension > 1)
            {
                throw new CodeEE("CONSTキーワードが指定された変数を多次元配列にはできません");
            }
            if (ret.CharaData && ret.Dimension > 2)
            {
                throw new CodeEE("3次元以上のキャラ型変数を宣言することはできません", sc);
            }
            if (ret.Dimension > 3)
            {
                throw new CodeEE("4次元以上の配列変数を宣言することはできません", sc);
            }
            ret.Lengths = new int[sizeNum.Count];
            if (ret.Reference)
            {
                return(ret);
            }
            Int64 totalBytes = 1;

            for (int i = 0; i < sizeNum.Count; i++)
            {
                ret.Lengths[i] = sizeNum[i];
                totalBytes    *= ret.Lengths[i];
            }
            if ((totalBytes <= 0) || (totalBytes > 1000000))
            {
                throw new CodeEE("ユーザー定義変数のサイズは1以上1000000以下でなければなりません", sc);
            }
            if (!isPrivate && ret.Save && !Config.SystemSaveInBinary)
            {
                if (dims && ret.Dimension > 1)
                {
                    throw new CodeEE("文字列型の多次元配列変数にSAVEDATAフラグを付ける場合には「バイナリ型セーブ」オプションが必須です", sc);
                }
                else if (ret.CharaData)
                {
                    throw new CodeEE("キャラ型変数にSAVEDATAフラグを付ける場合には「バイナリ型セーブ」オプションが必須です", sc);
                }
            }
            return(ret);
        }
Beispiel #8
0
        public static LogicalLine ParseLine(StringStream stream, ScriptPosition position, EmueraConsole console)
        {
            int    lineNo = position.LineNo;
            string errMes = "";

            LexicalAnalyzer.SkipWhiteSpace(stream);            //先頭のホワイトスペースを読み飛ばす
            if (stream.EOS)
            {
                return(null);
            }
            //コメント行かどうかはここに来る前に判定しておく
            try
            {
                #region 前置インクリメント、デクリメント行
                if (stream.Current == '+' || stream.Current == '-')
                {
                    char           op   = stream.Current;
                    WordCollection wc   = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, LexAnalyzeFlag.None);
                    OperatorWord   opWT = wc.Current as OperatorWord;
                    if ((opWT == null) || ((opWT.Code != OperatorCode.Increment) && (opWT.Code != OperatorCode.Decrement)))
                    {
                        if (op == '+')
                        {
                            errMes = "行が\'+\'から始まっていますが、インクリメントではありません";
                        }
                        else
                        {
                            errMes = "行が\'-\'から始まっていますが、デクリメントではありません";
                        }
                        goto err;
                    }
                    wc.ShiftNext();
                    //token = EpressionParser.単語一個分取得(wc)
                    //token非変数
                    //token文字列形
                    //token変更不可能
                    //if (wc != EOS)
                    //
                    return(new InstructionLine(position, FunctionIdentifier.SETFunction, opWT.Code, wc, null));
                }
                #endregion
                IdentifierWord idWT = LexicalAnalyzer.ReadFirstIdentifierWord(stream);
                if (idWT != null)
                {
                    FunctionIdentifier func = GlobalStatic.IdentifierDictionary.GetFunctionIdentifier(idWT.Code);
                    //命令文
                    if (func != null)                    //関数文
                    {
                        if (stream.EOS)                  //引数の無い関数
                        {
                            return(new InstructionLine(position, func, stream));
                        }
                        if ((stream.Current != ';') && (stream.Current != ' ') && (stream.Current != '\t') && (!Config.SystemAllowFullSpace || (stream.Current != ' ')))
                        {
                            if (stream.Current == ' ')
                            {
                                errMes = "命令で行が始まっていますが、命令の直後に半角スペース・タブ以外の文字が来ています(この警告はシステムオプション「" + Config.GetConfigName(ConfigCode.SystemAllowFullSpace) + "」により無視できます)";
                            }
                            else
                            {
                                errMes = "命令で行が始まっていますが、命令の直後に半角スペース・タブ以外の文字が来ています";
                            }
                            goto err;
                        }
                        stream.ShiftNext();
                        return(new InstructionLine(position, func, stream));
                    }
                }
                LexicalAnalyzer.SkipWhiteSpace(stream);
                if (stream.EOS)
                {
                    errMes = "解釈できない行です";
                    goto err;
                }
                //命令行ではない→代入行のはず
                stream.Seek(0, System.IO.SeekOrigin.Begin);
                OperatorCode   assignOP = OperatorCode.NULL;
                WordCollection wc1      = LexicalAnalyzer.Analyse(stream, LexEndWith.Operator, LexAnalyzeFlag.None);
                //if (idWT != null)
                //	wc1.Collection.Insert(0, idWT);
                try
                {
                    assignOP = LexicalAnalyzer.ReadAssignmentOperator(stream);
                }
                catch (CodeEE)
                {
                    errMes = "解釈できない行です";
                    goto err;
                }
                //eramaker互換警告
                //stream.Jump(-1);
                //if ((stream.Current != ' ') && (stream.Current != '\t'))
                //{
                //	errMes = "変数で行が始まっていますが、演算子の直前に半角スペースまたはタブがありません";
                //	goto err;
                //}
                //stream.ShiftNext();


                if (assignOP == OperatorCode.Equal)
                {
                    if (console != null)
                    {
                        ParserMediator.Warn("代入演算子に\"==\"が使われています", position, 0);
                    }
                    //"=="を代入文に使うのは本当はおかしいが結構使われているので仕様にする
                    assignOP = OperatorCode.Assignment;
                }
                return(new InstructionLine(position, FunctionIdentifier.SETFunction, assignOP, wc1, stream));

err:
                return(new InvalidLine(position, errMes));
            }
            catch (CodeEE e)
            {
                System.Media.SystemSounds.Hand.Play();
                return(new InvalidLine(position, e.Message));
            }
        }