/*
 * © Copyright 2015 -  SourceClear Inc
 */

package com.sourceclear.gramtest;

import java.util.LinkedList;
import java.util.List;

/**
 *
 */
public class GeneratorVisitor extends bnfBaseVisitor {

  ///////////////////////////// Class Attributes \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

  ////////////////////////////// Class Methods \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

  //////////////////////////////// Attributes \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
          
  /////////////////////////////// Constructors \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

  ////////////////////////////////// Methods \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

  //------------------------ Implements:

  //------------------------ Overrides:

  @Override
  public String visitId(bnfParser.IdContext ctx) {
    return ctx.getText();
  }

  @Override
  public List<String> visitText(bnfParser.TextContext ctx) {
    List<String> str = new LinkedList<>();
    str.add(ctx.STRINGLITERAL().getText());
    str.add(ctx.TEXT().getText());
    return str;
  }

  @Override
  public String visitCaptext(bnfParser.CaptextContext ctx) {
    return ctx.getText();
  }

  @Override
  public Object visitOneormore(bnfParser.OneormoreContext ctx) {
    return super.visitOneormore(ctx); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public Object visitZeroormore(bnfParser.ZeroormoreContext ctx) {
    return super.visitZeroormore(ctx); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public Object visitOptional(bnfParser.OptionalContext ctx) {
    return super.visitOptional(ctx); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public List<String> visitElement(bnfParser.ElementContext ctx) {
    List<String> result = new LinkedList<>();
    if(!ctx.optional().isEmpty()) {
      result = visitAlternatives(ctx.optional().alternatives());
    }
    else if(!ctx.zeroormore().isEmpty()) {
      result = visitAlternatives(ctx.zeroormore().alternatives()); // one time
      result.add(""); // zero time
    }
    else if(!ctx.oneormore().isEmpty()) {
      result = visitAlternatives(ctx.oneormore().alternatives()); // one time
      List<String> twoLs = combineTwoLists(result,result); //two times
      result.addAll(twoLs);
    }
    else if(!ctx.optional().isEmpty()) {
      //currently similar to zero of mroe times
      result = visitAlternatives(ctx.zeroormore().alternatives()); // one time
      result.add(""); // zero time
    }
    else if(!ctx.captext().isEmpty()) {
      result.add(visitCaptext(ctx.captext()));
    }
    else if(!ctx.text().isEmpty()) {
      result = visitText(ctx.text());
    }
    else {
      result.add(visitId(ctx.id()));
    }
    return result;
  }

  @Override
  public List<String> visitAlternative(bnfParser.AlternativeContext ctx) {
    List<List<String>> comStr = new LinkedList<>();
    for(bnfParser.ElementContext ec1 : ctx.element()) {
     comStr.add(visitElement(ec1));
    }
    return generateAllStrings(comStr, new LinkedList<String>());
  }

  @Override
  public List<String> visitAlternatives(bnfParser.AlternativesContext ctx) {
    List<String> altStrs = new LinkedList<>();
    for(bnfParser.AlternativeContext ac : ctx.alternative()) {
      altStrs.addAll(visitAlternative(ac));
    }
    return altStrs;
  }

  @Override
  public List<String> visitRhs(bnfParser.RhsContext ctx) {
    return visitAlternatives(ctx.alternatives()); 
  }

  @Override
  public Object visitLhs(bnfParser.LhsContext ctx) {
    return super.visitLhs(ctx); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public List<String> visitRule_(bnfParser.Rule_Context ctx) {
    return visitRhs(ctx.rhs());
  }

  @Override
  public List<String> visitRulelist(bnfParser.RulelistContext ctx) {
    List<String> sentences = new LinkedList();
    for(bnfParser.Rule_Context rc : ctx.rule_()) {
      sentences.addAll(visitRule_(rc));
    }
    return sentences;
  }
  
  //---------------------------- Abstract Methods -----------------------------

  //---------------------------- Utility Methods ------------------------------
  
  private List<String> generateAllStrings(List<List<String>> strList, List<String> result) {
    if(strList.size()>0) {
      List<String> newResult = combineTwoLists(result,strList.get(0));
      return generateAllStrings(strList, newResult);
    }
    return result;
  }
  
  private List<String> combineTwoLists(List<String> preList, List<String> postList) {
    List<String> combList = new LinkedList<>();
    for(String s1 : preList) {
      for(String s2 : postList) {
        combList.add(s1+s2);
      }
    }
    return combList;
  }

  //---------------------------- Property Methods -----------------------------
  
}

@@ -710,30 +710,30 @@
 de%0A  public 
-String
+Object
  visitId(bnf
@@ -763,36 +763,41 @@
 %0A    return 
-ctx.getText(
+super.visitId(ctx
 );%0A  %7D%0A%0A  @O
@@ -1795,25 +1795,24 @@
 %3E();%0A    if(
-!
 ctx.optional
@@ -1809,34 +1809,32 @@
 x.optional()
-.isEmpty()
+ != null
 ) %7B%0A      re
@@ -1904,25 +1904,24 @@
     else if(
-!
 ctx.zeroormo
@@ -1920,34 +1920,32 @@
 zeroormore()
-.isEmpty()
+ != null
 ) %7B%0A      re
@@ -2064,25 +2064,24 @@
     else if(
-!
 ctx.oneormor
@@ -2083,26 +2083,24 @@
 ormore()
-.isEmpty()
+ != null
 ) %7B%0A    
@@ -2286,25 +2286,24 @@
     else if(
-!
 ctx.optional
@@ -2304,26 +2304,24 @@
 tional()
-.isEmpty()
+ != null
 ) %7B%0A    
@@ -2492,25 +2492,24 @@
     else if(
-!
 ctx.captext(
@@ -2505,34 +2505,32 @@
 tx.captext()
-.isEmpty()
+ != null
 ) %7B%0A      re
@@ -2586,17 +2586,16 @@
 else if(
-!
 ctx.text
@@ -2600,18 +2600,16 @@
 xt()
-.isEmpty()
+ != null
 ) %7B%0A
@@ -2660,32 +2660,35 @@
     else %7B%0A     
+ //
  result.add(visi
@@ -2698,24 +2698,45 @@
 (ctx.id()));
+ // do nothing for id
 %0A    %7D%0A    r
@@ -4273,17 +4273,19 @@
 t.size()
-%3E
+ %3E 
 0) %7B%0A   
@@ -4343,19 +4343,22 @@
 strList.
-get
+remove
 (0));%0A  

Fix bug on removing