Advertisement
Guest User

Untitled

a guest
Mar 29th, 2020
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.47 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text.RegularExpressions;
  6.  
  7. namespace KizhiPart1
  8. {
  9. public class Function
  10. {
  11. public Function(int enter)
  12. {
  13. EnterLine = enter;
  14. }
  15.  
  16. public int EnterLine { get; }
  17. public int EndLine { get; set; }
  18. }
  19.  
  20. public class Interpreter
  21. {
  22. private readonly TextWriter writer;
  23. private readonly Dictionary<string, Action<string, int, int>> commands;
  24. private readonly Dictionary<string, Tuple<int, int>> variables;
  25. private readonly Dictionary<string, Function> functions;
  26. private readonly List<string> codeToRun;
  27. private readonly HashSet<int> breakPoints;
  28. private int executingLineIndex;
  29. private readonly Stack<Tuple<int, string>> trace;
  30. public bool IsSteppingInto { get; set; }
  31.  
  32. public Interpreter(TextWriter writer)
  33. {
  34. this.writer = writer;
  35. variables = new Dictionary<string, Tuple<int, int>>();
  36. functions = new Dictionary<string, Function>();
  37. breakPoints = new HashSet<int>();
  38. trace = new Stack<Tuple<int, string>>();
  39. commands = new Dictionary<string, Action<string, int, int>>
  40. {
  41. { "set", Set },
  42. { "sub", Sub },
  43. { "print", Print },
  44. { "rem", Remove },
  45. { "call", Call },
  46. { "def", Def },
  47. };
  48. }
  49.  
  50. public void AddBreakPoint(int index)
  51. {
  52. breakPoints.Add(index);
  53. }
  54.  
  55. public void PrintMemory()
  56. {
  57. foreach (var variable in variables)
  58. writer.WriteLine("{0} {1} {2}", variable.Key, variable.Value.Item1, variable.Value.Item2);
  59. }
  60.  
  61. public void PrintTrace()
  62. {
  63. foreach (var call in trace)
  64. writer.WriteLine("{0} {1}", call.Item1, call.Item2);
  65. }
  66.  
  67. private void ExecuteCommand(string line, int lineIndex)
  68. {
  69. var match = GetCommandMatch(line);
  70. if (!match.Success)
  71. throw new Exception();
  72. var command = match.Groups["command"].Value;
  73. if (!commands.ContainsKey(command))
  74. throw new Exception();
  75. var variable = match.Groups["variable"].Value;
  76. int.TryParse(match.Groups["value"].Value, out int value);
  77. commands[command](variable, value, lineIndex);
  78. }
  79.  
  80. private Match GetCommandMatch(string line)
  81. {
  82. var pattern = @"^(?<command>\w+)\s+(?<variable>[a-zA-z]+)(\s+(?<value>[1-9][0-9]*))?$";
  83. var re = new Regex(pattern);
  84. return re.Match(line);
  85. }
  86.  
  87. private void Set(string variable, int value, int lineIndex)
  88. {
  89. variables[variable] = Tuple.Create(value, lineIndex);
  90. }
  91.  
  92.  
  93. private void Sub(string variable, int value, int lineIndex)
  94. {
  95. if (!variables.ContainsKey(variable))
  96. writer.WriteLine("Переменная отсутствует в памяти");
  97. else
  98. variables[variable] = Tuple.Create(variables[variable].Item1 - value, lineIndex);
  99. }
  100.  
  101. private void Print(string variable, int _, int lineIndex)
  102. {
  103. if (!variables.ContainsKey(variable))
  104. writer.WriteLine("Переменная отсутствует в памяти");
  105. else
  106. writer.WriteLine(variables[variable].Item1);
  107. }
  108.  
  109. private void Remove(string variable, int _, int __)
  110. {
  111. if (!variables.ContainsKey(variable))
  112. writer.WriteLine("Переменная отсутствует в памяти");
  113. else
  114. variables.Remove(variable);
  115. }
  116.  
  117. private void Call(string functionName, int _, int lineIndex)
  118. {
  119. executingLineIndex = functions[functionName].EnterLine;
  120. trace.Push(Tuple.Create(lineIndex, functionName));
  121. }
  122.  
  123. private void Def(string functionName, int _, int __)
  124. {
  125. executingLineIndex = functions[functionName].EndLine;
  126. }
  127.  
  128. public void Run()
  129. {
  130. var isStopped = false;
  131. while (!isStopped)
  132. {
  133. isStopped = Step();
  134. }
  135. if (executingLineIndex == codeToRun.Count)
  136. {
  137. variables.Clear();
  138. functions.Clear();
  139. }
  140. }
  141.  
  142. public bool Step()
  143. {
  144. if (trace.Count != 0)
  145. {
  146. var funcCall = trace.Peek();
  147. if (executingLineIndex > functions[funcCall.Item2].EndLine)
  148. {
  149. trace.Pop();
  150. executingLineIndex = funcCall.Item1 + 1;
  151. }
  152. }
  153.  
  154. if (executingLineIndex >= codeToRun.Count)
  155. return true;
  156.  
  157. var match = GetCommandMatch(codeToRun[executingLineIndex]);
  158. if (match.Groups["command"].Value == "def")
  159. executingLineIndex = functions[match.Groups["variable"].Value].EndLine + 1;
  160.  
  161. if ((breakPoints.Contains(executingLineIndex) && !IsSteppingInto) || executingLineIndex == codeToRun.Count)
  162. return true;
  163. IsSteppingInto = false;
  164.  
  165. ExecuteCommand(codeToRun[executingLineIndex], executingLineIndex);
  166. executingLineIndex += 1;
  167. if (executingLineIndex == codeToRun.Count)
  168. {
  169. variables.Clear();
  170. functions.Clear();
  171. }
  172. return false;
  173. }
  174.  
  175. public void StepOver()
  176. {
  177. var traceDepth = trace.Count;
  178. Step();
  179. while (traceDepth < trace.Count)
  180. {
  181. if (trace.Count != 0)
  182. {
  183. var funcCall = trace.Peek();
  184. if (executingLineIndex > functions[funcCall.Item2].EndLine)
  185. {
  186. trace.Pop();
  187. executingLineIndex = funcCall.Item1 + 1;
  188. break;
  189. }
  190. }
  191.  
  192. if (executingLineIndex == codeToRun.Count)
  193. break;
  194.  
  195. ExecuteCommand(codeToRun[executingLineIndex], executingLineIndex);
  196. executingLineIndex += 1;
  197. }
  198. if (executingLineIndex == codeToRun.Count)
  199. {
  200. variables.Clear();
  201. functions.Clear();
  202. }
  203. }
  204.  
  205. public List<string> GetCodeToRun(string[] code)
  206. {
  207. var codeLines = code.Select(line => line.Trim()).ToList();
  208. FindAllFunctions(code);
  209. return codeLines;
  210. }
  211.  
  212. private void FindAllFunctions(string[] code)
  213. {
  214. const int indentation = 4;
  215. var isReadingFunction = false;
  216. var currentFunction = "";
  217. var wsLeftPattern = @"^ +";
  218. var wsLeftCount = new Regex(wsLeftPattern);
  219. for (int i = 0; i < code.Length; i++)
  220. {
  221. string line = code[i];
  222. var wsCount = wsLeftCount.Match(line).Length;
  223. if (isReadingFunction)
  224. {
  225. if (wsCount == 0)
  226. {
  227. isReadingFunction = false;
  228. functions[currentFunction].EndLine = i - 1;
  229. }
  230. else if (wsCount != indentation)
  231. throw new Exception("Incorrect indentation");
  232. }
  233. var match = GetCommandMatch(line.Trim());
  234. if (match.Groups["command"].Value == "def")
  235. {
  236. isReadingFunction = true;
  237. currentFunction = match.Groups["variable"].Value;
  238. functions[currentFunction] = new Function(i + 1);
  239. }
  240. }
  241. }
  242. }
  243.  
  244. public class Debugger
  245. {
  246. private readonly Interpreter interpreter;
  247. private bool isSettingCode;
  248.  
  249. public Debugger(TextWriter writer)
  250. {
  251. interpreter = new Interpreter(writer);
  252. }
  253.  
  254. public void ExecuteLine(string line, int lineIndex = 0)
  255. {
  256. if (line == "set code")
  257. isSettingCode = true;
  258. else if (line == "end set code")
  259. isSettingCode = false;
  260. else if (line == "run")
  261. {
  262. interpreter.IsSteppingInto = true;
  263. //if (executingLineIndex == codeToRun.Count)
  264. //executingLineIndex = 0;
  265. interpreter.Run();
  266. }
  267. else if (line == "step")
  268. {
  269. interpreter.IsSteppingInto = true;
  270. interpreter.Step();
  271. }
  272. else if (line == "step over")
  273. {
  274. interpreter.IsSteppingInto = true;
  275. interpreter.StepOver();
  276. }
  277. else if (line == "print mem")
  278. interpreter.PrintMemory();
  279. else if (line == "print trace")
  280. interpreter.PrintTrace();
  281. else if (isSettingCode)
  282. interpreter.GetCodeToRun(line.Split('\n'));
  283. }
  284. }
  285. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement