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