/// <summary> /// \@直後からの開始、\@の直後がCurrentになる /// </summary> /// <param name="st"></param> /// <returns></returns> public static YenAtSubWord AnalyseYenAt(StringStream st) { WordCollection w = Analyse(st, LexEndWith.Question, LexAnalyzeFlag.None); if (st.Current != '?') { throw new CodeEE("\'\\@\'が使われましたが対応する\'?\'が見つかりません"); } st.ShiftNext(); StrFormWord left = AnalyseFormattedString(st, FormStrEndWith.Sharp, true); if (st.Current != '#') { if (st.Current != '@') { throw new CodeEE("\'\\@\',\'?\'が使われましたが対応する\'#\'が見つかりません"); } st.ShiftNext(); ParserMediator.Warn("\'\\@\',\'?\'が使われましたが対応する\'#\'が見つかりません", GlobalStatic.Process.GetScaningLine(), 1, false, false); return(new YenAtSubWord(w, left, null)); } st.ShiftNext(); StrFormWord right = AnalyseFormattedString(st, FormStrEndWith.YenAt, true); if (st.Current != '@') { throw new CodeEE("\'\\@\',\'?\',\'#\'が使われましたが対応する\'\\@\'が見つかりません"); } st.ShiftNext(); return(new YenAtSubWord(w, left, right)); }
/// <summary> /// 識別子を読み終えた状態からの解析 /// </summary> /// <param name="st"></param> /// <returns></returns> public static VariableTerm ReduceVariable(VariableToken id, WordCollection wc) { IOperandTerm operand = null; IOperandTerm op1 = null; IOperandTerm op2 = null; IOperandTerm op3 = null; int i = 0; while (true) { if (wc.Current.Type != ':') break; if (i >= 3) throw new CodeEE(id.Code.ToString() + "の引数が多すぎます"); wc.ShiftNext(); operand = ExpressionParser.ReduceVariableArgument(wc, id.Code); if (i == 0) op1 = operand; else if (i == 1) op2 = operand; else if (i == 2) op3 = operand; i++; } return ReduceVariable(id, op1, op2, op3); }
public WordCollection Clone() { WordCollection ret = new WordCollection(); for(int i = 0;i < this.Collection.Count;i++) { ret.Collection.Add(this.Collection[i]); } return ret; }
public WordCollection Clone() { var ret = new WordCollection(); for (var i = 0; i < Collection.Count; i++) { ret.Collection.Add(Collection[i]); } return(ret); }
public WordCollection Clone() { WordCollection ret = new WordCollection(); for (int i = 0; i < this.Collection.Count; i++) { ret.Collection.Add(this.Collection[i]); } return(ret); }
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; }
/// <summary> /// まだ最初の識別子を読んでいない状態から決め打ちで変数を解読する /// </summary> /// <param name="st"></param> /// <returns></returns> public static VariableTerm ReduceVariable(WordCollection wc) { IdentifierWord id = wc.Current as IdentifierWord; if (id == null) return null; wc.ShiftNext(); VariableToken vid = ExpressionParser.ReduceVariableIdentifier(wc, id.Code); if (vid == null) throw new CodeEE("\"" + id.Code + "\"は解釈できない識別子です"); return ReduceVariable(vid, wc); }
public WordCollection Clone(int start, int count) { WordCollection ret = new WordCollection(); if (start > this.Collection.Count) return ret; int end = start + count; if (end > this.Collection.Count) end = this.Collection.Count; for(int i = start;i < end;i++) { ret.Collection.Add(this.Collection[i]); } return ret; }
public WordCollection Clone(int start, int count) { var ret = new WordCollection(); if (start > Collection.Count) { return(ret); } var end = start + count; if (end > Collection.Count) { end = Collection.Count; } for (var i = start; i < end; i++) { ret.Collection.Add(Collection[i]); } return(ret); }
public WordCollection Clone(int start, int count) { WordCollection ret = new WordCollection(); if (start > this.Collection.Count) { return(ret); } int end = start + count; if (end > this.Collection.Count) { end = this.Collection.Count; } for (int i = start; i < end; i++) { ret.Collection.Add(this.Collection[i]); } return(ret); }
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 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; }
public void Add(WordCollection wc) { Collection.AddRange(wc.Collection); }
private static IOperandTerm reduceIdentifier(WordCollection wc, string idStr, VariableCode varCode) { wc.ShiftNext(); SymbolWord symbol = wc.Current as SymbolWord; if (symbol != null && (symbol.Type == '(' || symbol.Type == '[') ) {//関数 wc.ShiftNext(); if (symbol.Type == '[') throw new CodeEE("[]を使った機能はまだ実装されていません"); //throw new NotImplementedException(); IOperandTerm[] args = ReduceArguments(wc, ArgsEndWith.RightParenthesis, false); IOperandTerm mToken = GlobalStatic.IdentifierDictionary.GetFunctionMethod(GlobalStatic.LabelDictionary, idStr, args); if (mToken == null) { if (!Program.AnalysisMode) GlobalStatic.IdentifierDictionary.ThrowException(idStr, true); else { if (GlobalStatic.tempDic.ContainsKey(idStr)) GlobalStatic.tempDic[idStr]++; else GlobalStatic.tempDic.Add(idStr, 1); return new NullTerm(0); } } return mToken; } else {//変数 or キーワード VariableToken id = ReduceVariableIdentifier(wc, idStr); if (varCode != VariableCode.__NULL__) { if (id == null) { if (GlobalStatic.ConstantData.isDefined(varCode, idStr)) return new SingleTerm(idStr); else GlobalStatic.IdentifierDictionary.ThrowException(idStr, false); } else { return VariableParser.ReduceVariable(id, null, null, null); } } else { if (id == null) GlobalStatic.IdentifierDictionary.ThrowException(idStr, false); return VariableParser.ReduceVariable(id, wc); } } throw new ExeEE("エラー投げ損ねた"); }
///// <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; }
public PercentSubWord(WordCollection w) : base(w) { }
public void Add(WordCollection wc) { Collection.AddRange(wc.Collection); }
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); }
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); }
/// <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; }
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; }
protected SubWord(WordCollection w) { words = w; }
/// <summary> /// 解析できるものは関数宣言や式のみ。FORM文字列や普通の文字列を送ってはいけない /// return時にはendWithの文字がCurrentになっているはず。終端の適切さの検証は呼び出し元が行う。 /// </summary> /// <returns></returns> public static WordCollection Analyse(StringStream st, LexEndWith endWith, bool isPrintV, bool allowAssignment) { WordCollection ret = new WordCollection(); int nestBracketS = 0; //int nestBracketM = 0; int nestBracketL = 0; while (true) { switch (st.Current) { case '\n': case '\0': goto end; case ' ': case '\t': st.ShiftNext(); continue; case ' ': if (!Config.SystemAllowFullSpace) throw new CodeEE("字句解析中に予期しない全角スペースを発見しました"); st.ShiftNext(); continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ret.Add(new LiteralIntegerWord(ReadInt64(st, false))); break; case '+': case '-': case '*': case '/': case '%': case '=': case '!': case '<': case '>': case '|': case '&': case '^': case '~': case '?': case '#': if ((nestBracketS == 0) && (nestBracketL == 0)) { if (endWith == LexEndWith.Operator) goto end;//代入演算子のはずである。呼び出し元がチェックするはず else if ((endWith == LexEndWith.Percent) && (st.Current == '%')) goto end; else if ((endWith == LexEndWith.Question) && (st.Current == '?')) goto end; } ret.Add(new OperatorWord(ReadOperator(st, allowAssignment))); break; case ')': ret.Add(new SymbolWord(')')); nestBracketS--; st.ShiftNext(); continue; case ']': ret.Add(new SymbolWord(']')); nestBracketL--; st.ShiftNext(); continue; case '(': ret.Add(new SymbolWord('(')); nestBracketS++; st.ShiftNext(); continue; case '[': if (st.Next == '[') { //throw new CodeEE("字句解析中に予期しない文字'[['を発見しました"); ////1808alpha006 rename処理変更 //1808beta009 ここだけ戻す //現在の処理だとここに来た時点でrename失敗確定だが警告内容を元に戻すため if (ParserMediator.RenameDic == null) throw new CodeEE("字句解析中に予期しない文字\"[[\"を発見しました"); int start = st.CurrentPosition; int find = st.Find("]]"); if (find <= 2) { if (find == 2) throw new CodeEE("空の[[]]です"); else throw new CodeEE("対応する\"]]\"のない\"[[\"です"); } string key = st.Substring(start, find + 2); string value = null; if (!ParserMediator.RenameDic.TryGetValue(key, out value)) throw new CodeEE("字句解析中に置換(rename)できない符号" + key + "を発見しました"); st.Replace(start, find + 2, value); continue;//その場から再度解析スタート } ret.Add(new SymbolWord('[')); nestBracketL++; st.ShiftNext(); continue; case ':': ret.Add(new SymbolWord(':')); st.ShiftNext(); continue; case ',': if ((endWith == LexEndWith.Comma) && (nestBracketS == 0))// && (nestBracketL == 0)) goto end; ret.Add(new SymbolWord(',')); st.ShiftNext(); continue; //case '}': ret.Add(new SymbolWT('}')); nestBracketM--; continue; //case '{': ret.Add(new SymbolWT('{')); nestBracketM++; continue; case '\'': if (!isPrintV) throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); st.ShiftNext(); ret.Add(new LiteralStringWord(ReadString(st, StrEndWith.Comma))); if (st.Current == ',') goto case ',';//続きがあるなら,の処理へ。それ以外は行終端のはず goto end; case '}': if (endWith == LexEndWith.RightCurlyBrace) goto end; throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); case '\"': st.ShiftNext(); ret.Add(new LiteralStringWord(ReadString(st, StrEndWith.DoubleQuotation))); if (st.Current != '\"') throw new CodeEE("\"が閉じられていません"); st.ShiftNext(); break; case '@': if (st.Next != '\"') { ret.Add(new SymbolWord('@')); st.ShiftNext(); continue; } st.ShiftNext(); st.ShiftNext(); ret.Add(AnalyseFormattedString(st, FormStrEndWith.DoubleQuotation, false)); if (st.Current != '\"') throw new CodeEE("\"が閉じられていません"); st.ShiftNext(); break; case '\\': if (st.Next != '@') throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); { st.Jump(2); ret.Add(new StrFormWord(new string[] { "", "" }, new SubWord[] { AnalyseYenAt(st) })); } break; case '{': case '$': case '.': throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); case ';'://1807 行中コメント if (st.CurrentEqualTo(";#;") && Program.DebugMode) { st.Jump(3); break; } else if (st.CurrentEqualTo(";!;")) { st.Jump(3); break; } st.Seek(0, System.IO.SeekOrigin.End); goto end; default: { ret.Add(new IdentifierWord(ReadSingleIdentifier(st))); break; } } } end: if ((nestBracketS != 0) || (nestBracketL != 0)) { if (nestBracketS < 0) throw new CodeEE("字句解析中に対応する'('のない')'を発見しました"); else if (nestBracketS > 0) throw new CodeEE("字句解析中に対応する')'のない'('を発見しました"); if (nestBracketL < 0) throw new CodeEE("字句解析中に対応する'['のない']'を発見しました"); else if (nestBracketL > 0) throw new CodeEE("字句解析中に対応する']'のない'['を発見しました"); } if (UseMacro) return expandMacro(ret); return ret; }
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; }
public YenAtSubWord(WordCollection w, StrFormWord fsLeft, StrFormWord fsRight) : base(w) { left = fsLeft; right = fsRight; }
public void InsertRange(WordCollection wc) { Collection.InsertRange(Pointer, wc.Collection); }
protected SubWord(WordCollection w) { words = w; }
public static UserDefinedVariableData Create(WordCollection wc, bool dims, bool isPrivate, ScriptPosition sc) { string dimtype = dims ? "#DIM" : "#DIMS"; UserDefinedVariableData ret = new UserDefinedVariableData(); ret.TypeStr = dims; IdentifierWord idw = null; bool staticDefined = false; 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 "REF": //TODO 1808beta009 throw new CodeEE("未実装の機能です", sc); if (!isPrivate) throw new CodeEE("広域変数の宣言に" + keyword + "キーワードは指定できません", sc); if (staticDefined && ret.Static) throw new CodeEE("STATICとREFキーワードは同時に指定できません", 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 (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 (staticDefined) if (!ret.Static) throw new CodeEE("STATICとDYNAMICキーワードは同時に指定できません", sc); else throw new CodeEE(keyword + "キーワードが二重に指定されています", sc); if (ret.Reference) throw new CodeEE("STATICとREFキーワードは同時に指定できません", sc); staticDefined = true; ret.Static = true; break; case "GLOBAL": if (isPrivate) throw new CodeEE("ローカル変数の宣言に" + keyword + "キーワードは指定できません", sc); if (ret.Global) throw new CodeEE(keyword + "キーワードが二重に指定されています", sc); ret.Global = true; break; case "SAVEDATA": if (isPrivate) throw new CodeEE("ローカル変数の宣言に" + keyword + "キーワードは指定できません", sc); if (ret.Save) throw new CodeEE(keyword + "キーワードが二重に指定されています", sc); ret.Save = true; break; case "CHARDATA": throw new CodeEE("キャラ変数の宣言は実装されていません", sc); 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>(); while (!wc.EOL) { if (wc.Current.Type != ',') throw new CodeEE("書式が間違っています", sc); wc.ShiftNext(); if (ret.Reference)//参照型の場合は要素数不要 { if (wc.EOL) break; if (wc.Current.Type == ',') { sizeNum.Add(0); continue; } } if (wc.EOL) throw new CodeEE("カンマの後に有効な定数式が指定されていません", sc); IOperandTerm arg = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.Comma); 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 (sizeNum.Count == 0) sizeNum.Add(1); ret.Private = isPrivate; ret.Dimension = sizeNum.Count; 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 && dims && ret.Dimension > 1 && ret.Save && !Config.SystemSaveInBinary) throw new CodeEE("文字列型の多次元配列変数にSAVEDATAフラグを付ける場合には「バイナリ型セーブ」オプションが必要です", sc); return ret; }
//#define FOO (~~) id to wc //#define BAR($1) (~~) idwithargs to wc(replaced) //#diseble FOOBAR //#dim piyo, i //#sdim 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(); bool hasArg = st.Current == '(';//引数を指定する場合には直後に(が続いていなければならない。ホワイトスペースも禁止。 //1808a3 代入演算子許可(関数宣言用) WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, false, true); 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>(); 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; } } 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 void InsertRange(WordCollection wc) { Collection.InsertRange(Pointer, wc.Collection); }
/// <summary> /// カンマで区切られた引数を一括して取得。 /// return時にはendWithの次の文字がCurrentになっているはず。終端の適切さの検証はExpressionParserがが行う。 /// 呼び出し元はCodeEEを適切に処理すること /// </summary> /// <returns></returns> public static IOperandTerm[] ReduceArguments(WordCollection wc, ArgsEndWith endWith, bool isDefine) { 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; }
public static IOperandTerm ReduceVariableArgument(WordCollection wc, VariableCode varCode) { IOperandTerm ret = reduceTerm(wc, false, TermEndWith.EoL, varCode); if(ret == null) throw new CodeEE("変数の:の後に引数がありません"); return ret; }
/// <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(); }
public CurlyBraceSubWord(WordCollection w) : base(w) { }
public CurlyBraceSubWord(WordCollection w) : base(w) { }
public YenAtSubWord(WordCollection w, StrFormWord fsLeft, StrFormWord fsRight) : base(w) { left = fsLeft; right = fsRight; }
public PercentSubWord(WordCollection w) : base(w) { }
/// <summary> /// 解析できるものは関数宣言や式のみ。FORM文字列や普通の文字列を送ってはいけない /// return時にはendWithの文字がCurrentになっているはず。終端の適切さの検証は呼び出し元が行う。 /// </summary> /// <returns></returns> public static WordCollection Analyse(StringStream st, LexEndWith endWith, LexAnalyzeFlag flag) { WordCollection ret = new WordCollection(); int nestBracketS = 0; //int nestBracketM = 0; int nestBracketL = 0; while (true) { switch (st.Current) { case '\n': case '\0': goto end; case ' ': case '\t': st.ShiftNext(); continue; case ' ': if (!Config.SystemAllowFullSpace) { throw new CodeEE("字句解析中に予期しない全角スペースを発見しました(この警告はシステムオプション「" + Config.GetConfigName(ConfigCode.SystemAllowFullSpace) + "」により無視できます)"); } st.ShiftNext(); continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ret.Add(new LiteralIntegerWord(ReadInt64(st, false))); break; case '>': if (endWith == LexEndWith.GreaterThan) { goto end; } goto case '+'; case '+': case '-': case '*': case '/': case '%': case '=': case '!': case '<': case '|': case '&': case '^': case '~': case '?': case '#': if ((nestBracketS == 0) && (nestBracketL == 0)) { if (endWith == LexEndWith.Operator) { goto end; //代入演算子のはずである。呼び出し元がチェックするはず } else if ((endWith == LexEndWith.Percent) && (st.Current == '%')) { goto end; } else if ((endWith == LexEndWith.Question) && (st.Current == '?')) { goto end; } } ret.Add(new OperatorWord(ReadOperator(st, (flag & LexAnalyzeFlag.AllowAssignment) == LexAnalyzeFlag.AllowAssignment))); break; case ')': ret.Add(new SymbolWord(')')); nestBracketS--; st.ShiftNext(); continue; case ']': ret.Add(new SymbolWord(']')); nestBracketL--; st.ShiftNext(); continue; case '(': ret.Add(new SymbolWord('(')); nestBracketS++; st.ShiftNext(); continue; case '[': if (st.Next == '[') { //throw new CodeEE("字句解析中に予期しない文字'[['を発見しました"); ////1808alpha006 rename処理変更 //1808beta009 ここだけ戻す //現在の処理だとここに来た時点でrename失敗確定だが警告内容を元に戻すため if (ParserMediator.RenameDic == null) { throw new CodeEE("字句解析中に予期しない文字\"[[\"を発見しました"); } int start = st.CurrentPosition; int find = st.Find("]]"); if (find <= 2) { if (find == 2) { throw new CodeEE("空の[[]]です"); } else { throw new CodeEE("対応する\"]]\"のない\"[[\"です"); } } string key = st.Substring(start, find + 2); //1810 ここまでで置換できなかったものは強制エラーにする //行連結前に置換不能で行連結より置換することができるようになったものまで置換されていたため throw new CodeEE("字句解析中に置換(rename)できない符号" + key + "を発見しました"); //string value = null; //if (!ParserMediator.RenameDic.TryGetValue(key, out value)) // throw new CodeEE("字句解析中に置換(rename)できない符号" + key + "を発見しました"); //st.Replace(start, find + 2, value); //continue;//その場から再度解析スタート } ret.Add(new SymbolWord('[')); nestBracketL++; st.ShiftNext(); continue; case ':': ret.Add(new SymbolWord(':')); st.ShiftNext(); continue; case ',': if ((endWith == LexEndWith.Comma) && (nestBracketS == 0)) // && (nestBracketL == 0)) { goto end; } ret.Add(new SymbolWord(',')); st.ShiftNext(); continue; //case '}': ret.Add(new SymbolWT('}')); nestBracketM--; continue; //case '{': ret.Add(new SymbolWT('{')); nestBracketM++; continue; case '\'': if ((flag & LexAnalyzeFlag.AllowSingleQuotationStr) == LexAnalyzeFlag.AllowSingleQuotationStr) { st.ShiftNext(); ret.Add(new LiteralStringWord(ReadString(st, StrEndWith.SingleQuotation))); if (st.Current != '\'') { throw new CodeEE("\'が閉じられていません"); } st.ShiftNext(); break; } if ((flag & LexAnalyzeFlag.AnalyzePrintV) != LexAnalyzeFlag.AnalyzePrintV) { //AssignmentStr用特殊処理 代入文の代入演算子を探索中で'=の場合のみ許可 if ((endWith == LexEndWith.Operator) && (nestBracketS == 0) && (nestBracketL == 0) && st.Next == '=') { goto end; } throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); } st.ShiftNext(); ret.Add(new LiteralStringWord(ReadString(st, StrEndWith.Comma))); if (st.Current == ',') { goto case ','; //続きがあるなら,の処理へ。それ以外は行終端のはず } goto end; case '}': if (endWith == LexEndWith.RightCurlyBrace) { goto end; } throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); case '\"': st.ShiftNext(); ret.Add(new LiteralStringWord(ReadString(st, StrEndWith.DoubleQuotation))); if (st.Current != '\"') { throw new CodeEE("\"が閉じられていません"); } st.ShiftNext(); break; case '@': if (st.Next != '\"') { ret.Add(new SymbolWord('@')); st.ShiftNext(); continue; } st.ShiftNext(); st.ShiftNext(); ret.Add(AnalyseFormattedString(st, FormStrEndWith.DoubleQuotation, false)); if (st.Current != '\"') { throw new CodeEE("\"が閉じられていません"); } st.ShiftNext(); break; case '.': ret.Add(new SymbolWord('.')); st.ShiftNext(); continue; case '\\': if (st.Next != '@') { throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); } { st.Jump(2); ret.Add(new StrFormWord(new string[] { "", "" }, new SubWord[] { AnalyseYenAt(st) })); } break; case '{': case '$': throw new CodeEE("字句解析中に予期しない文字'" + st.Current + "'を発見しました"); case ';': //1807 行中コメント if (st.CurrentEqualTo(";#;") && Program.DebugMode) { st.Jump(3); break; } else if (st.CurrentEqualTo(";!;")) { st.Jump(3); break; } st.Seek(0, System.IO.SeekOrigin.End); goto end; default: { ret.Add(new IdentifierWord(ReadSingleIdentifier(st))); break; } } } end: if ((nestBracketS != 0) || (nestBracketL != 0)) { if (nestBracketS < 0) { throw new CodeEE("字句解析中に対応する'('のない')'を発見しました"); } else if (nestBracketS > 0) { throw new CodeEE("字句解析中に対応する')'のない'('を発見しました"); } if (nestBracketL < 0) { throw new CodeEE("字句解析中に対応する'['のない']'を発見しました"); } else if (nestBracketL > 0) { throw new CodeEE("字句解析中に対応する']'のない'['を発見しました"); } } if (UseMacro) { return(expandMacro(ret)); } return(ret); }
/// <summary> /// カンマで区切られたCASEの引数を一括して取得。行端で終わる。 /// </summary> /// <param name="st"></param> /// <returns></returns> public static CaseExpression[] ReduceCaseExpressions(WordCollection wc) { List<CaseExpression> terms = new List<CaseExpression>(); while (!wc.EOL) { terms.Add(reduceCaseExpression(wc)); wc.ShiftNext(); } CaseExpression[] ret = new CaseExpression[terms.Count]; terms.CopyTo(ret); return ret; }