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 SemanticTreeList tree = new SemanticTreeList(null); SemanticTreeList currentBlock = tree; int lineNumber = 0; SyntaxAnalyzer sa = new SyntaxAnalyzer(); LexicalAnalyzer la = new LexicalAnalyzer(); 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); } 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 SyntaxAnalyzer.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 SyntaxAnalyzer.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 SyntaxAnalyzer.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 SemanticTreeList(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); } } // semantic analysis 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); SemanticErrorException semanticError = App.DoSemanticCheck(); if (semanticError != null) { throw semanticError; } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("\n---Interpretation complete---"); Console.ResetColor(); }
protected ExpressionNode BuildTree(IEnumerable <Token> tokens, ExpressionNode parent = null) { ExpressionNode root = null; ExpressionNode left = null; Token token = tokens.FirstOrDefault(); if (token is null) { return(null); } if (token.IsConstant || token.TokenType == Token.TokenTypes.ID || token.TokenType == Token.TokenTypes.BUILT_IN_FUNCTION) { left = new ExpressionNode() { Operator = token, Type = ExpressionNode.TokensToExpressionTypes.GetOrDefault(token.TokenType, ExpressionNode.ExpressionTypes.UNKNOWN) }; var tt = tokens.ElementAtOrDefault(1)?.TokenType; if (tt == TokenTypes.OPENING_ROUND_BRACKET || tt == TokenTypes.OPENING_SQUARE_BRACKET) { root = left; left = null; if (tt == TokenTypes.OPENING_SQUARE_BRACKET) { root.Type = ExpressionNode.ExpressionTypes.INDEXER_CALL; } else { root.Type = ExpressionNode.ExpressionTypes.FUNCTION_CALL; } root.Right = BuildTree(tokens.Skip(1)); } // else { root = BuildTree(tokens.Skip(1)); left.Parent = root; } } else if (token.IsOpeningBracket) { this.OpenedBracketsLevel++; root = BuildTree(tokens.Skip(1)); if (root != null) { root.OperatorPriority++; } } else if (token.IsClosingBracket) { this.OpenedBracketsLevel--; root = BuildTree(tokens.Skip(1)); if (root != null) { root.OperatorPriority--; } } else if (token.IsOperation) { root = new ExpressionNode() { Operator = token, Type = ExpressionNode.TokensToExpressionTypes.GetOrDefault(token.TokenType, ExpressionNode.ExpressionTypes.UNKNOWN) }; if (token.TokenType == Token.TokenTypes.MULTIPLICATION || token.TokenType == Token.TokenTypes.DIVISION) { root.OperatorPriority++; } root.Right = BuildTree(tokens.Skip(1), root); } if (root is null) { if (left is null) { return(null); } left.Parent = parent; return(left); } root.Parent = parent; if (left != null) { root.InsertDeepLeft(left); } if (root.Right != null && root.Operator.IsOperation && root.Right.Operator.IsOperation && root.OperatorPriority > root.Right.OperatorPriority) { return(root.LeftRotation()); } return(root); }