private ParserImpl parseFunctionDefinition(final IScope parentScope) throws IOException
    {
        return new ParserImpl() {

            @Override
            public String toString()
            {
                return "parseFunctionDefinition";
            }

            @Override
            protected ASTNode doParse() throws Exception
            {
                // parse return type
                ITextRegion region = new TextRegion(lexer.peek() );
                DataType returnType = parseDataType( parentScope , region );

                if ( lexer.peek(TokenType.ANGLE_BRACKETS_OPEN ) ) {
                    region.merge(lexer.read());
                    region.merge(lexer.read(TokenType.ANGLE_BRACKETS_CLOSE ) );
                    returnType = DataType.getDataType( returnType.getIdentifier() , true , returnType.getPtrCount() );
                }

                // parse function name
                Token tok = lexer.read(TokenType.IDENTIFIER);

                final Identifier functionName = new Identifier( tok );

                if ( parentScope.isFunctionDefined( functionName) ) {
                    throw new ParseException("Function already defined" , tok.getOffset() );
                }                

                FunctionDefinitionNode result = new FunctionDefinitionNode( functionName , returnType , tok.getTextRegion() );
                final IScope functionScope = createNewScope( functionName , result , parentScope );
                result.setScope( functionScope );

                // parse function parameters
                lexer.read(TokenType.PARENS_OPEN);

                if ( ! lexer.peek( TokenType.PARENS_CLOSE ) ) 
                {
                    do 
                    {
                        if ( ! parseFunctionParameter( functionScope ).parse() ) 
                        {
                            throw new ParseException("Expected parameter declaration",lexer.currentOffset());
                        }
                        ParameterDeclaration decl = (ParameterDeclaration) lastResult;
                        functionScope.defineVariable( decl );

                        result.addChild( lastResult );

                        if ( ! lexer.peek( TokenType.COMMA ) ) {
                            break;
                        } 
                        lexer.read(TokenType.COMMA);
                    } while(true);
                }

                lexer.read(TokenType.PARENS_CLOSE);

                // parse body
                if ( ! parseBlock( functionScope , true ).parse() ) {
                    return null;
                } 
                result.addChild( lastResult );
                return result;
            }
        };
    }