/// <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)); }
static public bool LoadContents() { if (!Directory.Exists(Program.ContentDir)) { return(true); } try { //resourcesフォルダ内の全てのcsvファイルを探索する string[] csvFiles = Directory.GetFiles(Program.ContentDir, "*.csv", SearchOption.AllDirectories); foreach (var filepath in csvFiles) { //アニメスプライト宣言。nullでないとき、フレーム追加モード SpriteAnime currentAnime = null; string directory = Path.GetDirectoryName(filepath).ToUpper() + "\\"; string filename = Path.GetFileName(filepath); string[] lines = File.ReadAllLines(filepath, Config.Encode); int lineNo = 0; foreach (var line in lines) { lineNo++; if (line.Length == 0) { continue; } string str = line.Trim(); if (str.Length == 0 || str.StartsWith(";")) { continue; } string[] tokens = str.Split(','); //AContentItem item = CreateFromCsv(tokens); ScriptPosition sp = new ScriptPosition(filename, lineNo, line); ASprite item = CreateFromCsv(tokens, directory, currentAnime, sp) as ASprite; if (item != null) { //アニメスプライト宣言ならcurrentAnime上書きしてフレーム追加モードにする。そうでないならnull currentAnime = item as SpriteAnime; if (!imageDictionary.ContainsKey(item.Name)) { imageDictionary.Add(item.Name, item); } else { ParserMediator.Warn("同名のリソースがすでに作成されています:" + item.Name, sp, 0); item.Dispose(); } } } } } catch { return(false); //throw new CodeEE("リソースファイルのロード中にエラーが発生しました"); } return(true); }
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); }
public static bool SetArgumentTo(InstructionLine line) { if (line == null) { return(false); } if (line.Argument != null) { return(true); } if (line.IsError) { return(false); } if (!Program.DebugMode && line.Function.IsDebug()) { //非DebugモードでのDebug系命令。何もしないので引数解析も不要 line.Argument = null; return(true); } Argument arg = null; string errmes = null; try { arg = line.Function.ArgBuilder.CreateArgument(line, GlobalStatic.EMediator); } catch (EmueraException e) { errmes = e.Message; goto error; } if (arg == null) { if (!line.IsError) { errmes = "命令の引数解析中に特定できないエラーが発生"; goto error; } return(false); } line.Argument = arg; if (arg == null) { line.IsError = true; } return(true); error: //SystemSounds.Hand.Play(); uEmuera.Media.SystemSounds.Hand.Play(); line.IsError = true; line.ErrMes = errmes; ParserMediator.Warn(errmes, line, 2, true, false); return(false); }
//private void analyzeSharpDim(StringStream st, ScriptPosition position, bool dims) //{ // //WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment); // //UserDefinedVariableData data = UserDefinedVariableData.Create(wc, dims, false, position); // //if (data.Reference) // // throw new NotImplCodeEE(); // //VariableToken var = null; // //if (data.CharaData) // // var = parentProcess.VEvaluator.VariableData.CreateUserDefCharaVariable(data); // //else // // var = parentProcess.VEvaluator.VariableData.CreateUserDefVariable(data); // //idDic.AddUseDefinedVariable(var); //} //1822 #DIMだけまとめておいて後で処理 private bool analyzeSharpDimLines() { bool noError = true; bool tryAgain = true; while (dimlines.Count > 0) { int count = dimlines.Count; for (int i = 0; i < count; i++) { DimLineWC dimline = dimlines.Dequeue(); try { UserDefinedVariableData data = UserDefinedVariableData.Create(dimline); if (data.Reference) { throw new NotImplCodeEE(); } VariableToken var = null; if (data.CharaData) { var = parentProcess.VEvaluator.VariableData.CreateUserDefCharaVariable(data); } else { var = parentProcess.VEvaluator.VariableData.CreateUserDefVariable(data); } idDic.AddUseDefinedVariable(var); } catch (IdentifierNotFoundCodeEE e) { //繰り返すことで解決する見込みがあるならキューの最後に追加 if (tryAgain) { dimline.WC.Pointer = 0; dimlines.Enqueue(dimline); } else { ParserMediator.Warn(e.Message, dimline.SC, 2); noError = true; } } catch (CodeEE e) { ParserMediator.Warn(e.Message, dimline.SC, 2); noError = false; } } if (dimlines.Count == count) { tryAgain = false; } } return(noError); }
internal void FileEnd(ScriptPosition position) { if (ppMatch.Count != 0) { var match = ppMatch.Pop(); if (match == "ELSEIF") { match = "ENDIF"; } ParserMediator.Warn($"[{match}]がありません", position, 1); } }
public static LogicalLine ParseLine(StringStream stream, ScriptPosition position, EmueraConsole console) { var lineNo = position.LineNo; var errMes = ""; LexicalAnalyzer.SkipWhiteSpace(stream); //先頭のホワイトスペースを読み飛ばす if (stream.EOS) { return(null); } //コメント行かどうかはここに来る前に判定しておく try { #region 前置インクリメント、デクリメント行 if (stream.Current == '+' || stream.Current == '-') { var op = stream.Current; var wc = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, LexAnalyzeFlag.None); var 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 var idWT = LexicalAnalyzer.ReadFirstIdentifierWord(stream); if (idWT != null) { var 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, SeekOrigin.Begin); var assignOP = OperatorCode.NULL; var 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) { SystemSounds.Hand.Play(); return(new InvalidLine(position, e.Message)); } }
public static LogicalLine ParseLabelLine(StringStream stream, ScriptPosition position, EmueraConsole console) { var isFunction = stream.Current == '@'; var lineNo = position.LineNo; var labelName = ""; var errMes = ""; try { var warnLevel = -1; stream.ShiftNext(); //@か$を除去 var wc = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment); 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, LexAnalyzeFlag.AllowAssignment); if (Program.AnalysisMode) { console.PrintC("@" + labelName, false); } var 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: SystemSounds.Hand.Play(); if (isFunction) { if (labelName.Length == 0) { labelName = "<Error>"; } return(new InvalidLabelLine(position, labelName, errMes)); } return(new InvalidLine(position, errMes)); }
public static bool ParseSharpLine(FunctionLabelLine label, StringStream st, ScriptPosition position, List <string> OnlyLabel) { st.ShiftNext(); //'#'を飛ばす var 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 { var wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment); 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(long) && token == "FUNCTION" || label.MethodType == typeof(string) && token == "FUNCTIONS") { ParserMediator.Warn("関数" + label.LabelName + "にはすでに#" + token + "が宣言されています(この行は無視されます)", position, 1); return(false); } if (label.MethodType == typeof(long) && 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(long); } 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 (wc.EOL) { ParserMediator.Warn("#" + token + "の後に有効な数値が指定されていません", position, 2); break; } //イベント関数では指定しても無視される if (label.IsEvent) { ParserMediator.Warn( "イベント関数では#" + token + "による" + token.Substring(0, token.Length - 4) + "のサイズ指定は無視されます", position, 1); break; } var arg = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.EoL); var sizeTerm = arg.Restructure(null) as SingleTerm; if (sizeTerm == null || sizeTerm.GetOperandType() != typeof(long)) { ParserMediator.Warn("#" + token + "の後に有効な定数式が指定されていません", position, 2); break; } if (sizeTerm.Int <= 0) { ParserMediator.Warn("#" + token + "に0以下の値(" + sizeTerm.Int + ")が与えられました。設定は無視されます", position, 1); break; } if (sizeTerm.Int >= int.MaxValue) { ParserMediator.Warn("#" + token + "に大きすぎる値(" + sizeTerm.Int + ")が与えられました。設定は無視されます", position, 1); break; } var size = (int)sizeTerm.Int; if (token == "LOCALSIZE") { if (GlobalStatic.IdentifierDictionary.getLocalIsForbid("LOCAL")) { ParserMediator.Warn("#" + token + "が指定されていますが変数LOCALは使用禁止されています", position, 2); break; } if (label.LocalLength > 0) { ParserMediator.Warn("この関数にはすでに#LOCALSIZEが定義されています。(以前の定義は無視されます)", position, 1); } label.LocalLength = size; } else { if (GlobalStatic.IdentifierDictionary.getLocalIsForbid("LOCALS")) { ParserMediator.Warn("#" + token + "が指定されていますが変数LOCALSは使用禁止されています", position, 2); break; } if (label.LocalsLength > 0) { ParserMediator.Warn("この関数にはすでに#LOCALSSIZEが定義されています。(以前の定義は無視されます)", position, 1); } label.LocalsLength = size; } } break; case "DIM": case "DIMS": { var 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); }
/// <summary> /// resourcesフォルダ中のcsvの1行を読んで新しいリソースを作る(or既存のアニメーションスプライトに1フレーム追加する) /// </summary> /// <param name="tokens"></param> /// <param name="dir"></param> /// <param name="currentAnime"></param> /// <param name="sp"></param> /// <returns></returns> static private AContentItem CreateFromCsv(string[] tokens, string dir, SpriteAnime currentAnime, ScriptPosition sp) { if (tokens.Length < 2) { return(null); } string name = tokens[0].Trim().ToUpper(); // string arg2 = tokens[1].ToUpper(); //画像ファイル名 if (name.Length == 0 || arg2.Length == 0) { return(null); } //アニメーションスプライト宣言 if (arg2 == "ANIME") { if (tokens.Length < 4) { ParserMediator.Warn("アニメーションスプライトのサイズが宣言されていません", sp, 1); return(null); } //w,h int[] sizeValue = new int[2]; bool sccs = true; for (int i = 0; i < 2; i++) { sccs &= int.TryParse(tokens[i + 2], out sizeValue[i]); } if (!sccs || sizeValue[0] <= 0 || sizeValue[1] <= 0 || sizeValue[0] > AbstractImage.MAX_IMAGESIZE || sizeValue[1] > AbstractImage.MAX_IMAGESIZE) { ParserMediator.Warn("アニメーションスプライトのサイズの指定が適切ではありません", sp, 1); return(null); } SpriteAnime anime = new SpriteAnime(name, new Size(sizeValue[0], sizeValue[1])); return(anime); } //アニメ宣言以外(アニメ用フレーム含む if (arg2.IndexOf('.') < 0) { ParserMediator.Warn("第二引数に拡張子がありません:" + arg2, sp, 1); return(null); } string parentName = dir + arg2; //親画像のロードConstImage if (!resourceDic.ContainsKey(parentName)) { string filepath = parentName; if (!File.Exists(filepath)) { ParserMediator.Warn("指定された画像ファイルが見つかりませんでした:" + arg2, sp, 1); return(null); } Bitmap bmp = new Bitmap(filepath); if (bmp == null) { ParserMediator.Warn("指定されたファイルの読み込みに失敗しました:" + arg2, sp, 1); return(null); } bmp.name = name; if (bmp.Width > AbstractImage.MAX_IMAGESIZE || bmp.Height > AbstractImage.MAX_IMAGESIZE) { //1824-2 すでに8192以上の幅を持つ画像を利用したバリアントが存在してしまっていたため、警告しつつ許容するように変更 // bmp.Dispose(); ParserMediator.Warn("指定された画像ファイルの大きさが大きすぎます(幅及び高さを" + AbstractImage.MAX_IMAGESIZE.ToString() + "以下にすることを強く推奨します):" + arg2, sp, 1); //return null; } ConstImage img = new ConstImage(parentName); img.CreateFrom(bmp, Config.TextDrawingMode == TextDrawingMode.WINAPI); if (!img.IsCreated) { ParserMediator.Warn("画像リソースの作成に失敗しました:" + arg2, sp, 1); return(null); } resourceDic.Add(parentName, img); } ConstImage parentImage = resourceDic[parentName] as ConstImage; if (parentImage == null || !parentImage.IsCreated) { ParserMediator.Warn("作成に失敗したリソースを元にスプライトを作成しようとしました:" + arg2, sp, 1); return(null); } Rectangle rect = new Rectangle(new Point(0, 0), parentImage.Bitmap.Size); Point pos = new Point(); int delay = 1000; //name,parentname, x,y,w,h ,offset_x,offset_y, delayTime if (tokens.Length >= 6) //x,y,w,h { int[] rectValue = new int[4]; bool sccs = true; for (int i = 0; i < 4; i++) { sccs &= int.TryParse(tokens[i + 2], out rectValue[i]); } if (sccs) { rect = new Rectangle(rectValue[0], rectValue[1], rectValue[2], rectValue[3]); pos = new Point(rectValue[0], rectValue[1]); if (rect.Width <= 0 || rect.Height <= 0) { ParserMediator.Warn("スプライトの高さ又は幅には正の値のみ指定できます:" + name, sp, 1); return(null); } //uEmuera在此时尚未获取图片尺寸 //if (!rect.IntersectsWith(new Rectangle(0,0,parentImage.Bitmap.Width, parentImage.Bitmap.Height))) //{ // ParserMediator.Warn("親画像の範囲外を参照しています:" + name, sp, 1); // return null; //} } if (tokens.Length >= 8) { sccs = true; for (int i = 0; i < 2; i++) { sccs &= int.TryParse(tokens[i + 6], out rectValue[i]); } if (sccs) { pos = new Point(rectValue[0], rectValue[1]); } if (tokens.Length >= 9) { sccs = int.TryParse(tokens[8], out delay); if (sccs && delay <= 0) { ParserMediator.Warn("フレーム表示時間には正の値のみ指定できます:" + name, sp, 1); return(null); } } } } //既存のスプライトに対するフレーム追加 if (currentAnime != null && currentAnime.Name == name) { if (!currentAnime.AddFrame(parentImage, rect, pos, delay)) { ParserMediator.Warn("アニメーションスプライトのフレームの追加に失敗しました:" + arg2, sp, 1); return(null); } return(null); } //新規スプライト定義 ASprite image = new SpriteF(name, parentImage, rect, pos); return(image); }
static public bool LoadContents() { if (!Directory.Exists(Program.ContentDir)) { return(true); } try { // List<string> bmpfilelist = new List<string>(); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.png", SearchOption.TopDirectoryOnly)); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.bmp", SearchOption.TopDirectoryOnly)); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.jpg", SearchOption.TopDirectoryOnly)); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.gif", SearchOption.TopDirectoryOnly)); //#if(UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.PNG", SearchOption.TopDirectoryOnly)); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.BMP", SearchOption.TopDirectoryOnly)); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.JPG", SearchOption.TopDirectoryOnly)); // bmpfilelist.AddRange(Directory.GetFiles(Program.ContentDir, "*.GIF", SearchOption.TopDirectoryOnly)); //#endif // foreach(var filename in bmpfilelist) //{//リスト化のみ。Loadはまだ // string name = Path.GetFileName(filename).ToUpper(); // resourceDic.Add(name, new BaseImage(name, filename)); //} //var bmpfilelist = uEmuera.Utils.GetContentFiles(); //foreach(var kv in bmpfilelist) //{ // resourceDic.Add(kv.Key, new BaseImage(kv.Key, kv.Value)); //} List <string> csvFiles = new List <string>(Directory.GetFiles(Program.ContentDir, "*.csv", SearchOption.TopDirectoryOnly)); #if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR csvFiles.AddRange(Directory.GetFiles(Program.ContentDir, "*.CSV", SearchOption.TopDirectoryOnly)); #endif var count = csvFiles.Count; for (var i = 0; i < count; ++i) { var filepath = csvFiles[i]; SpriteAnime currentAnime = null; string directory = Path.GetDirectoryName(filepath) + "/"; string filename = Path.GetFileName(filepath); //string[] lines = File.ReadAllLines(filepath, Config.Encode); string[] lines = uEmuera.Utils.GetResourceCSVLines(filepath, Config.Encode); int lineNo = 0; var linecount = lines.Length; for (var l = 0; l < linecount; ++l) { var line = lines[l]; lineNo++; if (line.Length == 0) { continue; } string str = line.Trim(); if (str.Length == 0 || str.StartsWith(";")) { continue; } string[] tokens = str.Split(','); //AContentItem item = CreateFromCsv(tokens); ScriptPosition sp = new ScriptPosition(filename, lineNo, line); ASprite item = CreateFromCsv(tokens, directory, currentAnime, sp) as ASprite; if (item != null) { currentAnime = item as SpriteAnime; if (!imageDictionary.ContainsKey(item.Name)) { imageDictionary.Add(item.Name, item); } else { ParserMediator.Warn("同名のリソースがすでに作成されています:" + item.Name, sp, 0); item.Dispose(); } } } } } catch (Exception) { return(false); //throw new CodeEE("リソースファイルのロード中にエラーが発生しました"); } return(true); }
internal void AddKeyword(string token, string token2, ScriptPosition position) { var token2Enabled = (token2?.Length == 0); if (!token2Enabled) { ParserMediator.Warn(token + "に余分な引数があります", position, 1); } else { switch (token) { case "SKIPSTART": if (skip) { ParserMediator.Warn("[SKIPSTART]が重複して使用されています", position, 1); break; } ppMatch.Push("SKIPEND"); disabledStack.Push(Disabled); doneStack.Push(done); done = false; Disabled = skip = true; break; case "IF_DEBUG": ppMatch.Push("ELSEIF"); disabledStack.Push(Disabled); doneStack.Push(done); Disabled = !Program.DebugMode; done = !Disabled; break; case "IF_NDEBUG": ppMatch.Push("ELSEIF"); disabledStack.Push(Disabled); doneStack.Push(done); Disabled = Program.DebugMode; done = !Disabled; break; case "IF": ppMatch.Push("ELSEIF"); disabledStack.Push(Disabled); doneStack.Push(done); Disabled = GlobalStatic.IdentifierDictionary.GetMacro(token2) == null; done = !Disabled; break; case "ELSEIF": if (ppMatch.Count == 0 || ppMatch.Pop() != "ELSEIF") { ParserMediator.Warn("不適切な[ELSEIF]です", position, 1); break; } ppMatch.Push("ELSEIF"); Disabled = done || (GlobalStatic.IdentifierDictionary.GetMacro(token2) == null); done |= !Disabled; break; case "ELSE": if (!string.IsNullOrEmpty(token2)) { ParserMediator.Warn(token + "に余分な引数があります", position, 1); break; } if (ppMatch.Count == 0 || ppMatch.Pop() != "ELSEIF") { ParserMediator.Warn("不適切な[ELSE]です", position, 1); break; } ppMatch.Push("ENDIF"); Disabled = done; done = true; break; case "SKIPEND": { string match = ppMatch.Count == 0 ? "" : ppMatch.Pop(); if (match != "SKIPEND") { ParserMediator.Warn("[SKIPSTART]と対応しない[SKIPEND]です", position, 1); break; } skip = false; Disabled = disabledStack.Pop(); done = doneStack.Pop(); } break; case "ENDIF": { string match = ppMatch.Count == 0 ? "" : ppMatch.Pop(); if (match != "ENDIF" && match != "ELSEIF") { ParserMediator.Warn("対応する[IF]のない[ENDIF]です", position, 1); break; } Disabled = disabledStack.Pop(); done = doneStack.Pop(); } break; default: ParserMediator.Warn("認識できないプリプロセッサです", position, 1); break; } } if (skip) { Disabled = true; } }
private bool loadHeaderFile(string filepath, string filename) { StringStream st = null; ScriptPosition position = null; //EraStreamReader eReader = new EraStreamReader(false); //1815修正 _rename.csvの適用 //eramakerEXの仕様的には.ERHに適用するのはおかしいけど、もうEmueraの仕様になっちゃってるのでしかたないか var eReader = new EraStreamReader(true); if (!eReader.Open(filepath, filename)) { throw new CodeEE(eReader.Filename + "のオープンに失敗しました"); } try { while ((st = eReader.ReadEnabledLine()) != null) { if (!noError) { return(false); } position = new ScriptPosition(filename, eReader.LineNo, st.RowString); LexicalAnalyzer.SkipWhiteSpace(st); if (st.Current != '#') { throw new CodeEE("ヘッダーの中に#で始まらない行があります", position); } st.ShiftNext(); var sharpID = LexicalAnalyzer.ReadSingleIdentifier(st); if (sharpID == null) { ParserMediator.Warn("解釈できない#行です", position, 1); return(false); } if (Config.ICFunction) { sharpID = sharpID.ToUpper(); } LexicalAnalyzer.SkipWhiteSpace(st); switch (sharpID) { case "DEFINE": analyzeSharpDefine(st, position); break; case "FUNCTION": case "FUNCTIONS": analyzeSharpFunction(st, position, sharpID == "FUNCTIONS"); break; case "DIM": case "DIMS": analyzeSharpDim(st, position, sharpID == "DIMS"); break; default: throw new CodeEE("#" + sharpID + "は解釈できないプリプロセッサです", position); } } } catch (CodeEE e) { if (e.Position != null) { position = e.Position; } ParserMediator.Warn(e.Message, position, 2); return(false); } finally { eReader.Close(); } return(true); }
//#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); }
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); }
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); }
/// <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()); }
/// <summary> /// GAMEBASE読み込み。GAMEBASE.csvの存在は必須ではないので読み込み失敗したらなかったことにする。 /// </summary> /// <param name="basePath"></param> /// <returns>読み込み続行するなら真、エラー終了なら偽</returns> public bool LoadGameBaseCsv(string basePath) { if (!File.Exists(basePath)) { return(true); } ScriptPosition pos = null; EraStreamReader eReader = new EraStreamReader(false); if (!eReader.Open(basePath)) { //output.PrintLine(eReader.Filename + "のオープンに失敗しました"); return(true); } try { StringStream st = null; while ((st = eReader.ReadEnabledLine()) != null) { string[] tokens = st.Substring().Split(','); if (tokens.Length < 2) { continue; } string param = tokens[1].Trim(); pos = new ScriptPosition(eReader.Filename, eReader.LineNo, st.RowString); switch (tokens[0]) { case "コード": if (tryatoi(tokens[1], out ScriptUniqueCode)) { if (ScriptUniqueCode == 0L) { ParserMediator.Warn("コード:0のセーブデータはいかなるコードのスクリプトからも読めるデータとして扱われます", pos, 0); } } break; case "バージョン": ScriptVersionDefined = tryatoi(tokens[1], out ScriptVersion); break; case "バージョン違い認める": tryatoi(tokens[1], out ScriptCompatibleMinVersion); break; case "最初からいるキャラ": tryatoi(tokens[1], out DefaultCharacter); break; case "アイテムなし": tryatoi(tokens[1], out DefaultNoItem); break; case "タイトル": ScriptTitle = tokens[1]; break; case "作者": ScriptAutherName = tokens[1]; break; case "製作年": ScriptYear = tokens[1]; break; case "追加情報": ScriptDetail = tokens[1]; break; case "ウィンドウタイトル": ScriptWindowTitle = tokens[1]; break; case "動作に必要なEmueraのバージョン": Compatible_EmueraVer = tokens[1]; if (!Regex.IsMatch(Compatible_EmueraVer, @"^\d+\.\d+\.\d+\.\d+$")) { ParserMediator.Warn("バージョン指定を読み取れなかったので処理を省略します", pos, 0); break; } Version curerntVersion = new Version(GlobalStatic.MainWindow.InternalEmueraVer); Version targetVersoin = new Version(Compatible_EmueraVer); if (curerntVersion < targetVersoin) { ParserMediator.Warn("このバリアント動作させるにはVer. " + GlobalStatic.MainWindow.EmueraVerText + "以降のバージョンのEmueraが必要です", pos, 2); return(false); } break; } } } catch { ParserMediator.Warn("GAMEBASE.CSVの読み込み中にエラーが発生したため、読みこみを中断します", pos, 1); return(true); } finally { eReader.Close(); } if (ScriptWindowTitle == null) { if (string.IsNullOrEmpty(ScriptTitle)) { ScriptWindowTitle = "Emuera"; } else { ScriptWindowTitle = ScriptTitle + " " + ScriptVersionText; } } return(true); }