示例#1
0
        /// <summary>
        /// 単語の取得。マクロ展開あり。関数型マクロ展開なし
        /// </summary>
        /// <param name="st"></param>
        /// <returns></returns>
        public static IdentifierWord ReadSingleIdentifierWord(StringStream st)
        {
            string str = ReadSingleIdentifier(st);

            if (string.IsNullOrEmpty(str))
            {
                return(null);
            }
            if (UseMacro)
            {
                int i = 0;
                while (true)
                {
                    DefineMacro macro = GlobalStatic.IdentifierDictionary.GetMacro(str);
                    i++;
                    if (i > MAX_EXPAND_MACRO)
                    {
                        throw new CodeEE("マクロの展開数が1文あたりの上限値" + MAX_EXPAND_MACRO.ToString() + "を超えました(自己参照・循環参照のおそれ)");
                    }
                    if (macro == null)
                    {
                        break;
                    }
                    if (macro.IDWord != null)
                    {
                        throw new CodeEE("マクロ" + macro.Keyword + "はこの文脈では使用できません(1単語に置き換えるマクロのみが使用できます)");
                    }
                    str = macro.IDWord.Code;
                }
            }
            return(new IdentifierWord(str));
        }
        public DefineMacro GetMacro(string key)
        {
            if (Config.ICVariable)
            {
                key = key.ToUpper();
            }
            DefineMacro dm = null;

            if (macroDic.TryGetValue(key, out dm))
            {
                return(dm);
            }
            return(null);
        }
示例#3
0
        private static WordCollection expandMacro(WordCollection wc)
        {
            //マクロ展開
            wc.Pointer = 0;
            int count = 0;

            while (!wc.EOL)
            {
                IdentifierWord word = wc.Current as IdentifierWord;
                if (word == null)
                {
                    wc.ShiftNext();
                    continue;
                }
                string      idStr = word.Code;
                DefineMacro macro = GlobalStatic.IdentifierDictionary.GetMacro(idStr);
                if (macro == null)
                {
                    wc.ShiftNext();
                    continue;
                }
                count++;
                if (count > MAX_EXPAND_MACRO)
                {
                    throw new CodeEE("マクロの展開数が1文あたりの上限" + MAX_EXPAND_MACRO.ToString() + "を超えました(自己参照・循環参照のおそれ)");
                }
                if (!macro.HasArguments)
                {
                    wc.Remove();
                    wc.InsertRange(macro.Statement);
                    continue;
                }
                //関数型マクロ
                wc = expandFunctionlikeMacro(macro, wc);
            }
            wc.Pointer = 0;
            return(wc);
        }
示例#4
0
        private static WordCollection expandFunctionlikeMacro(DefineMacro macro, WordCollection wc)
        {
            int macroStart = wc.Pointer;

            wc.ShiftNext();
            SymbolWord symbol = wc.Current as SymbolWord;

            if (symbol == null || symbol.Type != '(')
            {
                throw new CodeEE("関数形式のマクロ" + macro.Keyword + "に引数がありません");
            }
            WordCollection macroWC = macro.Statement.Clone();

            WordCollection[] args = new WordCollection[macro.ArgCount];
            //引数部読み取りループ
            for (int i = 0; i < macro.ArgCount; i++)
            {
                int macroNestBracketS = 0;
                args[i] = new WordCollection();
                while (true)
                {
                    wc.ShiftNext();
                    if (wc.EOL)
                    {
                        throw new CodeEE("関数形式のマクロ" + macro.Keyword + "の用法が正しくありません");
                    }
                    symbol = wc.Current as SymbolWord;
                    if (symbol == null)
                    {
                        args[i].Add(wc.Current);
                        continue;
                    }
                    switch (symbol.Type)
                    {
                    case '(': macroNestBracketS++; break;

                    case ')':
                        if (macroNestBracketS > 0)
                        {
                            macroNestBracketS--;
                            break;
                        }
                        if (i != macro.ArgCount - 1)
                        {
                            throw new CodeEE("関数形式のマクロ" + macro.Keyword + "の引数の数が正しくありません");
                        }
                        goto exitfor;

                    case ',':
                        if (macroNestBracketS == 0)
                        {
                            goto exitwhile;
                        }
                        break;
                    }
                    args[i].Add(wc.Current);
                }
exitwhile:
                if (args[i].Collection.Count == 0)
                {
                    throw new CodeEE("関数形式のマクロ" + macro.Keyword + "の引数を省略することはできません");
                }
                continue;
            }
            //引数部読み取りループ終端
exitfor:
            symbol = wc.Current as SymbolWord;
            if (symbol == null || symbol.Type != ')')
            {
                throw new CodeEE("関数形式のマクロ" + macro.Keyword + "の用法が正しくありません");
            }
            int macroLength = wc.Pointer - macroStart + 1;

            wc.Pointer = macroStart;
            for (int j = 0; j < macroLength; j++)
            {
                wc.Collection.RemoveAt(macroStart);
            }
            while (!macroWC.EOL)
            {
                MacroWord w = macroWC.Current as MacroWord;
                if (w == null)
                {
                    macroWC.ShiftNext();
                    continue;
                }
                macroWC.Remove();
                macroWC.InsertRange(args[w.Number]);
                macroWC.Pointer += args[w.Number].Collection.Count;
            }
            wc.InsertRange(macroWC);
            wc.Pointer = macroStart;
            return(wc);
        }
示例#5
0
 internal void AddMacro(DefineMacro mac)
 {
     nameDic.Add(mac.Keyword, DefinedNameType.UserMacro);
     macroDic.Add(mac.Keyword, mac);
 }
示例#6
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);呼び出し前に行う。
            var srcID = LexicalAnalyzer.ReadSingleIdentifier(st);

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

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

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

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

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

            var argID = new List <string>();

            if (hasArg)         //関数型マクロの引数解析
            {
                wc.ShiftNext(); //'('を読み飛ばす
                if (wc.Current.Type == ')')
                {
                    throw new CodeEE("関数型マクロの引数を0個にすることはできません", position);
                }
                while (!wc.EOL)
                {
                    var word = wc.Current as IdentifierWord;
                    if (word == null)
                    {
                        throw new CodeEE("置換元の引数指定の書式が間違っています", position);
                    }
                    word.SetIsMacro();
                    var 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);
            }
            var destWc = new WordCollection();

            while (!wc.EOL)
            {
                destWc.Add(wc.Current);
                wc.ShiftNext();
            }
            if (hasArg) //関数型マクロの引数セット
            {
                while (!destWc.EOL)
                {
                    var word = destWc.Current as IdentifierWord;
                    if (word == null)
                    {
                        destWc.ShiftNext();
                        continue;
                    }
                    for (var 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);
            }
            var mac = new DefineMacro(srcID, destWc, argID.Count);

            idDic.AddMacro(mac);
        }