static void DoTheJob(IEnumerable <string> codeLines) { Dictionary <string, Token> constants = new Dictionary <string, Token>(); Dictionary <string, Token> variables = new Dictionary <string, Token>(); Dictionary <string, Token> operators = new Dictionary <string, Token>(); Dictionary <string, Token> keywords = new Dictionary <string, Token>(); List <LexicalError> errors = new List <LexicalError>(); // running lexical analysis TreeList <SyntaxAnalizer.ExpressionNode> tree = new TreeList <SyntaxAnalizer.ExpressionNode>(null); TreeList <SyntaxAnalizer.ExpressionNode> currentBlock = tree; int lineNumber = 0; SyntaxAnalizer sa = new SyntaxAnalizer(); LexicalAnalizer la = new LexicalAnalizer(); int previousLineIndentation = 0; foreach (string line in codeLines) { Construction construction = la.AnaliseLine(line, lineNumber); if (construction.Tokens.Count == 0) { lineNumber++; continue; } for (int i = 0; i < construction.Tokens.Count; i++) { Token token = construction.Tokens[i]; if (token.IsReservedIdToken) { keywords.TryAdd(token.Value, token); } else if (token.IsOperation) { operators.TryAdd(token.Value, token); } else if (token.IsConstant) { constants.TryAdd(token.Value, token); } else if (token.TokenType != TokenTypes.UNKNOWN) { variables.TryAdd(token.Value, token); } } if (construction.HasErrors) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\t\t ERRORS"); Console.ResetColor(); foreach (LexicalError error in construction.Errors) { Console.WriteLine($"line {error.CodeLineNumber + 1} char {error.IndexInCodeLine + 1} :: {error.ErrorType}"); Console.WriteLine(error.Description); } Console.Read(); Environment.Exit(1); } SyntaxAnalizer.ExpressionNode node = null; bool isElifElseNode = false; bool newBlockToOpen = false; node = sa.Analyse(construction.Tokens, out newBlockToOpen, out isElifElseNode); int indentationDiff = previousLineIndentation - construction.Indentation; if (indentationDiff > 0) { for (int i = previousLineIndentation - 1; i >= construction.Indentation; i--) { currentBlock = currentBlock.Parent; if (currentBlock.Indentation == i) { break; } } // currentBlock = currentBlock.Parent; // TODO: create parent relationship between BLOCKS to support >1 level nesting if (node.Operator.IsElif && !currentBlock.Last().Operator.IsIf) { throw new SyntaxAnalizer.SyntaxErrorException( "elif block not allowed here", node.Operator.Value, node.Operator.CodeLineIndex, node.Operator.CodeLineNumber ); } else if (node.Operator.IsElse && !(currentBlock.Last().Operator.IsIf || currentBlock.Last().Operator.IsElif)) { throw new SyntaxAnalizer.SyntaxErrorException( "else block not allowed here", line, node.Operator.CodeLineIndex, node.Operator.CodeLineNumber ); } } previousLineIndentation = construction.Indentation; lineNumber++; if (newBlockToOpen) { if ((node.Operator.IsElif || node.Operator.IsElse) && !currentBlock.Last().Operator.IsIf&& !currentBlock.Last().Operator.IsElif) { throw new SyntaxAnalizer.SyntaxErrorException( "lacks IF clause for elif|else block to appear", node.Operator.Value, node.Operator.CodeLineIndex, node.Operator.CodeLineNumber ); } currentBlock.Add(node); currentBlock.Last().Block = new TreeList <SyntaxAnalizer.ExpressionNode>(currentBlock); currentBlock = currentBlock.Last().Block; currentBlock.Indentation = construction.Indentation; continue; } currentBlock.Add(node); } if (errors.Any()) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\t\t ERRORS"); Console.ResetColor(); foreach (LexicalError error in errors) { Console.WriteLine($"line {error.CodeLineNumber + 1} char {error.IndexInCodeLine + 1} :: {error.ErrorType}"); Console.WriteLine(error.Description); } } Console.WriteLine("SYNTAX TREE:\n"); PrintSyntaxTree(tree); // console tables output block Console.WriteLine("\n \t\t CONSTANTS"); PrintTokensDictionary(constants); Console.WriteLine("\n \t\t VARIABLES"); PrintTokensDictionary(variables); Console.WriteLine("\n \t\t KEYWORS"); PrintTokensDictionary(keywords); Console.WriteLine("\n \t\t OPERATORS"); PrintTokensDictionary(operators); }
public TreeList(TreeList <T> parent) { Parent = parent; }