public string analizeCode(string code) { Program.Clear(); parseLine(code, State.Program); StringBuilder str = new StringBuilder(); CProgram prog = Program.Peek() as CProgram; int index = 0; if (prog != null) { if (prog.Errors.Count == 0) { return(String.Join("\r\n", WriteTree(prog, ref index))); } return(String.Join("\r\n", prog.Errors)); } return(""); }
bool parseLine(string code, State search) { #region StateChecking switch (search) { case State.Variable: { #region Variable code = code.Trim(" \t".ToArray()); // проверка выражения A2b4c6d Regex rVar = new Regex(@"^\w(?:\w|\d)*$"); Match mVar = rVar.Match(code); if (mVar.Success) { Expression var = new Expression(mVar.Groups[0].Value, State.Variable); //bool declared = Variables.Contains(var); //if ( !declared ) // throw new LexemException("Unexpected identifier encountered"); Program.Push(var); return(true); } else { throw new CompileException($"Unknown identifier '{code}'"); } #endregion } case State.Constant: { #region Constant code = code.Trim(" \t".ToArray()); SystemTypes?constVal = Recognise(code); if (constVal != null) { Program.Push(new Expression(code, State.Constant)); return(true); } return(false); #endregion } case State.Declaration: { #region Declaration Regex rdecl = new Regex(@"^int\s+(.+\s*,?)*\s*$"); Match mdecl = rdecl.Match(code); if (mdecl.Success) { List <Expression> Initializes = new List <Expression>(); string[] variables = mdecl.Groups[1].Value.Split(','); foreach (var variable in variables) { if (parseLine(variable, State.Initialization)) { Initializes.Add(Program.Pop()); } else { throw new CompileException("Wrong initialization saw"); } } var newVars = Initializes.Select(init => init.Children[0]); Variables = new HashSet <Expression>(Variables.Concat(newVars)); Expression Declaration = new Expression($"int {String.Join(", ", Initializes.Select(var => var.Code))}", State.Declaration); Declaration.Children.AddRange(Initializes); Program.Push(Declaration); return(true); } return(false); #endregion } case State.Initialization: { #region Initialization Regex rInit = new Regex(@"\s*(?<left>.+)\s*=\s*(?<right>.+)\s*"); Match mInit = rInit.Match(code); if (mInit.Success) { if (!parseLine(mInit.Groups["left"].Value, State.Variable)) { throw new CompileException($"Expected variable, but encountered '{mInit.Groups["left"].Value}'"); } Initialization Initialization; Expression variable = Program.Pop(); Expression value; if (parseLine(mInit.Groups["right"].Value, State.Statement)) { value = Program.Pop(); Initialization = new Initialization(variable, value); Program.Push(Initialization); return(true); } else { throw new CompileException($"Expected statement after '{variable.Code} = '"); } } return(false); #endregion } case State.IF: { #region IF Regex rIf = new Regex(@"^if\s*\((.*)\)\s*$"); Match mIf = rIf.Match(code); if (mIf.Success) { if (parseLine(mIf.Groups[1].Value, State.Statement)) { Expression statement = Program.Peek(); code.Replace(mIf.Groups[0].Value, ""); Expression ifBlock = new Expression($"if ({statement.Code})", State.IF); ifBlock.Children.Add(statement); Program.Pop(); Program.Push(ifBlock); return(true); } else { throw new CompileException("Expected statement in if block"); } } return(false); #endregion } case State.Statement: { #region Statement Regex rInner = new Regex(@"^\(([^\(\)]+)\)$"); Match mInner = rInner.Match(code); bool parantacies = mInner.Success; while (mInner.Success) { code = mInner.Groups[1].Value; mInner = rInner.Match(code); } // проверка выражения a>=b Regex rStatement = new Regex(@"(?<left>.+)\s*(?<operator>[\*\/\+\-<=>\&\|]{2}|\+|\-|\/|\*|<|>)\s*(?<right>.+)"); Match mStatement = rStatement.Match(code); if (mStatement.Success) // && mStatement.Groups.Count == 4 { Expression oper; string operStr = mStatement.Groups["operator"].Value; if (Operators.Contains(operStr, StringComparer.InvariantCulture)) { oper = new Expression(operStr, State.Operator); } else { throw new CompileException($"Unknown identifier encountered {operStr}"); } if (!parseLine(mStatement.Groups["left"].Value, State.Statement)) { throw new CompileException($"Expected statement before '{oper.Code}'"); } Expression left = Program.Pop(); if (!parseLine(mStatement.Groups["right"].Value, State.Statement)) { throw new CompileException($"Expected statement after '{oper.Code}'"); } Expression right = Program.Pop(); Expression statement; // проверяю можно ли применить простой оператор над целыми числами if (left.Type == State.Constant && right.Type == State.Constant && FuncOperators.Keys.Contains(oper.Code)) { SystemTypes?Type1 = Recognise(left.Code); SystemTypes?Type2 = Recognise(right.Code); if (Type1 == SystemTypes.Int && Type2 == SystemTypes.Int) { int result = FuncOperators[oper.Code](int.Parse(left.Code), int.Parse(right.Code)); statement = new Expression(result.ToString(), State.Constant); Program.Push(statement); return(true); } } if (parantacies) { statement = new Expression($"({left.Code} {oper.Code} {right.Code})", State.Statement); } else { statement = new Expression($"{left.Code} {oper.Code} {right.Code}", State.Statement); } statement.Children.Add(left); statement.Children.Add(oper); statement.Children.Add(right); Program.Push(statement); return(true); } if (parseLine(code, State.Constant)) { return(true); } if (parseLine(code, State.Variable)) { return(true); } return(false); #endregion } case State.Expression: { #region Expression Regex rexp = new Regex(@"\s*([\w\d\s=,\(\)\*/\-\+]+);\s*"); MatchCollection mexp = rexp.Matches(code); if (mexp.Count > 0) { foreach (Match match in mexp) { string exp = match.Groups[1].Value; if (parseLine(exp, State.Declaration)) { continue; } if (parseLine(exp, State.Initialization)) { continue; } throw new CompileException("Wrong expression occured before ';'"); } return(true); } if (parseLine(code, State.IF)) { return(true); } throw new CompileException("';' is required"); #endregion } case State.Program: { #region Program List <string> errors = new List <string>(); Expression IfBlock = new Expression("awds", State.Error); bool ifblock = false; int lineCount = 1; foreach (var line in code.Split("\r\n\t".ToArray(), StringSplitOptions.RemoveEmptyEntries)) { try { parseLine(line, State.Expression); Expression exp = Program.Peek(); Expression undef = findUndeclared(Variables, exp, State.Variable); if (undef != null) { errors.Add($"Line {lineCount}: Encountered undeclared variable {undef.Code}"); continue; } if (exp.Type == State.IF) { IfBlock = Program.Pop(); ifblock = true; } if (ifblock && (State.Initialization | State.Declaration).HasFlag(exp.Type)) { ifblock = false; IfBlock.Children.Add(Program.Pop()); Program.Push(IfBlock); } } catch (CompileException except) { errors.Add($"Line {lineCount}: {except.Message}"); } lineCount++; } if (ifblock) { errors.Add($"Line {lineCount-1}: Expected end of if block"); } CProgram Prog = new CProgram(Program.Reverse(), errors); Program.Clear(); Program.Push(Prog); return(true); #endregion } default: return(false); } #endregion }