public static bool AllPathsReturns(SyntaxTreeNode rootNode) { bool hasReturnOnRoot = rootNode.Children.Any(node => node.Value == Symbols.SRetorno); if (hasReturnOnRoot) { return true; } return InternalAllPathsReturns(rootNode); }
private static bool InternalAllPathsReturns(SyntaxTreeNode node) { var foundReturn = true; foreach (var child in node.Children) { var rootReturn = child.Children.Any(childNode => childNode.Value == Symbols.SRetorno); if (rootReturn) { return foundReturn & rootReturn; } foundReturn &= InternalAllPathsReturns(child); } return node.Children.Count > 0 && foundReturn; }
private void AnalyzeFuncDcl() { _isAnalyzingFunction = true; NextToken(); if (_token.Symbol != Symbols.SIdentificador) { RaiseUnexpectedTokenError("identificador"); } var item = _symbolTable.Search(_token.Lexeme); if (item != null) { RaiseDoubleError(Symbols.SFuncao); } var funcItem = new FunctionItem { Lexeme = _token.Lexeme, Level = _level, Label = _codeGenerator.GetStringLabelFor(_lastLabel) }; _funcInfo = new FunctionInfo { Name = _token.Lexeme }; _rootNode = new SyntaxTreeNode { Value = _token.Symbol }; _currentNode = _rootNode; _codeGenerator.GenerateLabel(_lastLabel); _level++; NextToken(); if (_token.Symbol != Symbols.SDoisPontos) { RaiseUnexpectedTokenError("\":\""); } NextToken(); if (_token.Symbol != Symbols.SInteiro && _token.Symbol != Symbols.SBooleano) { RaiseUnexpectedTokenError("\"inteiro\" ou \"booleano\""); } var type = _token.Symbol == Symbols.SInteiro ? ItemType.Integer : ItemType.Boolean; funcItem.Type = type; _symbolTable.Insert(funcItem); NextToken(); if (_token.Symbol != Symbols.SPontoVirgula) { RaiseMissingSemicolonError(); } AnalyzeBlock(true); if (!FunctionHelper.AllPathsReturns(_rootNode)) { RaiseMissingFunctionReturn(); } _symbolTable.CleanUpToLevel(_level); _level--; _rootNode = _currentNode = null; _funcInfo = null; }
private void AnalyzeSimpleCommand(bool isFunction = false) { if (_token.Symbol == Symbols.SIdentificador) { var item = _symbolTable.Search(_token.Lexeme); if (item == null) { RaiseNotFoundIdentificatorError(_token.Lexeme); } _analyzingLexeme = _token.Lexeme; var funcItem = item as FunctionItem; if (_funcInfo != null && funcItem?.Lexeme == _funcInfo.Name) { NextToken(); if (_token.Symbol == Symbols.SAtribuicao) { AnalyzeAttribution(); } else { throw new CompilationException(string.Format(WrongFunctionCall, _lexical.Position.Line, _lexical.Position.Column)); } if (isFunction) { _currentNode = _rootNode; } if (_currentNode != null) { _currentNode.Children.Add(new SyntaxTreeNode { Parent = _currentNode, Value = Symbols.SRetorno }); } _codeGenerator.GenerateInstruction(RETURNF, _funcInfo.FirstVarAddress, _funcInfo.VarsCount); } else { NextToken(); if (_token.Symbol == Symbols.SAtribuicao) { AnalyzeAttribution(); } else { AnalyzeProcCall(); } } } else if (_token.Symbol == Symbols.SSe) { AnalyzeIf(); } else if (_token.Symbol == Symbols.SEnquanto) { AnalyzeWhile(); } else if (_token.Symbol == Symbols.SLeia) { AnalyzeRead(); } else if (_token.Symbol == Symbols.SEscreva) { AnalyzeWrite(); } else { AnalyzeCommands(); } }
private SyntaxTreeNode GetNode(SyntaxTreeNode parent) { return new SyntaxTreeNode { Parent = parent, Value = _token.Symbol }; }
private void AnalyzeIf() { uint firstLabel; uint secondLabel; SyntaxTreeNode node = null; SyntaxTreeNode parent = null; if (_funcInfo != null && _isAnalyzingFunction) { parent = _currentNode ?? _rootNode ?? new SyntaxTreeNode(); node = GetNode(parent); parent.Children.Add(node); _currentNode = node; } firstLabel = secondLabel = _lastLabel; _lastLabel++; NextToken(); var expressionType = AnalyzeExpressionType(); if (expressionType != ItemType.Boolean) { RaiseIncompatibleTypeError(); } _codeGenerator.GenerateInstruction(JMPF, _codeGenerator.GetStringLabelFor(firstLabel)); if (_token.Symbol != Symbols.SEntao) { RaiseUnexpectedTokenError("\"entao\""); } NextToken(); AnalyzeSimpleCommand(); if (_token.Symbol == Symbols.SSenao) { secondLabel = _lastLabel; _lastLabel++; _codeGenerator.GenerateInstruction(JMP, _codeGenerator.GetStringLabelFor(secondLabel)); _codeGenerator.GenerateLabel(firstLabel); if (_funcInfo != null) { node = GetNode(parent); parent.Children.Add(node); _currentNode = node; } NextToken(); AnalyzeSimpleCommand(); } _codeGenerator.GenerateLabel(secondLabel); }
private void AnalyzeCommands(bool isFunction = false) { if (_token.Symbol == Symbols.SInicio) { NextToken(); AnalyzeSimpleCommand(isFunction); while (_token.Symbol != Symbols.SFim) { if (_token.Symbol == Symbols.SPontoVirgula) { if (_funcInfo != null) { _currentNode = _currentNode?.Parent ?? _rootNode; } NextToken(); if (_token.Symbol != Symbols.SFim) { AnalyzeSimpleCommand(isFunction); } } else { RaiseMissingSemicolonError(); } } NextToken(); } else { RaiseInvalidToken(); } }
private void AnalyzeBlock(bool isFunction = false) { uint totalVars; NextToken(); totalVars = AnalyzeVarsDcl(); if (totalVars > 0) { if (isFunction) { _funcInfo.VarsCount = totalVars; _funcInfo.FirstVarAddress = totalVars == 0 ? 0 : _allocBase; } _codeGenerator.GenerateInstruction(ALLOC, _allocBase, totalVars); _allocBase += totalVars; } _lastLabel++; if (isFunction) { //Saves the current values //We'll need this values saved in case a function has other functions inside it var rootNode = _rootNode; var funcInfo = _funcInfo; var currentNode = _currentNode; AnalyzeSubRoutines(); _rootNode = rootNode; _funcInfo = funcInfo; _currentNode = currentNode; } else { AnalyzeSubRoutines(); } AnalyzeCommands(true); if (totalVars > 0) { _allocBase -= totalVars; if (!isFunction) { _codeGenerator.GenerateInstruction(DALLOC, _allocBase, totalVars); } _memory -= totalVars; } }