/// <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); }
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); }
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); }
internal void AddMacro(DefineMacro mac) { nameDic.Add(mac.Keyword, DefinedNameType.UserMacro); macroDic.Add(mac.Keyword, mac); }
//#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); }