package org.spoofax.jsglr2;

import java.util.HashMap;
import java.util.Map;

import org.metaborg.characterclasses.CharacterClassFactory;
import org.metaborg.parsetable.IParseTable;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.jsglr2.JSGLR2Variants.ParserVariant;
import org.spoofax.jsglr2.actions.ActionsFactory;
import org.spoofax.jsglr2.imploder.IImploder;
import org.spoofax.jsglr2.imploder.ImplodeResult;
import org.spoofax.jsglr2.parseforest.IParseForest;
import org.spoofax.jsglr2.parseforest.ParseForestConstruction;
import org.spoofax.jsglr2.parseforest.ParseForestRepresentation;
import org.spoofax.jsglr2.parser.IParser;
import org.spoofax.jsglr2.parser.ParseException;
import org.spoofax.jsglr2.parser.result.ParseFailure;
import org.spoofax.jsglr2.parser.result.ParseResult;
import org.spoofax.jsglr2.parser.result.ParseSuccess;
import org.spoofax.jsglr2.parsetable.ParseTableReadException;
import org.spoofax.jsglr2.parsetable.ParseTableReader;
import org.spoofax.jsglr2.reducing.Reducing;
import org.spoofax.jsglr2.stack.StackRepresentation;
import org.spoofax.jsglr2.stack.collections.ActiveStacksRepresentation;
import org.spoofax.jsglr2.stack.collections.ForActorStacksRepresentation;
import org.spoofax.jsglr2.states.StateFactory;

public class JSGLR2<ParseForest extends IParseForest, AbstractSyntaxTree> {

    private static Map<IParseTable, JSGLR2<?, IStrategoTerm>> incrementalJSGLR2map = new HashMap<>();
    public final IParser<ParseForest, ?> parser;
    public final IImploder<ParseForest, AbstractSyntaxTree> imploder;

    public static JSGLR2<?, IStrategoTerm> standard(IParseTable parseTable) {
        return JSGLR2Variants.getJSGLR2(parseTable,
            new ParserVariant(ActiveStacksRepresentation.ArrayList, ForActorStacksRepresentation.ArrayDeque,
                ParseForestRepresentation.Hybrid, ParseForestConstruction.Full, StackRepresentation.HybridElkhound,
                Reducing.Elkhound));
    }

    public static JSGLR2<?, IStrategoTerm> dataDependent(IParseTable parseTable) {
        return JSGLR2Variants.getJSGLR2(parseTable,
            new ParserVariant(ActiveStacksRepresentation.ArrayList, ForActorStacksRepresentation.ArrayDeque,
                ParseForestRepresentation.DataDependent, ParseForestConstruction.Full, StackRepresentation.Basic,
                Reducing.DataDependent));
    }

    public static JSGLR2<?, IStrategoTerm> layoutSensitive(IParseTable parseTable) {
        return JSGLR2Variants.getJSGLR2(parseTable,
            new ParserVariant(ActiveStacksRepresentation.ArrayList, ForActorStacksRepresentation.ArrayDeque,
                ParseForestRepresentation.LayoutSensitive, ParseForestConstruction.Full, StackRepresentation.Basic,
                Reducing.DataDependent));
    }

    public static JSGLR2<?, IStrategoTerm> incremental(IParseTable parseTable) {
        if(!incrementalJSGLR2map.containsKey(parseTable))
            incrementalJSGLR2map.put(parseTable,
                JSGLR2Variants.getJSGLR2(parseTable,
                    new ParserVariant(ActiveStacksRepresentation.ArrayList, ForActorStacksRepresentation.ArrayDeque,
                        ParseForestRepresentation.Incremental, ParseForestConstruction.Full, StackRepresentation.Basic,
                        Reducing.Basic)));
        System.err.println("Parsermap size:" + incrementalJSGLR2map.size());
        return incrementalJSGLR2map.get(parseTable);
    }

    public static JSGLR2<?, IStrategoTerm> standard(IStrategoTerm parseTableTerm) throws ParseTableReadException {
        IParseTable parseTable =
            new ParseTableReader(new CharacterClassFactory(true, true), new ActionsFactory(true), new StateFactory())
                .read(parseTableTerm);

        return standard(parseTable);
    }

    public JSGLR2(IParser<ParseForest, ?> parser, IImploder<ParseForest, AbstractSyntaxTree> imploder) {
        this.parser = parser;
        this.imploder = imploder;
    }

    public AbstractSyntaxTree parse(String input) {
        return parse(input, "", null);
    }

    public AbstractSyntaxTree parse(String input, String filename, String startSymbol) {
        return parseResult(input, filename, startSymbol).ast;
    }

    public JSGLR2Result<AbstractSyntaxTree> parseResult(String input, String filename, String startSymbol) {
        try {
            return parseUnsafeResult(input, filename, startSymbol);
        } catch(ParseException e) {
            return new JSGLR2Result<>();
        }
    }

    public AbstractSyntaxTree parseUnsafe(String input, String filename, String startSymbol) throws ParseException {
        return parseUnsafeResult(input, filename, startSymbol).ast;
    }

    public JSGLR2Result<AbstractSyntaxTree> parseUnsafeResult(String input, String filename, String startSymbol)
        throws ParseException {

        ParseResult<ParseForest> parseResult = parser.parse(input, filename, startSymbol);

        if(parseResult.isSuccess) {
            ParseSuccess<ParseForest> success = (ParseSuccess<ParseForest>) parseResult;

            ImplodeResult<AbstractSyntaxTree> implodeResult = imploder.implode(input, filename, success.parseResult);

            return new JSGLR2Result<>(implodeResult);
        } else {
            ParseFailure<ParseForest> failure = (ParseFailure<ParseForest>) parseResult;

            throw failure.exception();
        }
    }

}

@@ -26,57 +26,8 @@
 2;%0A%0A
-import java.util.HashMap;%0Aimport java.util.Map;%0A%0A
 impo
@@ -74,32 +74,32 @@
 erClassFactory;%0A
+
 import org.metab
@@ -1302,110 +1302,8 @@
  %7B%0A%0A
-    private static Map%3CIParseTable, JSGLR2%3C?, IStrategoTerm%3E%3E incrementalJSGLR2map = new HashMap%3C%3E();%0A
     
@@ -2728,122 +2728,14 @@
     
-if(!incrementalJSGLR2map.containsKey(parseTable))%0A            incrementalJSGLR2map.put(parseTable,%0A               
+return
  JSG
@@ -2776,32 +2776,24 @@
             
-       
- 
 new ParserVa
@@ -2889,32 +2889,24 @@
             
-        
 ParseForestR
@@ -3001,32 +3001,24 @@
             
-       
- 
 Reducing.Bas
@@ -3025,139 +3025,8 @@
 ic))
-);%0A        System.err.println(%22Parsermap size:%22 + incrementalJSGLR2map.size());%0A        return incrementalJSGLR2map.get(parseTable)
 ;%0A  

Move caching of parser to org.metaborg.spoofax.core.JSGLRParseService