public static FEEL_1_1Parser parse(FEELEventListenersManager eventsManager, String source, Map<String, Type> inputVariableTypes, Map<String, Object> inputVariables, Collection<FEELFunction> additionalFunctions, List<FEELProfile> profiles, FEELTypeRegistry typeRegistry) {
        CharStream input = CharStreams.fromString(source);
        FEEL_1_1Lexer lexer = new FEEL_1_1Lexer( input );
        CommonTokenStream tokens = new CommonTokenStream( lexer );
        FEEL_1_1Parser parser = new FEEL_1_1Parser( tokens );

        ParserHelper parserHelper = new ParserHelper(eventsManager);
        additionalFunctions.forEach(f -> parserHelper.getSymbolTable().getBuiltInScope().define(f.getSymbol()));
        parser.setHelper(parserHelper);
        parser.setErrorHandler( new FEELErrorHandler() );
        parser.removeErrorListeners(); // removes the error listener that prints to the console
        parser.addErrorListener( new FEELParserErrorListener( eventsManager ) );

        // pre-loads the parser with symbols
        defineVariables( inputVariableTypes, inputVariables, parser );
        
        if (typeRegistry != null) {
            parserHelper.setTypeRegistry(typeRegistry);
        }

        return parser;
    }
@Test
    void nestedContexts() {
        String inputExpression = "{ a value : 10,"
                       + " an applicant : { "
                       + "    first name : \"Edson\", "
                       + "    last + name : \"Tirelli\", "
                       + "    full name : first name + last + name, "
                       + "    address : {"
                       + "        street : \"55 broadway st\","
                       + "        city : \"New York\" "
                       + "    }, "
                       + "    xxx: last + name"
                       + " } "
                       + "}";
        BaseNode ctxbase = parse( inputExpression );

        assertThat( ctxbase).isInstanceOf(ContextNode.class);
        assertThat( ctxbase.getText()).isEqualTo(inputExpression);

        ContextNode ctx = (ContextNode) ctxbase;
        assertThat( ctx.getEntries()).hasSize(2);

        ContextEntryNode entry = ctx.getEntries().get( 0 );
        assertThat( entry.getName()).isInstanceOf(NameDefNode.class);
        NameDefNode name = (NameDefNode) entry.getName();
        assertThat( name.getText()).isEqualTo("a value");
        assertThat( entry.getValue()).isInstanceOf(NumberNode.class);
        assertThat( entry.getResultType()).isEqualTo(BuiltInType.NUMBER);
        assertThat( entry.getValue().getText()).isEqualTo("10");

        entry = ctx.getEntries().get( 1 );
        assertThat( entry.getName()).isInstanceOf(NameDefNode.class);
        name = (NameDefNode) entry.getName();
        assertThat( name.getText()).isEqualTo( "an applicant");
        assertThat( entry.getValue()).isInstanceOf(ContextNode.class);

        ContextNode applicant = (ContextNode) entry.getValue();
        assertThat( applicant.getEntries()).hasSize(5);
        assertThat( applicant.getEntries().get( 0 ).getName().getText()).isEqualTo("first name");
        assertThat( applicant.getEntries().get( 0 ).getResultType()).isEqualTo(BuiltInType.STRING);
        assertThat( applicant.getEntries().get( 1 ).getName().getText()).isEqualTo("last + name");
        assertThat( applicant.getEntries().get( 1 ).getResultType()).isEqualTo(BuiltInType.STRING);
        assertThat( applicant.getEntries().get( 2 ).getName().getText()).isEqualTo("full name");
        assertThat( applicant.getEntries().get( 2 ).getResultType()).isEqualTo(BuiltInType.STRING);
        assertThat( applicant.getEntries().get( 3 ).getName().getText()).isEqualTo("address");
        assertThat( applicant.getEntries().get( 3 ).getValue()).isInstanceOf(ContextNode.class);

        ContextNode address = (ContextNode) applicant.getEntries().get( 3 ).getValue();
        assertThat( address.getEntries()).hasSize(2);
        assertThat( address.getEntries().get( 0 ).getName().getText()).isEqualTo("street");
        assertThat( address.getEntries().get( 0 ).getResultType()).isEqualTo(BuiltInType.STRING);
        assertThat( address.getEntries().get( 1 ).getName().getText()).isEqualTo("city");
        assertThat( address.getEntries().get( 0 ).getResultType()).isEqualTo(BuiltInType.STRING);
    }