8
8
import org .antlr .v4 .runtime .CommonTokenStream ;
9
9
import org .antlr .v4 .runtime .Lexer ;
10
10
import org .antlr .v4 .runtime .ParserRuleContext ;
11
+ import org .antlr .v4 .runtime .TokenStream ;
11
12
import org .antlr .v4 .runtime .atn .PredictionMode ;
12
13
import org .antlr .v4 .runtime .tree .ErrorNode ;
13
14
import org .antlr .v4 .runtime .tree .ParseTree ;
14
- import org .antlr .v4 .runtime .tree .ParseTreeWalker ;
15
+ import org .antlr .v4 .runtime .tree .ParseTreeListener ;
15
16
import org .antlr .v4 .runtime .tree .TerminalNode ;
16
17
17
18
import convex .core .data .ACell ;
@@ -140,8 +141,7 @@ public void exitForm(FormContext ctx) {
140
141
141
142
@ Override
142
143
public void enterForms (FormsContext ctx ) {
143
- // We add a new ArrayList to the stack to capture values
144
- pushList ();
144
+ // Nothing to do
145
145
}
146
146
147
147
@ Override
@@ -161,7 +161,7 @@ public void exitDataStructure(DataStructureContext ctx) {
161
161
162
162
@ Override
163
163
public void enterList (ListContext ctx ) {
164
- // Nothing to do
164
+ pushList (); // We add a new ArrayList to the stack to capture values
165
165
}
166
166
167
167
@ Override
@@ -172,7 +172,7 @@ public void exitList(ListContext ctx) {
172
172
173
173
@ Override
174
174
public void enterVector (VectorContext ctx ) {
175
- // Nothing to do
175
+ pushList (); // We add a new ArrayList to the stack to capture values
176
176
}
177
177
178
178
@ Override
@@ -183,7 +183,7 @@ public void exitVector(VectorContext ctx) {
183
183
184
184
@ Override
185
185
public void enterSet (SetContext ctx ) {
186
- // Nothing to do
186
+ pushList (); // We add a new ArrayList to the stack to capture values
187
187
}
188
188
189
189
@ Override
@@ -194,7 +194,7 @@ public void exitSet(SetContext ctx) {
194
194
195
195
@ Override
196
196
public void enterMap (MapContext ctx ) {
197
- // Nothing to do
197
+ pushList (); // We add a new ArrayList to the stack to capture values
198
198
}
199
199
200
200
@ Override
@@ -237,7 +237,7 @@ public void enterDoubleValue(DoubleValueContext ctx) {
237
237
238
238
@ Override
239
239
public void exitDoubleValue (DoubleValueContext ctx ) {
240
- String s =ctx .getText ();
240
+ String s =ctx .getStop (). getText ();
241
241
CVMDouble v =CVMDouble .parse (s );
242
242
if (v ==null ) throw new ParseException ("Bad double format: " +s );
243
243
push (v );
@@ -457,7 +457,7 @@ public void enterSpecialLiteral(SpecialLiteralContext ctx) {
457
457
458
458
@ Override
459
459
public void exitSpecialLiteral (SpecialLiteralContext ctx ) {
460
- String s =ctx .getText ();
460
+ String s =ctx .getStop (). getText ();
461
461
ACell special =ReaderUtils .specialLiteral (s );
462
462
if (special ==null ) throw new ParseException ("Invalid special literal: " +s );
463
463
push (special );
@@ -511,8 +511,8 @@ public void exitSingleForm(SingleFormContext ctx) {
511
511
512
512
@ Override
513
513
public void enterAllForms (AllFormsContext ctx ) {
514
- // Nothing
515
-
514
+ // Add a new list to stack to capture all forms. readAll() will pop this
515
+ pushList ();
516
516
}
517
517
518
518
@ Override
@@ -540,9 +540,6 @@ public void enterPrimary(PrimaryContext ctx) {
540
540
public void exitPrimary (PrimaryContext ctx ) {
541
541
// Nothing
542
542
}
543
-
544
-
545
-
546
543
}
547
544
548
545
public static ACell read (String s ) {
@@ -555,47 +552,79 @@ public static ACell read(java.io.Reader r) throws IOException {
555
552
556
553
private static final ConvexErrorListener ERROR_LISTENER =new ConvexErrorListener ();
557
554
558
- static ACell read (CharStream cs ) {
559
- try {
560
- ConvexLexer lexer =new ConvexLexer (cs );
561
- lexer .removeErrorListeners ();
562
- lexer .addErrorListener (ERROR_LISTENER );
563
- CommonTokenStream tokens = new CommonTokenStream (lexer );
564
- ConvexParser parser = new ConvexParser (tokens );
565
-
566
- // We don't need a parse tree, just want to visit everything in our listener
567
- parser .setBuildParseTree (false );
568
- parser .removeErrorListeners ();
569
- parser .getInterpreter ().setPredictionMode (PredictionMode .SLL ); // Seems OK for our grammar?
570
- parser .addErrorListener (ERROR_LISTENER );
571
- CRListener visitor =new CRListener ();
572
- parser .addParseListener (visitor );
573
-
574
- parser .singleForm ();
575
- // ParseTreeWalker.DEFAULT.walk(visitor, tree);
576
-
577
- ArrayList <ACell > top =visitor .popList ();
578
- if (top .size ()!=1 ) {
579
- throw new ParseException ("Bad parse output: " +top );
555
+ // Recommended in https://github.com/antlr/antlr4/blob/dev/doc/listeners.md
556
+ static class CatchingParser extends ConvexParser {
557
+ protected boolean listenerExceptionOccurred = false ;
558
+ public CatchingParser (TokenStream input ) {
559
+ super (input );
560
+ }
561
+
562
+ @ Override
563
+ protected void triggerExitRuleEvent () {
564
+ if ( listenerExceptionOccurred ) return ;
565
+ try {
566
+ // reverse order walk of listeners
567
+ for (int i = _parseListeners .size () - 1 ; i >= 0 ; i --) {
568
+ ParseTreeListener listener = _parseListeners .get (i );
569
+ _ctx .exitRule (listener );
570
+ listener .exitEveryRule (_ctx );
571
+ }
580
572
}
581
-
582
- return top .get (0 );
583
- } catch (Exception e ) {
584
- throw new ParseException ("Unexpected Parse Error" ,e );
573
+ catch (ParseException e ) {
574
+ // If an exception is thrown in the user's listener code, we need to bail out
575
+ // completely out of the parser, without executing anymore user code. We
576
+ // must also stop the parse otherwise other listener actions will attempt to execute
577
+ // almost certainly with invalid results. So, record the fact an exception occurred
578
+ listenerExceptionOccurred = true ;
579
+ throw e ;
580
+ }
581
+ }
582
+
583
+ }
584
+
585
+ static ConvexParser getParser (CharStream cs , CRListener listener ) {
586
+ // Create lexer and paser for the CharStream
587
+ ConvexLexer lexer =new ConvexLexer (cs );
588
+ lexer .removeErrorListeners ();
589
+ lexer .addErrorListener (ERROR_LISTENER );
590
+ CommonTokenStream tokens = new CommonTokenStream (lexer );
591
+ ConvexParser parser = new CatchingParser (tokens );
592
+
593
+ // We don't need a parse tree, just want to visit everything in our listener
594
+ parser .setBuildParseTree (false );
595
+ parser .removeErrorListeners ();
596
+ parser .getInterpreter ().setPredictionMode (PredictionMode .SLL ); // Seems OK for our grammar?
597
+ parser .addErrorListener (ERROR_LISTENER );
598
+
599
+ parser .addParseListener (listener );
600
+ return parser ;
601
+ }
602
+
603
+ static ACell read (CharStream cs ) {
604
+ CRListener listener =new CRListener ();
605
+ ConvexParser parser =getParser (cs ,listener );
606
+
607
+ parser .singleForm ();
608
+
609
+ ArrayList <ACell > top =listener .popList ();
610
+ if (top .size ()!=1 ) {
611
+ throw new ParseException ("Bad parse output: " +top );
585
612
}
613
+
614
+ return top .get (0 );
586
615
}
587
616
588
617
public static AList <ACell > readAll (String source ) {
589
618
return readAll (CharStreams .fromString (source ));
590
619
}
591
620
592
621
static AList <ACell > readAll (CharStream cs ) {
593
- ParseTree tree = getParseTree (cs );
622
+ CRListener listener =new CRListener ();
623
+ ConvexParser parser =getParser (cs ,listener );
594
624
595
- CRListener visitor =new CRListener ();
596
- ParseTreeWalker .DEFAULT .walk (visitor , tree );
625
+ parser .allForms ();
597
626
598
- ArrayList <ACell > top =visitor .popList ();
627
+ ArrayList <ACell > top =listener .popList ();
599
628
return Lists .create (top );
600
629
}
601
630
0 commit comments