The part of the problem that really manifests itself in my grammar is the shown 
following two output lines:

 

4: b is false size = 2 bt = 2
4: b is true size = 1 bt = 1

 

This means my sempred is looking different frames at different points. I could 
check for {IsStackEmpty()}? but it means nothing because the information I 
really need is {IsStackValid()}?. The 2nd stack frame should *always* be pushed 
before entering the code in nest3subrule1, but in certain cases it is not. I 
found a convoluted method of detecting valid frames by altering scopes for 
token index comparisons within specially crafted matching sempreds and actions. 
However, this method results in the memoize option being useless. I’d post more 
of the grammar, but this subsection is over 1000 lines of the 10000 line .g3 
file and another 400 in helper functions inside a .cs partial class file.

 

Example of sempreds altering items in the scopes, and I need similar code for 
each of the basic types (long, double, float, short, signed, unsigned, char, 
wchar_t, void, user types):

 

        |       ('int') => {( !HaveValidDeclSpecifierSeqScope() || CanMatchInt( 
ref $decl_specifier_seq::_savedIndex ) )}?

                'int'

                {

                        // executes during backtracking

                        (state.backtracking==0 || 
!HaveValidDeclSpecifierSeqScope() ||

                                (       ($decl_specifier_seq::_not_object = 
$decl_specifier_seq::_savedIndex) >= 0

                                &&      ($decl_specifier_seq::_is_int = 
$decl_specifier_seq::_savedIndex) >= 0

                        )

                        )

                }?

                {

                        if ( HaveValidDeclSpecifierSeqScope() )

                        {

                                $decl_specifier_seq::_is_int = 
$decl_specifier_seq::_savedIndex;

                                $decl_specifier_seq::_not_object = 
$decl_specifier_seq::_savedIndex;

                        }

                }

 

With the following validity checks:

 

bool CanMatchInt( ref int savedIndex )

{

    if ( decl_specifier_seq_stack.Count > 0 )

    {

        decl_specifier_seq_scope scope = 
(decl_specifier_seq_scope)decl_specifier_seq_stack.Peek();

        int index = input.Index();

 

        if ( scope._last_specifier >= 0 && index >= scope._last_specifier )

            return true;

 

        // check if we've been here already

        if ( scope._is_int == index )

        {

            savedIndex = index;

            return true;

        }

 

        if ( scope._is_object == -1

            && scope._has_sign == -1

            && scope._is_double == -1

            && scope._is_int == -1

            )

        {

            savedIndex = input.Index();

            return true;

        }

 

        return false;

    }

 

    return true;

}

 

bool HaveValidDeclSpecifierSeqScope()

{

    // TODO: this is not 100% correct but catches the cases I need right now

    //       TArray<ObjectType*> 

    if ( template_argument_stack.Count > 0 )

        return false;

 

    if ( decl_specifier_seq_stack.Count > 0 )

    {

        int top_id = -1;

        if ( member_declaration_stack.Count > 0 )

            top_id = ( 
(member_declaration_scope)member_declaration_stack.Peek() )._id;

        if ( declaration_stack.Count > 0 )

            top_id = Math.Max( top_id, ( 
(declaration_scope)declaration_stack.Peek() )._id );

        if ( declaration_statement_stack.Count > 0 )

            top_id = Math.Max( top_id, ( 
(declaration_statement_scope)declaration_statement_stack.Peek() )._id );

 

        return ( (decl_specifier_seq_scope)decl_specifier_seq_stack.Peek() 
)._declaration_scope == top_id;

    }

 

    return false;

}

 

 

From: Jim Idle [mailto:[EMAIL PROTECTED] 
Sent: Thursday, October 23, 2008 3:37 PM
To: Sam Harwell
Cc: ANTLR-dev Dev
Subject: Re: [antlr-dev] Bug when using sempreds, synpreds, and scopes

 

On Thu, 2008-10-23 at 15:24 -0500, Sam Harwell wrote: 

When this grammar is given the following input, a few bugs are observed, as 
shown in the output.


I think that your grammar just has a path encoded that allows it to try 
accessing the scope when there is nothing in it. Move the scope up to a level 
where this cannot happen, or test for the stack being empty and assume that 
this means false or true or whatever it means to your logic ;-)

Jim





 

Input: “ident ident” (no quotes)

 

Output:

Setting scope at level 1 to true

4: b is false size = 2 bt = 2

3: b is false size = 2 bt = 2

2: b is false size = 2 bt = 2

4: b is true size = 1 bt = 1

4: b is false size = 2 bt = 1

3: b is false size = 2 bt = 1

2: b is false size = 2 bt = 1

1: b is true size = 1 bt = 1

Exception in thread "main" java.util.EmptyStackException

                at java.util.Stack.peek(Unknown Source)

                at TestSemPredScopesParser.test(TestSemPredScopesParser.java:98)

                at __Test__.main(__Test__.java:14)

 

Grammar:

 

grammar TestSemPredScopes;

 

scope MyScope { boolean b; }

 

@parser::members {

        boolean report( int n, boolean b ) {

                System.err.println( n + ": b is " + b + " size = " + 
MyScope_stack.size() + " bt = " + state.backtracking);

                return true;

        }

}

 

test

        :       (       (subrule1) => subrule1

                |       subrule2

                )

                EOF

        ;

 

subrule1

scope MyScope;

        :       nest1subrule1

        ;

 

nest1subrule1

@init

{

        System.err.println( "Setting scope at level " + MyScope_stack.size() + 
" to true" );

        $MyScope::b = true;

}

        :       (nest2subrule1) => nest2subrule1 {report(1,$MyScope::b)}?

        |       subrule2

        ;

 

nest2subrule1

scope MyScope;

        : nest3subrule1 {report(2,$MyScope::b)}? ;

 

nest3subrule1

        :       {report(4,$MyScope::b) /*&& !$MyScope::b*/}? => 
{report(3,$MyScope::b)}? IDENTIFIER IDENTIFIER

        ;

 

subrule2 : IDENTIFIER ;

 

IDENTIFIER : ('a'..'z')+ ;

WS : (' ' | '\t')+ {$channel = HIDDEN;} ;

 



         
        _______________________________________________
        antlr-dev mailing list
        [email protected]
        http://www.antlr.org:8080/mailman/listinfo/antlr-dev

_______________________________________________
antlr-dev mailing list
[email protected]
http://www.antlr.org:8080/mailman/listinfo/antlr-dev

Reply via email to