/*
 * Copyright © 2015 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jsx.parser;

import com.io7m.jeucreader.UnicodeCharacterReader;
import com.io7m.jeucreader.UnicodeCharacterReaderPushBackType;
import com.io7m.jsx.SExpressionType;
import com.io7m.jsx.lexer.JSXLexer;
import com.io7m.jsx.lexer.JSXLexerConfiguration;
import com.io7m.jsx.lexer.JSXLexerConfigurationBuilderType;
import com.io7m.jsx.lexer.JSXLexerType;
import com.io7m.jsx.serializer.JSXSerializerTrivial;
import com.io7m.jsx.serializer.JSXSerializerType;
import com.io7m.junreachable.UnreachableCodeException;

import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Simple parser demo that parses and then serializes.
 */

public final class JSXParserDemoMain
{
  private JSXParserDemoMain()
  {
    throw new UnreachableCodeException();
  }

  /**
   * Main program.
   *
   * @param args Command line arguments
   *
   * @throws IOException On I/O errors
   */

  public static void main(
    final String[] args)
    throws IOException
  {
    try {
      final JSXLexerConfigurationBuilderType lcb =
        JSXLexerConfiguration.newBuilder();
      lcb.setNewlinesInQuotedStrings(false);
      final JSXLexerConfiguration lc = lcb.build();

      final UnicodeCharacterReaderPushBackType r =
        UnicodeCharacterReader.newReader(new InputStreamReader(System.in));
      final JSXLexerType lex = JSXLexer.newLexer(lc, r);

      final JSXParserConfigurationBuilderType pcb =
        JSXParserConfiguration.newBuilder();
      pcb.preserveLexicalInformation(true);
      final JSXParserConfiguration pc = pcb.build();
      final JSXParserType p = JSXParser.newParser(pc, lex);

      final JSXSerializerType s = JSXSerializerTrivial.newSerializer();

      while (true) {
        final SExpressionType e = p.parseExpression();
        s.serialize(e, System.out);
      }
    } catch (final JSXParserException e) {
      System.err.println(
        "error: parse error: "
        + e.getLexicalInformation()
        + ": "
        + e.getMessage());
    }
  }
}

@@ -1371,16 +1371,43 @@
 mReader;
+%0Aimport java.util.Optional;
 %0A%0A/**%0A *
@@ -1788,20 +1788,8 @@
   %7B%0A
-    try %7B%0A  
     
@@ -1829,26 +1829,24 @@
 rType lcb =%0A
-  
       JSXLex
@@ -1879,18 +1879,16 @@
 ();%0A    
-  
 lcb.setN
@@ -1914,26 +1914,24 @@
 ngs(false);%0A
-  
     final JS
@@ -1969,26 +1969,24 @@
 ild();%0A%0A    
-  
 final Unicod
@@ -2024,18 +2024,16 @@
 =%0A      
- 
- 
 UnicodeC
@@ -2092,26 +2092,24 @@
 m.in));%0A    
-  
 final JSXLex
@@ -2144,34 +2144,32 @@
 er(lc, r);%0A%0A    
- 
- 
 final JSXParserC
@@ -2194,26 +2194,24 @@
 rType pcb =%0A
-  
       JSXPar
@@ -2245,18 +2245,16 @@
 ();%0A    
-  
 pcb.pres
@@ -2283,18 +2283,16 @@
 (true);%0A
-  
     fina
@@ -2334,26 +2334,24 @@
 uild();%0A    
-  
 final JSXPar
@@ -2393,26 +2393,24 @@
  lex);%0A%0A    
- 
- 
 final JSXSer
@@ -2468,18 +2468,16 @@
 );%0A%0A    
-  
 while (t
@@ -2489,24 +2489,45 @@
 %7B%0A      
-  final 
+try %7B%0A        final Optional%3C
 SExpress
@@ -2533,18 +2533,23 @@
 sionType
+%3E
  e
+_opt
  = p.par
@@ -2560,16 +2560,21 @@
 pression
+OrEOF
 ();%0A    
@@ -2581,44 +2581,166 @@
     
-s.serialize(e, System.out);%0A      %7D%0A
+if (e_opt.isPresent()) %7B%0A          final SExpressionType e = e_opt.get();%0A          s.serialize(e, System.out);%0A        %7D else %7B%0A          break;%0A        %7D%0A  
     
@@ -2773,17 +2773,17 @@
 ception 
-e
+x
 ) %7B%0A    
@@ -2784,16 +2784,18 @@
 %7B%0A      
+ 
+ 
 System.e
@@ -2806,16 +2806,18 @@
 rintln(%0A
+  
         
@@ -2835,24 +2835,28 @@
 se error: %22%0A
+    
         + e.
@@ -2849,25 +2849,25 @@
           + 
-e
+x
 .getLexicalI
@@ -2887,16 +2887,20 @@
         
+    
 + %22: %22%0A 
@@ -2910,11 +2910,15 @@
     
+ 
+   
 + 
-e
+x
 .get
@@ -2925,24 +2925,32 @@
 Message());%0A
+      %7D%0A
     %7D%0A  %7D%0A%7D%0A

Make the demo parser recoverable