public LocalVariableToken GetNewLocalVariableToken(string subKey, FunctionLabelLine func) { LocalVariableToken ret = null; var newSize = 0; if (varCode == VariableCode.LOCAL) { newSize = func.LocalLength; } else if (varCode == VariableCode.LOCALS) { newSize = func.LocalsLength; } else if (varCode == VariableCode.ARG) { newSize = func.ArgLength; } else if (varCode == VariableCode.ARGS) { newSize = func.ArgsLength; } if (newSize > 0) { if (newSize < size && (varCode == VariableCode.ARG || varCode == VariableCode.ARGS)) { newSize = size; } ret = creater(varCode, subKey, newSize); } else if (newSize == 0) { ret = creater(varCode, subKey, size); } else { ret = creater(varCode, subKey, size); var line = GlobalStatic.Process.GetScaningLine(); if (line != null) { if (!func.IsSystem) { ParserMediator.Warn( "関数宣言に引数変数\"" + varCode + "\"が使われていない関数中で\"" + varCode + "\"が使われています(関数の引数以外の用途に使うことは推奨されません。代わりに#DIMの使用を検討してください)", line, 1, false, false); } else { ParserMediator.Warn( "システム関数" + func.LabelName + "中で\"" + varCode + "\"が使われています(関数の引数以外の用途に使うことは推奨されません。代わりに#DIMの使用を検討してください)", line, 1, false, false); } } //throw new CodeEE("この関数に引数変数\"" + varCode + "\"は定義されていません"); } localVarTokens.Add(subKey, ret); return(ret); }
/// <summary> /// エラーならnullを返す。 /// </summary> public static UserDefinedMethodTerm Create(FunctionLabelLine targetLabel, IOperandTerm[] srcArgs, out string errMes) { CalledFunction call = CalledFunction.CreateCalledFunctionMethod(targetLabel, targetLabel.LabelName); UserDefinedFunctionArgument arg = call.ConvertArg(srcArgs, out errMes); if (arg == null) { return(null); } return(new UserDefinedMethodTerm(arg, call.TopLabel.MethodType, call)); }
/// <summary> /// 戻り値と引数の数・型の完全一致が必要 /// </summary> /// <param name="call"></param> /// <returns>一致ならtrue</returns> internal bool MatchType(CalledFunction call) { FunctionLabelLine label = call.TopLabel; if (label.IsError) { return(false); } if (RetType != label.MethodType) { return(false); } if (ArgTypeList.Length != label.Arg.Length) { return(false); } for (int i = 0; i < ArgTypeList.Length; i++) { VariableToken vToken = label.Arg[i].Identifier; if (vToken.IsReference) { UserDifinedFunctionDataArgType type = UserDifinedFunctionDataArgType.__Ref; type += vToken.Dimension; if (vToken.IsInteger) { type |= UserDifinedFunctionDataArgType.Int; } else { type |= UserDifinedFunctionDataArgType.Str; } if (ArgTypeList[i] != type) { return(false); } } else { if (vToken.IsInteger && ArgTypeList[i] != UserDifinedFunctionDataArgType.Int) { return(false); } if (vToken.IsString && ArgTypeList[i] != UserDifinedFunctionDataArgType.Str) { return(false); } } } return(true); }
public void AddLabel(FunctionLabelLine point) { point.Index = count; point.FileIndex = currentFileCount; count++; string id = point.LabelName; if (labelAtDic.ContainsKey(id)) { labelAtDic[id].Add(point); } else { List<FunctionLabelLine> labelList = new List<FunctionLabelLine>(); labelList.Add(point); labelAtDic.Add(id, labelList); } }
public List <string> GetOverloadedList(LabelDictionary labelDic) { List <string> list = new List <string>(); foreach (KeyValuePair <string, FunctionMethod> pair in methodDic) { FunctionLabelLine func = labelDic.GetNonEventLabel(pair.Key); if (func == null) { continue; } if (!func.IsMethod) { continue; } list.Add(pair.Key); } return(list); }
public LocalVariableToken GetNewLocalVariableToken(string subKey, FunctionLabelLine func) { LocalVariableToken ret = null; int newSize = 0; if (varCode == VariableCode.LOCAL) newSize = func.LocalLength; else if (varCode == VariableCode.LOCALS) newSize = func.LocalsLength; else if (varCode == VariableCode.ARG) newSize = func.ArgLength; else if (varCode == VariableCode.ARGS) newSize = func.ArgsLength; if (newSize > 0) { if((newSize < size) && ((varCode == VariableCode.ARG) || (varCode == VariableCode.ARGS))) newSize = size; ret = creater(varCode, subKey, newSize); } else if (newSize == 0) ret = creater(varCode, subKey, size); else { ret = creater(varCode, subKey, size); LogicalLine line = GlobalStatic.Process.GetScaningLine(); if (line != null) { if (!func.IsSystem) ParserMediator.Warn("関数宣言に引数変数\"" + varCode + "\"が使われていない関数中で\"" + varCode + "\"が使われています(関数の引数以外の用途に使うことは推奨されません)", line, 1, false, false); else ParserMediator.Warn("システム関数" + func.LabelName + "中で\"" + varCode + "\"が使われています(関数の引数以外の用途に使うことは推奨されません)", line, 1, false, false); } //throw new CodeEE("この関数に引数変数\"" + varCode + "\"は定義されていません"); } localVarTokens.Add(subKey, ret); return ret; }
public static CalledFunction CreateCalledFunctionMethod(FunctionLabelLine labelline, string label) { CalledFunction called = new CalledFunction(label); called.TopLabel = labelline; called.CurrentLabel = labelline; called.returnAddress = null; return called; }
private void parseLabel(FunctionLabelLine label) { WordCollection wc = label.PopRowArgs(); string errMes = null; SingleTerm[] subNames = new SingleTerm[0]; VariableTerm[] args = new VariableTerm[0]; SingleTerm[] defs = new SingleTerm[0]; int maxArg = -1; int maxArgs = -1; //1807 非イベント関数のシステム関数については警告レベル低下&エラー解除&引数を設定するように。 if (label.IsEvent) { if (!wc.EOL) ParserMediator.Warn("イベント関数@" + label.LabelName + " に引数は設定できません", label, 2, true, false); //label.SubNames = subNames; label.Arg = args; label.Def = defs; label.ArgLength = -1; label.ArgsLength = -1; return; } if (!wc.EOL) { if (label.IsSystem) ParserMediator.Warn("システム関数@" + label.LabelName + " に引数が設定されています", label, 1, false, false); SymbolWord symbol = wc.Current as SymbolWord; wc.ShiftNext(); if (symbol == null) { errMes = "引数の書式が間違っています"; goto err; } if (symbol.Type == '[') { IOperandTerm[] subNamesRow = ExpressionParser.ReduceArguments(wc, ArgsEndWith.RightBracket, false); if (subNamesRow.Length == 0) { errMes = "関数定義の[]内の引数は空にできません"; goto err; } subNames = new SingleTerm[subNamesRow.Length]; for (int i = 0; i < subNamesRow.Length; i++) { if (subNamesRow[i] == null) { errMes = "関数定義の引数は省略できません"; goto err; } IOperandTerm term = subNamesRow[i].Restructure(exm); subNames[i] = term as SingleTerm; if (subNames[i] == null) { errMes = "関数定義の[]内の引数は定数のみ指定できます"; goto err; } } symbol = wc.Current as SymbolWord; if ((!wc.EOL) && (symbol == null)) { errMes = "引数の書式が間違っています"; goto err; } wc.ShiftNext(); } if (!wc.EOL) { IOperandTerm[] argsRow = null; if (symbol.Type == ',') argsRow = ExpressionParser.ReduceArguments(wc, ArgsEndWith.EoL, true); else if (symbol.Type == '(') argsRow = ExpressionParser.ReduceArguments(wc, ArgsEndWith.RightParenthesis, true); else { errMes = "引数の書式が間違っています"; goto err; } int length = argsRow.Length / 2; args = new VariableTerm[length]; defs = new SingleTerm[length]; for (int i = 0; i < length; i++) { VariableTerm vTerm = null; SingleTerm def = null; IOperandTerm term = argsRow[i * 2]; //引数読み取り時点で判別されないといけない //if (term == null) //{ errMes = "関数定義の引数は省略できません"; goto err; } vTerm = term.Restructure(exm) as VariableTerm; if ((vTerm == null) || (vTerm.Identifier.Readonly)) { errMes = "関数定義の引数には代入可能な変数を指定してください"; goto err; } else if (!vTerm.isAllConst) { errMes = "関数定義の引数の添え字には定数を指定してください"; goto err; } if (vTerm.Identifier.Code == VariableCode.ARG) { if (maxArg < vTerm.getEl1forArg + 1) maxArg = vTerm.getEl1forArg + 1; } else if (vTerm.Identifier.Code == VariableCode.ARGS) { if (maxArgs < vTerm.getEl1forArg + 1) maxArgs = vTerm.getEl1forArg + 1; } bool canDef = (vTerm.Identifier.Code == VariableCode.ARG || vTerm.Identifier.Code == VariableCode.ARGS || vTerm.Identifier.IsPrivate); term = argsRow[i * 2 + 1]; if (term is NullTerm) { if (canDef)// && label.ArgOptional) { if (vTerm.GetOperandType() == typeof(Int64)) def = new SingleTerm(0); else def = new SingleTerm(""); } } else { def = term.Restructure(exm) as SingleTerm; if (def == null) { errMes = "引数の初期値には定数のみを指定できます"; goto err; } if (!canDef) { errMes = "引数の初期値を定義できるのは\"ARG\"、\"ARGS\"またはプライベート変数のみです"; goto err; } else if (vTerm.Identifier.IsReference) { errMes = "参照渡しの引数に初期値は定義できません"; goto err; } if (vTerm.GetOperandType() != def.GetOperandType()) { errMes = "引数の型と初期値の型が一致していません"; goto err; } } args[i] = vTerm; defs[i] = def; } } } if (!wc.EOL) { errMes = "引数の書式が間違っています"; goto err; } //label.SubNames = subNames; label.Arg = args; label.Def = defs; label.ArgLength = maxArg; label.ArgsLength = maxArgs; return; err: ParserMediator.Warn("関数@" + label.LabelName + " の引数のエラー:" + errMes, label, 2, true, false); return; }
private void nestCheck(FunctionLabelLine label) { //2周目/3周 //IF-ELSEIF-ENDIF、REPEAT-RENDの対応チェックなど //PRINTDATA系もここでチェック LogicalLine nextLine = label; List<InstructionLine> tempLineList = new List<InstructionLine>(); Stack<InstructionLine> nestStack = new Stack<InstructionLine>(); Stack<InstructionLine> SelectcaseStack = new Stack<InstructionLine>(); InstructionLine pairLine = null; while (true) { nextLine = nextLine.NextLine; parentProcess.scaningLine = nextLine; if ((nextLine is NullLine) || (nextLine is FunctionLabelLine)) break; if (!(nextLine is InstructionLine)) { if (nextLine is GotoLabelLine) { InstructionLine currentBaseFunc = nestStack.Count == 0 ? null : nestStack.Peek(); if (currentBaseFunc != null) { if ((currentBaseFunc.FunctionCode == FunctionCode.PRINTDATA) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAL) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAW) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAD) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATADL) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATADW) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAK) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAKL) || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAKW) || (currentBaseFunc.FunctionCode == FunctionCode.DATALIST) || (currentBaseFunc.FunctionCode == FunctionCode.TRYCALLLIST) || (currentBaseFunc.FunctionCode == FunctionCode.TRYJUMPLIST) || (currentBaseFunc.FunctionCode == FunctionCode.TRYGOTOLIST)) //|| (currentBaseFunc.FunctionCode == FunctionCode.SELECTCASE)) { ParserMediator.Warn(currentBaseFunc.Function.Name + "構文中に$ラベルを定義することはできません", nextLine, 2, true, false); } } } continue; } InstructionLine func = (InstructionLine)nextLine; pairLine = null; InstructionLine baseFunc = nestStack.Count == 0 ? null : nestStack.Peek(); if (baseFunc != null) { if ((baseFunc.FunctionCode == FunctionCode.PRINTDATA) || (baseFunc.FunctionCode == FunctionCode.PRINTDATAL) || (baseFunc.FunctionCode == FunctionCode.PRINTDATAW) || (baseFunc.FunctionCode == FunctionCode.PRINTDATAD) || (baseFunc.FunctionCode == FunctionCode.PRINTDATADL) || (baseFunc.FunctionCode == FunctionCode.PRINTDATADW) || (baseFunc.FunctionCode == FunctionCode.PRINTDATAK) || (baseFunc.FunctionCode == FunctionCode.PRINTDATAKL) || (baseFunc.FunctionCode == FunctionCode.PRINTDATAKW) ) { if ((func.FunctionCode != FunctionCode.DATA) && (func.FunctionCode != FunctionCode.DATAFORM) && (func.FunctionCode != FunctionCode.DATALIST) && (func.FunctionCode != FunctionCode.ENDLIST) && (func.FunctionCode != FunctionCode.ENDDATA)) { ParserMediator.Warn("PRINTDATA構文に使用できない命令\'" + func.Function.Name + "\'が含まれています", func, 2, true, false); continue; } } else if (baseFunc.FunctionCode == FunctionCode.DATALIST) { if ((func.FunctionCode != FunctionCode.DATA) && (func.FunctionCode != FunctionCode.DATAFORM) && (func.FunctionCode != FunctionCode.ENDLIST)) { ParserMediator.Warn("DATALIST構文に使用できない命令\'" + func.Function.Name + "\'が含まれています", func, 2, true, false); continue; } } else if ((baseFunc.FunctionCode == FunctionCode.TRYCALLLIST) || (baseFunc.FunctionCode == FunctionCode.TRYJUMPLIST) || (baseFunc.FunctionCode == FunctionCode.TRYGOTOLIST)) { if ((func.FunctionCode != FunctionCode.FUNC) && (func.FunctionCode != FunctionCode.ENDFUNC)) { ParserMediator.Warn(baseFunc.Function.Name + "構文に使用できない命令" + func.Function.Name + "が含まれています", func, 2, true, false); continue; } } else if (baseFunc.FunctionCode == FunctionCode.SELECTCASE) { if ((baseFunc.IfCaseList.Count == 0) && (func.FunctionCode != FunctionCode.CASE) && (func.FunctionCode != FunctionCode.CASEELSE) && (func.FunctionCode != FunctionCode.ENDSELECT)) { ParserMediator.Warn("SELECTCASE構文の分岐の外に命令" + func.Function.Name + "が含まれています", func, 2, true, false); continue; } } } switch (func.FunctionCode) { case FunctionCode.REPEAT: foreach (InstructionLine iLine in nestStack) { if (iLine.FunctionCode == FunctionCode.REPEAT) { ParserMediator.Warn("REPEAT文が入れ子にされています", func, 2, true, false); break; } } if (func.IsError) break; nestStack.Push(func); break; case FunctionCode.IF: nestStack.Push(func); func.IfCaseList = new List<InstructionLine>(); func.IfCaseList.Add(func); break; case FunctionCode.SELECTCASE: nestStack.Push(func); func.IfCaseList = new List<InstructionLine>(); SelectcaseStack.Push(func); break; case FunctionCode.FOR: case FunctionCode.WHILE: case FunctionCode.TRYCGOTO: case FunctionCode.TRYCJUMP: case FunctionCode.TRYCCALL: case FunctionCode.TRYCGOTOFORM: case FunctionCode.TRYCJUMPFORM: case FunctionCode.TRYCCALLFORM: case FunctionCode.DO: nestStack.Push(func); break; case FunctionCode.BREAK: case FunctionCode.CONTINUE: InstructionLine[] array = nestStack.ToArray(); for (int i = 0; i < array.Length; i++) { if ((array[i].FunctionCode == FunctionCode.REPEAT) || (array[i].FunctionCode == FunctionCode.FOR) || (array[i].FunctionCode == FunctionCode.WHILE) || (array[i].FunctionCode == FunctionCode.DO)) { pairLine = array[i]; break; } } if (pairLine == null) { ParserMediator.Warn("REPEAT, FOR, WHILE, DOの中以外で" + func.Function.Name + "文が使われました", func, 2, true, false); break; } func.JumpTo = pairLine; break; case FunctionCode.ELSEIF: case FunctionCode.ELSE: { //1.725 Stack<T>.Peek()はStackが空の時はnullを返す仕様だと思いこんでおりました。 InstructionLine ifLine = nestStack.Count == 0 ? null : nestStack.Peek(); if ((ifLine == null) || (ifLine.FunctionCode != FunctionCode.IF)) { ParserMediator.Warn("IF~ENDIFの外で" + func.Function.Name + "文が使われました", func, 2, true, false); break; } if (ifLine.IfCaseList[ifLine.IfCaseList.Count - 1].FunctionCode == FunctionCode.ELSE) ParserMediator.Warn("ELSE文より後で" + func.Function.Name + "文が使われました", func, 1, false, false); ifLine.IfCaseList.Add(func); } break; case FunctionCode.ENDIF: { InstructionLine ifLine = nestStack.Count == 0 ? null : nestStack.Peek(); if ((ifLine == null) || (ifLine.FunctionCode != FunctionCode.IF)) { ParserMediator.Warn("対応するIFの無いENDIF文です", func, 2, true, false); break; } foreach (InstructionLine ifelseifLine in ifLine.IfCaseList) { ifelseifLine.JumpTo = func; } nestStack.Pop(); } break; case FunctionCode.CASE: case FunctionCode.CASEELSE: { InstructionLine selectLine = nestStack.Count == 0 ? null : nestStack.Peek(); if ((selectLine == null) || (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count == 0)) { ParserMediator.Warn("SELECTCASE~ENDSELECTの外で" + func.Function.Name + "文が使われました", func, 2, true, false); break; } else if (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count > 0) { do { ParserMediator.Warn(selectLine.Function.Name + "文に対応する" + FunctionIdentifier.getMatchFunction(selectLine.FunctionCode) + "がない状態で" + func.Function.Name + "文に到達しました", func, 2, true, false); //これを跨いでIF等が閉じられることがないようにする。 nestStack.Pop(); if (nestStack.Count > 0) selectLine = nestStack.Count == 0 ? null : nestStack.Peek(); } while (selectLine != null && selectLine.FunctionCode != FunctionCode.SELECTCASE); break; } if ((selectLine.IfCaseList.Count > 0) && (selectLine.IfCaseList[selectLine.IfCaseList.Count - 1].FunctionCode == FunctionCode.CASEELSE)) ParserMediator.Warn("CASEELSE文より後で" + func.Function.Name + "文が使われました", func, 1, false, false); selectLine.IfCaseList.Add(func); } break; case FunctionCode.ENDSELECT: { InstructionLine selectLine = nestStack.Count == 0 ? null : nestStack.Peek(); if ((selectLine == null) || (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count == 0)) { ParserMediator.Warn("対応するSELECTCASEの無いENDSELECT文です", func, 2, true, false); break; } else if (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count > 0) { do { ParserMediator.Warn(selectLine.Function.Name + "文に対応する" + FunctionIdentifier.getMatchFunction(selectLine.FunctionCode) + "がない状態で" + func.Function.Name + "文に到達しました", func, 2, true, false); //これを跨いでIF等が閉じられることがないようにする。 nestStack.Pop(); if (nestStack.Count > 0) selectLine = nestStack.Count == 0 ? null : nestStack.Peek(); } while (selectLine != null && selectLine.FunctionCode != FunctionCode.SELECTCASE); //とりあえず、対応するSELECTCASE跨ぎは閉じる SelectcaseStack.Pop(); break; } nestStack.Pop(); SelectcaseStack.Pop(); selectLine.JumpTo = func; if (selectLine.IsError) break; IOperandTerm term = ((ExpressionArgument)selectLine.Argument).Term; if (term == null) { ParserMediator.Warn("SELECTCASEの引数がありません", selectLine, 2, true, false); break; } foreach (InstructionLine caseLine in selectLine.IfCaseList) { caseLine.JumpTo = func; if (caseLine.IsError) continue; if (caseLine.FunctionCode == FunctionCode.CASEELSE) continue; CaseExpression[] caseExps = ((CaseArgument)caseLine.Argument).CaseExps; if (caseExps.Length == 0) ParserMediator.Warn("CASEの引数がありません", caseLine, 2, true, false); foreach (CaseExpression exp in caseExps) { if (exp.GetOperandType() != term.GetOperandType()) ParserMediator.Warn("CASEの引数の型がSELECTCASEと一致しません", caseLine, 2, true, false); } } } break; case FunctionCode.REND: case FunctionCode.NEXT: case FunctionCode.WEND: case FunctionCode.LOOP: FunctionCode parentFunc = FunctionIdentifier.getParentFunc(func.FunctionCode); //if (parentFunc == FunctionCode.__NULL__) // throw new ExeEE("何か変?"); if ((nestStack.Count == 0) || (nestStack.Peek().FunctionCode != parentFunc)) { ParserMediator.Warn("対応する" + parentFunc.ToString() + "の無い" + func.Function.Name + "文です", func, 2, true, false); break; } pairLine = nestStack.Pop();//REPEAT func.JumpTo = pairLine; pairLine.JumpTo = func; break; case FunctionCode.CATCH: pairLine = nestStack.Count == 0 ? null : nestStack.Peek(); if ((pairLine == null) || ((pairLine.FunctionCode != FunctionCode.TRYCGOTO) && (pairLine.FunctionCode != FunctionCode.TRYCCALL) && (pairLine.FunctionCode != FunctionCode.TRYCJUMP) && (pairLine.FunctionCode != FunctionCode.TRYCGOTOFORM) && (pairLine.FunctionCode != FunctionCode.TRYCCALLFORM) && (pairLine.FunctionCode != FunctionCode.TRYCJUMPFORM))) { ParserMediator.Warn("対応するTRYC系命令がありません", func, 2, true, false); break; } pairLine = nestStack.Pop();//TRYC pairLine.JumpToEndCatch = func;//TRYCにCATCHの位置を教える nestStack.Push(func); break; case FunctionCode.ENDCATCH: if ((nestStack.Count == 0) || (nestStack.Peek().FunctionCode != FunctionCode.CATCH)) { ParserMediator.Warn("対応するCATCHのないENDCATCHです", func, 2, true, false); break; } pairLine = nestStack.Pop();//CATCH pairLine.JumpToEndCatch = func;//CATCHにENDCATCHの位置を教える break; case FunctionCode.PRINTDATA: case FunctionCode.PRINTDATAL: case FunctionCode.PRINTDATAW: case FunctionCode.PRINTDATAD: case FunctionCode.PRINTDATADL: case FunctionCode.PRINTDATADW: case FunctionCode.PRINTDATAK: case FunctionCode.PRINTDATAKL: case FunctionCode.PRINTDATAKW: foreach (InstructionLine iLine in nestStack) { if (iLine.FunctionCode == FunctionCode.PRINTDATA || iLine.FunctionCode == FunctionCode.PRINTDATAL || iLine.FunctionCode == FunctionCode.PRINTDATAW || iLine.FunctionCode == FunctionCode.PRINTDATAD || iLine.FunctionCode == FunctionCode.PRINTDATADL || iLine.FunctionCode == FunctionCode.PRINTDATADW || iLine.FunctionCode == FunctionCode.PRINTDATAK || iLine.FunctionCode == FunctionCode.PRINTDATAKL || iLine.FunctionCode == FunctionCode.PRINTDATAKW) { ParserMediator.Warn("PRINTDATA系命令が入れ子にされています", func, 2, true, false); break; } } if (func.IsError) break; func.dataList = new List<List<InstructionLine>>(); nestStack.Push(func); break; case FunctionCode.DATALIST: InstructionLine plist = (nestStack.Count == 0) ? null : nestStack.Peek(); if ((plist == null) || (plist.FunctionCode != FunctionCode.PRINTDATA && plist.FunctionCode != FunctionCode.PRINTDATAL && plist.FunctionCode != FunctionCode.PRINTDATAW && plist.FunctionCode != FunctionCode.PRINTDATAD && plist.FunctionCode != FunctionCode.PRINTDATADL && plist.FunctionCode != FunctionCode.PRINTDATADW && plist.FunctionCode != FunctionCode.PRINTDATAK && plist.FunctionCode != FunctionCode.PRINTDATAKL && plist.FunctionCode != FunctionCode.PRINTDATAKW)) { ParserMediator.Warn("対応するPRINTDATA系命令のないDATALISTです", func, 2, true, false); break; } tempLineList = new List<InstructionLine>(); nestStack.Push(func); break; case FunctionCode.ENDLIST: if ((nestStack.Count == 0) || (nestStack.Peek().FunctionCode != FunctionCode.DATALIST)) { ParserMediator.Warn("対応するDATALISTのないENDLISTです", func, 2, true, false); break; } if (tempLineList.Count == 0) ParserMediator.Warn("DATALIST命令に表示データが与えられていません(このDATALISTは空文字列を表示します)", func, 1, false, false); nestStack.Pop(); nestStack.Peek().dataList.Add(tempLineList); break; case FunctionCode.DATA: case FunctionCode.DATAFORM: InstructionLine pdata = (nestStack.Count == 0) ? null : nestStack.Peek(); if ((pdata == null) || (pdata.FunctionCode != FunctionCode.PRINTDATA && pdata.FunctionCode != FunctionCode.PRINTDATAL && pdata.FunctionCode != FunctionCode.PRINTDATAW && pdata.FunctionCode != FunctionCode.PRINTDATAD && pdata.FunctionCode != FunctionCode.PRINTDATADL && pdata.FunctionCode != FunctionCode.PRINTDATADW && pdata.FunctionCode != FunctionCode.PRINTDATAK && pdata.FunctionCode != FunctionCode.PRINTDATAKL && pdata.FunctionCode != FunctionCode.PRINTDATAKW && pdata.FunctionCode != FunctionCode.DATALIST)) { ParserMediator.Warn("対応するPRINTDATA系命令のない" + func.Function.Name + "です", func, 2, true, false); break; } List<InstructionLine> iList = new List<InstructionLine>(); if (pdata.FunctionCode != FunctionCode.DATALIST) { iList.Add(func); pdata.dataList.Add(iList); } else tempLineList.Add(func); break; case FunctionCode.ENDDATA: InstructionLine pdataline = (nestStack.Count == 0) ? null : nestStack.Peek(); if ((pdataline == null) || (pdataline.FunctionCode != FunctionCode.PRINTDATA && pdataline.FunctionCode != FunctionCode.PRINTDATAL && pdataline.FunctionCode != FunctionCode.PRINTDATAW && pdataline.FunctionCode != FunctionCode.PRINTDATAD && pdataline.FunctionCode != FunctionCode.PRINTDATADL && pdataline.FunctionCode != FunctionCode.PRINTDATADW && pdataline.FunctionCode != FunctionCode.PRINTDATAK && pdataline.FunctionCode != FunctionCode.PRINTDATAKL && pdataline.FunctionCode != FunctionCode.PRINTDATAKW)) { ParserMediator.Warn("対応するPRINTDATA系命令のない" + func.Function.Name + "です", func, 2, true, false); break; } if (pdataline.FunctionCode == FunctionCode.DATALIST) ParserMediator.Warn("DATALISTが閉じられていません", func, 2, true, false); if (pdataline.dataList.Count == 0) ParserMediator.Warn(pdataline.Function.Name + "命令に表示データがありません(この命令は無視されます)", func, 1, false, false); pdataline.JumpTo = func; nestStack.Pop(); break; case FunctionCode.TRYCALLLIST: case FunctionCode.TRYJUMPLIST: case FunctionCode.TRYGOTOLIST: foreach (InstructionLine iLine in nestStack) { if (iLine.FunctionCode == FunctionCode.TRYCALLLIST || iLine.FunctionCode == FunctionCode.TRYJUMPLIST || iLine.FunctionCode == FunctionCode.TRYGOTOLIST) { ParserMediator.Warn("TRYCALLLIST系命令が入れ子にされています", func, 2, true, false); break; } } if (func.IsError) break; func.callList = new List<InstructionLine>(); nestStack.Push(func); break; case FunctionCode.FUNC: { InstructionLine pFunc = (nestStack.Count == 0) ? null : nestStack.Peek(); if ((pFunc == null) || (pFunc.FunctionCode != FunctionCode.TRYCALLLIST && pFunc.FunctionCode != FunctionCode.TRYJUMPLIST && pFunc.FunctionCode != FunctionCode.TRYGOTOLIST)) { ParserMediator.Warn("対応するTRYCALLLIST系命令のない" + func.Function.Name + "です", func, 2, true, false); break; } if (pFunc.FunctionCode == FunctionCode.TRYGOTOLIST) { if (((SpCallArgment)func.Argument).SubNames.Length != 0) { ParserMediator.Warn("TRYGOTOLISTの呼び出し対象に[~~]が設定されています", func, 2, true, false); break; } if (((SpCallArgment)func.Argument).RowArgs.Length != 0) { ParserMediator.Warn("TRYGOTOLISTの呼び出し対象に引数が設定されています", func, 2, true, false); break; } } pFunc.callList.Add(func); break; } case FunctionCode.ENDFUNC: InstructionLine pf = (nestStack.Count == 0) ? null : nestStack.Peek(); if ((pf == null) || (pf.FunctionCode != FunctionCode.TRYCALLLIST && pf.FunctionCode != FunctionCode.TRYJUMPLIST && pf.FunctionCode != FunctionCode.TRYGOTOLIST)) { ParserMediator.Warn("対応するTRYCALLLIST系命令のない" + func.Function.Name + "です", func, 2, true, false); break; } pf.JumpTo = func; nestStack.Pop(); break; case FunctionCode.NOSKIP: foreach (InstructionLine iLine in nestStack) { if (iLine.FunctionCode == FunctionCode.NOSKIP) { ParserMediator.Warn("NOSKIP系命令が入れ子にされています", func, 2, true, false); break; } } if (func.IsError) break; nestStack.Push(func); break; case FunctionCode.ENDNOSKIP: InstructionLine pfunc = (nestStack.Count == 0) ? null : nestStack.Peek(); if ((pfunc == null) || (pfunc.FunctionCode != FunctionCode.NOSKIP)) { ParserMediator.Warn("対応するNOSKIP系命令のない" + func.Function.Name + "です", func, 2, true, false); break; } //エラーハンドリング用 pfunc.JumpTo = func; func.JumpTo = pfunc; nestStack.Pop(); break; } } while (nestStack.Count != 0) { InstructionLine func = nestStack.Pop(); string funcName = func.Function.Name; string funcMatch = FunctionIdentifier.getMatchFunction(func.FunctionCode); if (func != null) ParserMediator.Warn(funcName + "に対応する" + funcMatch + "が見つかりません", func, 2, true, false); else ParserMediator.Warn("ディフォルトエラー(Emuera設定漏れ)", func, 2, true, false); } //使ったスタックをクリア SelectcaseStack.Clear(); }
private void checkFunctionWithCatch(FunctionLabelLine label) { //ここでエラーを捕まえることは本来はないはず。ExeEE相当。 try { System.Windows.Forms.Application.DoEvents(); string filename = label.Position.Filename.ToUpper(); setArgument(label); nestCheck(label); setJumpTo(label); } catch (Exception exc) { System.Media.SystemSounds.Hand.Play(); //1756beta2+v6.1 修正の効率化のために何かパース関係でハンドリングできてないエラーが出た場合はスタックトレースを投げるようにした string errmes = (exc is EmueraException) ? exc.Message : exc.GetType().ToString() + ":" + exc.Message; ParserMediator.Warn("@" + label.LabelName + " の解析中にエラー:" + errmes, label, 2, true, false, !(exc is EmueraException) ? exc.StackTrace : null); label.ErrMes = "ロード時に解析に失敗した関数が呼び出されました"; } finally { parentProcess.scaningLine = null; } }
private void setJumpTo(FunctionLabelLine label) { //3周目/3周 //フロー制御命令のジャンプ先を設定 LogicalLine nextLine = label; int depth = label.Depth; if (depth < 0) depth = -2; while (true) { string FunctionoNotFoundName = null; nextLine = nextLine.NextLine; InstructionLine func = nextLine as InstructionLine; if (func == null) { if ((nextLine is NullLine) || (nextLine is FunctionLabelLine)) break; continue; } if (func.IsError) continue; parentProcess.scaningLine = func; if (func.Function.Instruction != null) { try { func.Function.Instruction.SetJumpTo(ref useCallForm, func, depth, ref FunctionoNotFoundName); } catch (CodeEE e) { ParserMediator.Warn(e.Message, func, 2, true, false); continue; } if (FunctionoNotFoundName != null) { if (!Program.AnalysisMode) printFunctionNotFoundWarning("指定された関数名\"@" + FunctionoNotFoundName + "\"は存在しません", func, 2, true); else printFunctionNotFoundWarning(FunctionoNotFoundName, func, 2, true); } continue; } if ((func.FunctionCode == FunctionCode.TRYCALLLIST) || (func.FunctionCode == FunctionCode.TRYJUMPLIST)) useCallForm = true; } }
public static bool ParseSharpLine(FunctionLabelLine label, StringStream st, ScriptPosition position, List<string> OnlyLabel) { st.ShiftNext();//'#'を飛ばす string token = LexicalAnalyzer.ReadSingleIdentifier(st);//#~自体にはマクロ非適用 if (Config.ICFunction) token = token.ToUpper(); //#行として不正な行でもAnalyzeに行って引っかかることがあるので、先に存在しない#~は弾いてしまう if (token == null || (token != "SINGLE" && token != "LATER" && token != "PRI" && token != "ONLY" && token != "FUNCTION" && token != "FUNCTIONS" && token != "LOCALSIZE" && token != "LOCALSSIZE" && token != "DIM" && token != "DIMS")) { ParserMediator.Warn("解釈できない#行です", position, 1); return false; } try { WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, false, false); switch (token) { case "SINGLE": if (label.IsMethod) { ParserMediator.Warn("式中関数では#SINGLEは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#SINGLEは機能しません", position, 1); break; } else if (label.IsSingle) { ParserMediator.Warn("#SINGLEが重複して使われています", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが指定されたイベント関数では#SINGLEは機能しません", position, 1); break; } label.IsSingle = true; break; case "LATER": if (label.IsMethod) { ParserMediator.Warn("式中関数では#LATERは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#LATERは機能しません", position, 1); break; } else if (label.IsLater) { ParserMediator.Warn("#LATERが重複して使われています", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが指定されたイベント関数では#LATERは機能しません", position, 1); break; } else if (label.IsPri) ParserMediator.Warn("#PRIと#LATERが重複して使われています(この関数は2度呼ばれます)", position, 1); label.IsLater = true; break; case "PRI": if (label.IsMethod) { ParserMediator.Warn("式中関数では#PRIは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#PRIは機能しません", position, 1); break; } else if (label.IsPri) { ParserMediator.Warn("#PRIが重複して使われています", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが指定されたイベント関数では#PRIは機能しません", position, 1); break; } else if (label.IsLater) ParserMediator.Warn("#PRIと#LATERが重複して使われています(この関数は2度呼ばれます)", position, 1); label.IsPri = true; break; case "ONLY": if (label.IsMethod) { ParserMediator.Warn("式中関数では#ONLYは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#ONLYは機能しません", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが重複して使われています", position, 1); break; } else if (OnlyLabel.Contains(label.LabelName)) ParserMediator.Warn("このイベント関数\"@" + label.LabelName + "\"にはすでに#ONLYが宣言されています(この関数は実行されません)", position, 1); OnlyLabel.Add(label.LabelName); label.IsOnly = true; if (label.IsPri) { ParserMediator.Warn("このイベント関数には#PRIが宣言されていますが無視されます", position, 1); label.IsPri = false; } if (label.IsLater) { ParserMediator.Warn("このイベント関数には#LATERが宣言されていますが無視されます", position, 1); label.IsLater = false; } if (label.IsSingle) { ParserMediator.Warn("このイベント関数には#SINGLEが宣言されていますが無視されます", position, 1); label.IsSingle = false; } break; case "FUNCTION": case "FUNCTIONS": if (!string.IsNullOrEmpty(label.LabelName) && char.IsDigit(label.LabelName[0])) { ParserMediator.Warn("#" + token + "属性は関数名が数字で始まる関数には指定できません", position, 1); label.IsError = true; label.ErrMes = "関数名が数字で始まっています"; break; } if (label.IsMethod) { if ((label.MethodType == typeof(Int64) && token == "FUNCTION") || (label.MethodType == typeof(string) && token == "FUNCTIONS")) { ParserMediator.Warn("関数" + label.LabelName + "にはすでに#" + token + "が宣言されています(この行は無視されます)", position, 1); return false; } if (label.MethodType == typeof(Int64) && token == "FUNCTIONS") ParserMediator.Warn("関数" + label.LabelName + "にはすでに#FUNCTIONが宣言されています", position, 2); else if (label.MethodType == typeof(string) && token == "FUNCTION") ParserMediator.Warn("関数" + label.LabelName + "にはすでに#FUNCTIONSが宣言されています", position, 2); return false; } if (label.Depth == 0) { ParserMediator.Warn("システム関数に#" + token + "が指定されています", position, 2); return false; } label.IsMethod = true; label.Depth = 0; if (token == "FUNCTIONS") label.MethodType = typeof(string); else label.MethodType = typeof(Int64); if (label.IsPri) { ParserMediator.Warn("式中関数では#PRIは機能しません", position, 1); label.IsPri = false; } if (label.IsLater) { ParserMediator.Warn("式中関数では#LATERは機能しません", position, 1); label.IsLater = false; } if (label.IsSingle) { ParserMediator.Warn("式中関数では#SINGLEは機能しません", position, 1); label.IsSingle = false; } if (label.IsOnly) { ParserMediator.Warn("式中関数では#ONLYは機能しません", position, 1); label.IsOnly = false; } break; case "LOCALSIZE": case "LOCALSSIZE": { //イベント関数では指定しても無視される if (label.IsEvent) { ParserMediator.Warn("イベント関数では#" + token + "による" + token.Substring(0, token.Length - 4)+ "のサイズ指定は無視されます", position, 1); break; } if (wc.EOL) { ParserMediator.Warn("#" + token + "の後に有効な数値が指定されていません", position, 2); break; } IOperandTerm arg = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.EoL); SingleTerm sizeTerm = arg.Restructure(null) as SingleTerm; if ((sizeTerm == null) || (sizeTerm.GetOperandType() != typeof(Int64))) { ParserMediator.Warn("#" + token + "の後に有効な定数式が指定されていません", position, 2); break; } if (sizeTerm.Int <= 0) { ParserMediator.Warn("#" + token + "に0以下の値(" + sizeTerm.Int.ToString() + ")が与えられました。設定は無視されます", position, 1); break; } if (sizeTerm.Int >= Int32.MaxValue) { ParserMediator.Warn("#" + token + "に大きすぎる値(" + sizeTerm.Int.ToString() + ")が与えられました。設定は無視されます", position, 1); break; } int size = (int)sizeTerm.Int; if (token == "LOCALSIZE") { if (label.LocalLength > 0) ParserMediator.Warn("この関数にはすでに#LOCALSIZEが定義されています。(以前の定義は無視されます)", position, 1); label.LocalLength = size; } else { if (label.LocalsLength > 0) ParserMediator.Warn("この関数にはすでに#LOCALSSIZEが定義されています。(以前の定義は無視されます)", position, 1); label.LocalsLength = size; } } break; case "DIM": case "DIMS": { UserDefinedVariableData data = UserDefinedVariableData.Create(wc, token == "DIMS", true, position); if (!label.AddPrivateVariable(data)) { ParserMediator.Warn("変数名" + data.Name + "は既に使用されています", position, 2); return false; } break; } default: ParserMediator.Warn("解釈できない#行です", position, 1); break; } if (!wc.EOL) ParserMediator.Warn("#の識別子の後に余分な文字があります", position, 1); } catch (Exception e) { ParserMediator.Warn(e.Message, position, 2); goto err; } return true; err: return false; }
internal void AddInvalidLabel(FunctionLabelLine invalidLabelLine) { invalidList.Add(invalidLabelLine); }
public FunctionLabelLine GetSameNameLabel(FunctionLabelLine point) { string id = point.LabelName; if (!labelAtDic.ContainsKey(id)) return null; if (point.IsError) return null; List<FunctionLabelLine> labelList = labelAtDic[id]; if (labelList.Count <= 1) return null; return labelList[0]; }
public GotoLabelLine GetLabelDollar(string key, FunctionLabelLine labelAtLine) { foreach (GotoLabelLine label in labelDollarList) { if ((label.LabelName == key) && (label.ParentLabelLine == labelAtLine)) return label; } return null; }
private void setArgument(FunctionLabelLine label) { //1周目/3周 //引数の解析とか LogicalLine nextLine = label; bool inMethod = label.IsMethod; while (true) { nextLine = nextLine.NextLine; parentProcess.scaningLine = nextLine; InstructionLine func = nextLine as InstructionLine; if (func == null) { if ((nextLine is NullLine) || (nextLine is FunctionLabelLine)) break; continue; } if (inMethod) { if (!func.Function.IsMethodSafe()) { ParserMediator.Warn(func.Function.Name + "命令は#FUNCTION中で使うことはできません", nextLine, 2, true, false); continue; } } if (Config.NeedReduceArgumentOnLoad || Program.AnalysisMode || func.Function.IsForceSetArg()) ArgumentParser.SetArgumentTo(func); } }
public IOperandTerm GetFunctionMethod(LabelDictionary labelDic, string codeStr, IOperandTerm[] arguments, bool userDefinedOnly) { if (Config.ICFunction) { codeStr = codeStr.ToUpper(); } if (arguments == null) //引数なし、名前のみの探索 { if (refmethodDic.ContainsKey(codeStr)) { return(new UserDefinedRefMethodNoArgTerm(refmethodDic[codeStr])); } return(null); } if ((labelDic != null) && (labelDic.Initialized)) { if (refmethodDic.ContainsKey(codeStr)) { return(new UserDefinedRefMethodTerm(refmethodDic[codeStr], arguments)); } FunctionLabelLine func = labelDic.GetNonEventLabel(codeStr); if (func != null) { if (userDefinedOnly && !func.IsMethod) { throw new CodeEE("#FUNCTIONが指定されていない関数\"@" + func.LabelName + "\"をCALLF系命令で呼び出そうとしました"); } if (func.IsMethod) { string errMes; IOperandTerm ret = UserDefinedMethodTerm.Create(func, arguments, out errMes); if (ret == null) { throw new CodeEE(errMes); } return(ret); } //1.721 #FUNCTIONが定義されていない関数は組み込み関数を上書きしない方向に。 PANCTION.ERBのRANDとか。 if (!methodDic.ContainsKey(codeStr)) { throw new CodeEE("#FUNCTIONが定義されていない関数(" + func.Position.Filename + ":" + func.Position.LineNo + "行目)を式中で呼び出そうとしました"); } } } if (userDefinedOnly) { return(null); } FunctionMethod method = null; if (!methodDic.TryGetValue(codeStr, out method)) { return(null); } string errmes = method.CheckArgumentType(codeStr, arguments); if (errmes != null) { throw new CodeEE(errmes); } return(new FunctionMethodTerm(method, arguments)); }
public static LogicalLine ParseLabelLine(StringStream stream, ScriptPosition position, EmueraConsole console) { bool isFunction = (stream.Current == '@'); int lineNo = position.LineNo; string labelName = ""; string errMes = ""; try { int warnLevel = -1; stream.ShiftNext();//@か$を除去 WordCollection wc = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, false, true); if (wc.EOL || !(wc.Current is IdentifierWord)) { errMes = "関数名が不正であるか存在しません"; goto err; } labelName = ((IdentifierWord)wc.Current).Code; wc.ShiftNext(); if (Config.ICVariable) labelName = labelName.ToUpper(); GlobalStatic.IdentifierDictionary.CheckUserLabelName(ref errMes, ref warnLevel, isFunction, labelName); if (warnLevel >= 0) { if (warnLevel >= 2) goto err; ParserMediator.Warn(errMes, position, warnLevel); } if (!isFunction)//$ならこの時点で終了 { if (!wc.EOL) ParserMediator.Warn("$で始まるラベルに引数が設定されています", position, 1); return new GotoLabelLine(position, labelName); } //labelName = LexicalAnalyzer.ReadString(stream, StrEndWith.LeftParenthesis_Bracket_Comma_Semicolon); //labelName = labelName.Trim(); //if (Config.ICVariable) // labelName = labelName.ToUpper(); //GlobalStatic.IdentifierDictionary.CheckUserLabelName(ref errMes, ref warnLevel, isFunction, labelName); //if(warnLevel >= 0) //{ // if (warnLevel >= 2) // goto err; // ParserMediator.Warn(errMes, position, warnLevel); //} //if (!isFunction)//$ならこの時点で終了 //{ // LexicalAnalyzer.SkipWhiteSpace(stream); // if (!stream.EOS) // ParserMediator.Warn("$で始まるラベルに引数が設定されています", position, 1); // return new GotoLabelLine(position, labelName); //} ////関数名部分に_renameを使えないように変更 //if (ParserMediator.RenameDic != null && ((stream.ToString().IndexOf("[[") >= 0) && (stream.ToString().IndexOf("]]") >= 0))) //{ // string line = stream.ToString(); // foreach (KeyValuePair<string, string> pair in ParserMediator.RenameDic) // line = line.Replace(pair.Key, pair.Value); // stream = new StringStream(line); //} //WordCollection wc = null; //wc = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, false, true); if (Program.AnalysisMode) console.PrintC("@" + labelName, false); FunctionLabelLine funclabelLine = new FunctionLabelLine(position, labelName, wc); if (IdentifierDictionary.IsEventLabelName(labelName)) { funclabelLine.IsEvent = true; funclabelLine.IsSystem = true; funclabelLine.Depth = 0; } else if (IdentifierDictionary.IsSystemLabelName(labelName)) { funclabelLine.IsSystem = true; funclabelLine.Depth = 0; } return funclabelLine; } catch (CodeEE e) { errMes = e.Message; } err: System.Media.SystemSounds.Hand.Play(); if (isFunction) { if(labelName.Length == 0) labelName = "<Error>"; return new InvalidLabelLine(position, labelName, errMes); } return new InvalidLine(position, errMes); }