private int ParseProcedureArguments(int start, int end, string vName, string[] code) { if (start > code.Length) { return(-1); } int len = ParserInternal.VARIABLE.Length + vName.Length; for (int i = start - 1; i > end; i--) { string line = code[i].TrimStart().ToLowerInvariant(); if (len > line.Length) { continue; } int y = line.IndexOf(ParserInternal.VARIABLE); if (y == -1) { continue; } line = ParserInternal.RemoveDoubleWhiteSpaces(line, y, 0); TryPass: int x = line.IndexOf(ParserInternal.VARIABLE + vName, y); if (x > -1) { char c = line[x + len]; if (c == '_' || Char.IsLetterOrDigit(c)) { line = line.Remove(x, len); goto TryPass; } int z = line.IndexOf(ParserInternal.BEGIN); if (z > -1 && x > z) { break; // переменная находится за пределами begin } return(i + 1); } if (line.StartsWith(ParserInternal.PROCEDURE)) { break; // найдена процедура, прерываем цикл } } return(-1); }
public static void ParseNodeCode(string text, List <DialogueParser> args, ProgramInfo pi, bool diagram = false, bool excludeComment = true, StringSplitOptions splitOption = StringSplitOptions.RemoveEmptyEntries) { DialogueParser.pi = pi; int _comm = 0, _count = 0; Regex regex = new Regex(@"\b" + OpcodeType.call.ToString() + @"\b", RegexOptions.IgnoreCase); string[] bodyNode = text.Split(new char[] { '\n' }, splitOption); for (int i = 0; i < bodyNode.Length; i++) { nLine = i; string str = bodyNode[i].TrimEnd(); if (excludeComment || !diagram) { string _str = str.TrimStart(); if (ParserInternal.CommentBlockParse(ref _str, ref _comm)) { continue; } } if (excludeComment || diagram) { _count = args.Count; } ReplySubParse(args, str, OpcodeType.Message); ReplySubParse(args, str, OpcodeType.Reply); OptionSubParse(args, str); MiscSubParse(args, str); // для макросов использующихся как переход к ноде // for call opcode MatchCollection matches = regex.Matches(str); foreach (Match m in matches) { args.Add(new DialogueParser(OpcodeType.call, null, str, m.Index + 4)); } // для диаграмм добавляем строку кода из ноды if (diagram && _count == args.Count) { args.Add(new DialogueParser(OpcodeType.None, null, str)); } } }
public List <FoldMarker> GenerateFoldMarkers(IDocument document, string fileName, object parseInformation) { Procedure[] procs = (Procedure[])parseInformation; List <FoldMarker> list = new List <FoldMarker>(procs.Length); int minStart = -1; fileName = fileName.ToLowerInvariant(); for (int i = 0; i < procs.Length; i++) { string fstart = Path.GetFileName(procs[i].fstart ?? string.Empty).ToLowerInvariant(); if (fstart != fileName || procs[i].d.start >= procs[i].d.end) { continue; } int dstart = procs[i].d.start - 1; if (minStart > dstart || minStart == -1) { minStart = dstart; } int len = document.GetLineSegment(procs[i].d.end - 1).Length; list.Add(new FoldMarker(document, dstart, 0, procs[i].d.end - 1, len, FoldType.MemberBody, " " + procs[i].name.ToUpperInvariant() + " ")); } if (list.Count > 0 && Path.GetExtension(fileName) == ".ssl") { ProcedureBlock dRegion = ParserInternal.GetRegionDeclaration(document.TextContent, minStart); if (dRegion.end < 0) { dRegion.end = minStart - 2; } if (dRegion.end > dRegion.begin) { list.Add(new FoldMarker(document, dRegion.begin, 0, dRegion.end, 1000, FoldType.Region, " - Declaration Region - ")); } } // Get variable and #if foldings block List <ProcedureBlock> blockList = ParserInternal.GetFoldingBlock(document.TextContent); foreach (ProcedureBlock block in blockList) { string str = block.copy ? TextUtilities.GetLineAsString(document, block.begin) + " " : " - Variables - "; list.Add(new FoldMarker(document, block.begin, 0, block.end, 1000, FoldType.TypeBody, str)); } return(list); }
public GetMacros(string[] lines, string file, string dir, SortedDictionary <string, Macro> macros, bool include = true) { if (dir == null) { dir = Path.GetDirectoryName(file); } bool commentBlock = false; for (int i = 0; i < lines.Length; i++) { if (lines[i].Length < 2) { continue; } lines[i] = lines[i].Replace('\t', ' ').Trim(); // убираем все лишнее #region Пропускаем закоментированные макросы if (lines[i].StartsWith("//")) { continue; } if (!commentBlock) { if (lines[i].StartsWith("/*")) { if (lines[i].LastIndexOf("*/") == -1) { commentBlock = true; // в встроке нет закрывающего тэга } continue; } } else { int close = lines[i].IndexOf("*/"); if (close == -1) { continue; } commentBlock = false; close += 2; if (close == lines[i].Length) { continue; } lines[i] = lines[i].Remove(0, close).TrimStart(); } if (lines[i].Length <= 8) { continue; // минимальное необходимое значение для ключевого слова #define } #endregion if (include && lines[i].StartsWith(ParserInternal.INCLUDE)) { string[] text = lines[i].Split('"'); if (text.Length < 2) { continue; } if (text[1].IndexOfAny(Path.GetInvalidPathChars()) != -1) { continue; } ParserInternal.GetIncludePath(ref text[1], dir); new GetMacros(text[1], null, macros); } else if (lines[i].StartsWith(ParserInternal.DEFINE)) { // описание к макросу List <string> desc = new List <string>(); int descBlock = 0; for (int j = i - 1; j >= 0; j--) { if (descBlock <= 0 && lines[j].Length == 0) { break; } string line = lines[j]; int n = line.LastIndexOf(" **/"); if (descBlock == 0 && n == -1) { break; } if (n != -1) { descBlock++; line = line.Remove(n); } n = line.IndexOf("/** "); if (n != -1) { descBlock--; if (descBlock < 0) { break; } line = line.Substring(n + 4); } desc.Add(line.Trim()); } string description = null; if (desc.Count > 0) { var sbDesc = new StringBuilder(); desc.Reverse(); foreach (var item in desc) { sbDesc.AppendLine(item); } description = sbDesc.ToString(); } if (lines[i].EndsWith(@"\")) { var sb = new StringBuilder(); int lineno = i; lines[i] = lines[i].Substring(8); do { sb.Append(lines[i].Remove(lines[i].Length - 1).TrimEnd()); // удаляем пробелы и символ '\' в конце макроса sb.Append(Environment.NewLine); i++; lines[i] = lines[i].TrimEnd(); } while (lines[i].EndsWith(@"\")); sb.Append(lines[i]); AddMacro(sb.ToString(), macros, file, lineno, description); } else { AddMacro(lines[i].Substring(8), macros, file, i, description); } } } }
public ProgramInfo Parse(string text, string filepath, ProgramInfo prev_pi) { // Parse disabled, get only macros if (Settings.enableParser && filepath != null) { File.WriteAllText(parserPath, text, Encoding.Default); try { lastStatus = parse_main(parserPath, filepath, Path.GetDirectoryName(filepath), Settings.preprocDef, (Settings.IsSearchIncludes) ? Settings.pathHeadersFiles : null, Settings.compileBackwardMode); } catch { lastStatus = 3; MessageBox.Show("An unexpected error occurred while parsing text of the script.\n" + "It is recommended that you save all unsaved documents and restart application,\n" + "in order to avoid further incorrect operation of the application.", "Error: Parser.dll"); }; } ProgramInfo pi = (lastStatus >= 1) ? prev_pi //new ProgramInfo(0, 0) : new ProgramInfo(numProcs(), numVars()); if (lastStatus >= 1 && prev_pi != null) // preprocess error - store previous data Procs/Vars { if (prev_pi.parsed) //.parseData { if (Settings.enableParser) { pi = (!pi.reParseData) ? ParserInternal.UpdateProcsPI(prev_pi, text, filepath) : ParserInternal.UpdatePI(prev_pi, filepath); } else if (firstParse) { pi.RebuildProcedureDictionary(); } } if (!pi.reParseData) { pi.macros.Clear(); } } pi.parseError = (lastStatus != 0 & Settings.enableParser); // // Macros // string[] scriptCode = text.Split('\n'); if (!pi.reParseData) { new GetMacros(scriptCode, filepath, Path.GetDirectoryName(filepath), pi.macros); } pi.parsed = true; pi.reParseData = false; if (lastStatus >= 1) { return(pi); // parse failed, return macros and previous parsed data Procs/Vars } // // Getting data of variables/procedures // pi.parseData = true; // received data from parser.dll byte[] names = new byte[namespaceSize()]; int stringsSize = stringspaceSize(); getNamespace(names); byte[] strings = null; if (stringsSize > 0) { strings = new byte[stringsSize]; getStringspace(strings); } // Variables for (int i = 0; i < pi.vars.Length; i++) { pi.vars[i] = new Variable(); getVar(i, out pi.vars[i].d); pi.vars[i].name = ParseName(names, pi.vars[i].d.name); if (pi.vars[i].d.initialized != 0) { switch (pi.vars[i].d.initialType) { case ValueType.Int: pi.vars[i].initialValue = pi.vars[i].d.intValue.ToString(); break; case ValueType.Float: pi.vars[i].initialValue = pi.vars[i].d.floatValue.ToString(); break; case ValueType.String: pi.vars[i].initialValue = '"' + ParseName(strings, pi.vars[i].d.intValue) + '"'; break; } } if (pi.vars[i].d.fdeclared != IntPtr.Zero) { pi.vars[i].fdeclared = Path.GetFullPath(Marshal.PtrToStringAnsi(pi.vars[i].d.fdeclared)); pi.vars[i].filename = Path.GetFileName(pi.vars[i].fdeclared).ToLowerInvariant(); } if (pi.vars[i].d.numRefs == 0) { pi.vars[i].references = new Reference[0]; } else { int[] tmp = new int[pi.vars[i].d.numRefs * 2]; getVarRefs(i, tmp); pi.vars[i].references = new Reference[pi.vars[i].d.numRefs]; for (int j = 0; j < pi.vars[i].d.numRefs; j++) { pi.vars[i].references[j] = Reference.FromPtr(tmp[j * 2], tmp[j * 2 + 1]); } } } // Procedures for (int i = 0; i < pi.procs.Length; i++) { pi.procs[i] = new Procedure(); getProc(i, out pi.procs[i].d); pi.procs[i].name = ParseName(names, pi.procs[i].d.name); if (pi.procs[i].d.fdeclared != IntPtr.Zero) { //pi.procs[i].fdeclared=Marshal.PtrToStringAnsi(pi.procs[i].d.fdeclared); pi.procs[i].fdeclared = Path.GetFullPath(Marshal.PtrToStringAnsi(pi.procs[i].d.fdeclared)); pi.procs[i].filename = Path.GetFileName(pi.procs[i].fdeclared).ToLowerInvariant(); } if (pi.procs[i].d.fstart != IntPtr.Zero) { //pi.procs[i].fstart = Marshal.PtrToStringAnsi(pi.procs[i].d.fstart); pi.procs[i].fstart = Path.GetFullPath(Marshal.PtrToStringAnsi(pi.procs[i].d.fstart)); } //pi.procs[i].fend=Marshal.PtrToStringAnsi(pi.procs[i].d.fend); if (pi.procs[i].d.numRefs == 0) { pi.procs[i].references = new Reference[0]; } else { int[] tmp = new int[pi.procs[i].d.numRefs * 2]; getProcRefs(i, tmp); pi.procs[i].references = new Reference[pi.procs[i].d.numRefs]; for (int j = 0; j < pi.procs[i].d.numRefs; j++) { pi.procs[i].references[j] = Reference.FromPtr(tmp[j * 2], tmp[j * 2 + 1]); } } // Procedure variables if (getProcNamespaceSize(i) == -1) { pi.procs[i].variables = new Variable[0]; } else { byte[] procnames = new byte[getProcNamespaceSize(i)]; getProcNamespace(i, procnames); pi.procs[i].variables = new Variable[pi.procs[i].d.numVariables]; for (int j = 0; j < pi.procs[i].variables.Length; j++) { Variable var = pi.procs[i].variables[j] = new Variable(); getProcVar(i, j, out var.d); var.name = ParseName(procnames, var.d.name); if (var.d.initialized != 0) { switch (var.d.initialType) { case ValueType.Int: var.initialValue = var.d.intValue.ToString(); break; case ValueType.Float: var.initialValue = var.d.floatValue.ToString(); break; case ValueType.String: var.initialValue = '"' + ParseName(strings, var.d.intValue) + '"'; break; } } var.fdeclared = Marshal.PtrToStringAnsi(var.d.fdeclared); if (var.d.numRefs == 0) { var.references = new Reference[0]; } else { int[] tmp = new int[var.d.numRefs * 2]; getProcVarRefs(i, j, tmp); var.references = new Reference[var.d.numRefs]; for (int k = 0; k < var.d.numRefs; k++) { var.references[k] = Reference.FromPtr(tmp[k * 2], tmp[k * 2 + 1]); } } var.adeclared = ParseProcedureArguments(pi.procs[i].d.start, var.d.declared, var.name.ToLowerInvariant(), scriptCode); } } } pi.BuildDictionaries(); return(pi); }
/// <summary> /// Get information about the location of procedures for updating Foldings /// </summary> internal static void UpdateFolding(IDocument document, string filepath) { Procedure[] parseInformation = ParserInternal.GetProcsData(document.TextContent, filepath); UpdateFolding(document, Path.GetFileName(filepath), parseInformation); }