Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text.RegularExpressions;
- namespace KizhiPart1
- {
- public class Function
- {
- public Function(int enter)
- {
- EnterLine = enter;
- }
- public int EnterLine { get; }
- public int EndLine { get; set; }
- }
- public class Interpreter
- {
- private readonly TextWriter writer;
- private readonly Dictionary<string, Action<string, int, int>> commands;
- private readonly Dictionary<string, Tuple<int, int>> variables;
- private readonly Dictionary<string, Function> functions;
- private readonly List<string> codeToRun;
- private readonly HashSet<int> breakPoints;
- private int executingLineIndex;
- private readonly Stack<Tuple<int, string>> trace;
- public bool IsSteppingInto { get; set; }
- public Interpreter(TextWriter writer)
- {
- this.writer = writer;
- variables = new Dictionary<string, Tuple<int, int>>();
- functions = new Dictionary<string, Function>();
- breakPoints = new HashSet<int>();
- trace = new Stack<Tuple<int, string>>();
- commands = new Dictionary<string, Action<string, int, int>>
- {
- { "set", Set },
- { "sub", Sub },
- { "print", Print },
- { "rem", Remove },
- { "call", Call },
- { "def", Def },
- };
- }
- public void AddBreakPoint(int index)
- {
- breakPoints.Add(index);
- }
- public void PrintMemory()
- {
- foreach (var variable in variables)
- writer.WriteLine("{0} {1} {2}", variable.Key, variable.Value.Item1, variable.Value.Item2);
- }
- public void PrintTrace()
- {
- foreach (var call in trace)
- writer.WriteLine("{0} {1}", call.Item1, call.Item2);
- }
- private void ExecuteCommand(string line, int lineIndex)
- {
- var match = GetCommandMatch(line);
- if (!match.Success)
- throw new Exception();
- var command = match.Groups["command"].Value;
- if (!commands.ContainsKey(command))
- throw new Exception();
- var variable = match.Groups["variable"].Value;
- int.TryParse(match.Groups["value"].Value, out int value);
- commands[command](variable, value, lineIndex);
- }
- private Match GetCommandMatch(string line)
- {
- var pattern = @"^(?<command>\w+)\s+(?<variable>[a-zA-z]+)(\s+(?<value>[1-9][0-9]*))?$";
- var re = new Regex(pattern);
- return re.Match(line);
- }
- private void Set(string variable, int value, int lineIndex)
- {
- variables[variable] = Tuple.Create(value, lineIndex);
- }
- private void Sub(string variable, int value, int lineIndex)
- {
- if (!variables.ContainsKey(variable))
- writer.WriteLine("Переменная отсутствует в памяти");
- else
- variables[variable] = Tuple.Create(variables[variable].Item1 - value, lineIndex);
- }
- private void Print(string variable, int _, int lineIndex)
- {
- if (!variables.ContainsKey(variable))
- writer.WriteLine("Переменная отсутствует в памяти");
- else
- writer.WriteLine(variables[variable].Item1);
- }
- private void Remove(string variable, int _, int __)
- {
- if (!variables.ContainsKey(variable))
- writer.WriteLine("Переменная отсутствует в памяти");
- else
- variables.Remove(variable);
- }
- private void Call(string functionName, int _, int lineIndex)
- {
- executingLineIndex = functions[functionName].EnterLine;
- trace.Push(Tuple.Create(lineIndex, functionName));
- }
- private void Def(string functionName, int _, int __)
- {
- executingLineIndex = functions[functionName].EndLine;
- }
- public void Run()
- {
- var isStopped = false;
- while (!isStopped)
- {
- isStopped = Step();
- }
- if (executingLineIndex == codeToRun.Count)
- {
- variables.Clear();
- functions.Clear();
- }
- }
- public bool Step()
- {
- if (trace.Count != 0)
- {
- var funcCall = trace.Peek();
- if (executingLineIndex > functions[funcCall.Item2].EndLine)
- {
- trace.Pop();
- executingLineIndex = funcCall.Item1 + 1;
- }
- }
- if (executingLineIndex >= codeToRun.Count)
- return true;
- var match = GetCommandMatch(codeToRun[executingLineIndex]);
- if (match.Groups["command"].Value == "def")
- executingLineIndex = functions[match.Groups["variable"].Value].EndLine + 1;
- if ((breakPoints.Contains(executingLineIndex) && !IsSteppingInto) || executingLineIndex == codeToRun.Count)
- return true;
- IsSteppingInto = false;
- ExecuteCommand(codeToRun[executingLineIndex], executingLineIndex);
- executingLineIndex += 1;
- if (executingLineIndex == codeToRun.Count)
- {
- variables.Clear();
- functions.Clear();
- }
- return false;
- }
- public void StepOver()
- {
- var traceDepth = trace.Count;
- Step();
- while (traceDepth < trace.Count)
- {
- if (trace.Count != 0)
- {
- var funcCall = trace.Peek();
- if (executingLineIndex > functions[funcCall.Item2].EndLine)
- {
- trace.Pop();
- executingLineIndex = funcCall.Item1 + 1;
- break;
- }
- }
- if (executingLineIndex == codeToRun.Count)
- break;
- ExecuteCommand(codeToRun[executingLineIndex], executingLineIndex);
- executingLineIndex += 1;
- }
- if (executingLineIndex == codeToRun.Count)
- {
- variables.Clear();
- functions.Clear();
- }
- }
- public List<string> GetCodeToRun(string[] code)
- {
- var codeLines = code.Select(line => line.Trim()).ToList();
- FindAllFunctions(code);
- return codeLines;
- }
- private void FindAllFunctions(string[] code)
- {
- const int indentation = 4;
- var isReadingFunction = false;
- var currentFunction = "";
- var wsLeftPattern = @"^ +";
- var wsLeftCount = new Regex(wsLeftPattern);
- for (int i = 0; i < code.Length; i++)
- {
- string line = code[i];
- var wsCount = wsLeftCount.Match(line).Length;
- if (isReadingFunction)
- {
- if (wsCount == 0)
- {
- isReadingFunction = false;
- functions[currentFunction].EndLine = i - 1;
- }
- else if (wsCount != indentation)
- throw new Exception("Incorrect indentation");
- }
- var match = GetCommandMatch(line.Trim());
- if (match.Groups["command"].Value == "def")
- {
- isReadingFunction = true;
- currentFunction = match.Groups["variable"].Value;
- functions[currentFunction] = new Function(i + 1);
- }
- }
- }
- }
- public class Debugger
- {
- private readonly Interpreter interpreter;
- private bool isSettingCode;
- public Debugger(TextWriter writer)
- {
- interpreter = new Interpreter(writer);
- }
- public void ExecuteLine(string line, int lineIndex = 0)
- {
- if (line == "set code")
- isSettingCode = true;
- else if (line == "end set code")
- isSettingCode = false;
- else if (line == "run")
- {
- interpreter.IsSteppingInto = true;
- //if (executingLineIndex == codeToRun.Count)
- //executingLineIndex = 0;
- interpreter.Run();
- }
- else if (line == "step")
- {
- interpreter.IsSteppingInto = true;
- interpreter.Step();
- }
- else if (line == "step over")
- {
- interpreter.IsSteppingInto = true;
- interpreter.StepOver();
- }
- else if (line == "print mem")
- interpreter.PrintMemory();
- else if (line == "print trace")
- interpreter.PrintTrace();
- else if (isSettingCode)
- interpreter.GetCodeToRun(line.Split('\n'));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement