@@ -71,7 +71,8 @@ enum NullValue {
7171}
7272
7373abstract class StackListener extends Listener {
74- final Stack stack = new Stack ();
74+ static const bool debugStack = false ;
75+ final Stack stack = debugStack ? new DebugStack () : new StackImpl ();
7576
7677 /// Used to report an internal error encountered in the stack listener.
7778 dynamic internalProblem (Message message, int charOffset, Uri uri);
@@ -112,10 +113,9 @@ abstract class StackListener extends Listener {
112113 bool checkState (Token token, List <ValueKind > kinds) {
113114 bool success = true ;
114115 for (int kindIndex = 0 ; kindIndex < kinds.length; kindIndex++ ) {
115- int stackIndex = stack.arrayLength - kindIndex - 1 ;
116116 ValueKind kind = kinds[kindIndex];
117- if (stackIndex >= 0 ) {
118- Object value = stack.array[stackIndex ];
117+ if (kindIndex < stack.length ) {
118+ Object value = stack[kindIndex ];
119119 if (! kind.check (value)) {
120120 success = false ;
121121 }
@@ -154,8 +154,7 @@ abstract class StackListener extends Listener {
154154 // Compute kind/stack frame information for all expected values plus 3 more
155155 // stack elements if available.
156156 for (int kindIndex = 0 ; kindIndex < kinds.length + 3 ; kindIndex++ ) {
157- int stackIndex = stack.arrayLength - kindIndex - 1 ;
158- if (stackIndex < 0 && kindIndex >= kinds.length) {
157+ if (kindIndex >= stack.length && kindIndex >= kinds.length) {
159158 // No more stack elements nor kinds to display.
160159 break ;
161160 }
@@ -168,8 +167,8 @@ abstract class StackListener extends Listener {
168167 } else {
169168 sb.write (padRight ('---' , 60 ));
170169 }
171- if (stackIndex >= 0 ) {
172- Object value = stack.array[stackIndex ];
170+ if (kindIndex < stack.length ) {
171+ Object value = stack[kindIndex ];
173172 if (kind == null || kind.check (value)) {
174173 sb.write (' ' );
175174 } else {
@@ -496,7 +495,29 @@ abstract class StackListener extends Listener {
496495 {bool wasHandled: false , List <LocatedMessage > context});
497496}
498497
499- class Stack {
498+ abstract class Stack {
499+ /// Pops [count] elements from the stack and puts it into [list] .
500+ /// Returns [null] if a [ParserRecovery] value is found, or [list] otherwise.
501+ List <Object > popList (int count, List <Object > list, NullValue nullValue);
502+
503+ void push (Object value);
504+
505+ /// Will return [null] instead of [NullValue] .
506+ Object get last;
507+
508+ bool get isNotEmpty;
509+
510+ List <Object > get values;
511+
512+ Object pop (NullValue nullValue);
513+
514+ int get length;
515+
516+ /// Raw, i.e. [NullValue] s will be returned instead of [null] .
517+ Object operator [](int index);
518+ }
519+
520+ class StackImpl implements Stack {
500521 List <Object > array = new List <Object >(8 );
501522 int arrayLength = 0 ;
502523
@@ -509,6 +530,10 @@ class Stack {
509530 return value is NullValue ? null : value;
510531 }
511532
533+ Object operator [](int index) {
534+ return array[arrayLength - 1 - index];
535+ }
536+
512537 void push (Object value) {
513538 array[arrayLength++ ] = value;
514539 if (array.length == arrayLength) {
@@ -545,9 +570,7 @@ class Stack {
545570 } else if (value is ParserRecovery ) {
546571 isParserRecovery = true ;
547572 } else {
548- if (value is NullValue ) {
549- print (value);
550- }
573+ assert (value is ! NullValue );
551574 list[i] = value;
552575 }
553576 }
@@ -571,6 +594,54 @@ class Stack {
571594 }
572595}
573596
597+ class DebugStack implements Stack {
598+ Stack realStack = new StackImpl ();
599+ Stack stackTraceStack = new StackImpl ();
600+ List <StackTrace > latestStacktraces = new List <StackTrace >();
601+
602+ @override
603+ Object operator [](int index) {
604+ Object result = realStack[index];
605+ latestStacktraces.clear ();
606+ latestStacktraces.add (stackTraceStack[index]);
607+ return result;
608+ }
609+
610+ @override
611+ bool get isNotEmpty => realStack.isNotEmpty;
612+
613+ @override
614+ Object get last => this [0 ];
615+
616+ @override
617+ int get length => realStack.length;
618+
619+ @override
620+ Object pop (NullValue nullValue) {
621+ Object result = realStack.pop (nullValue);
622+ latestStacktraces.clear ();
623+ latestStacktraces.add (stackTraceStack.pop (null ));
624+ return result;
625+ }
626+
627+ @override
628+ List <Object > popList (int count, List <Object > list, NullValue nullValue) {
629+ List <Object > result = realStack.popList (count, list, nullValue);
630+ latestStacktraces.length = count;
631+ stackTraceStack.popList (count, latestStacktraces, null );
632+ return result;
633+ }
634+
635+ @override
636+ void push (Object value) {
637+ realStack.push (value);
638+ stackTraceStack.push (StackTrace .current);
639+ }
640+
641+ @override
642+ List <Object > get values => realStack.values;
643+ }
644+
574645/// Helper constant for popping a list of the top of a [Stack] . This helper
575646/// returns null instead of empty lists, and the lists returned are of fixed
576647/// length.
0 commit comments