/*
 * Copyright 2021 wssccc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ngscript.parser;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.ngscript.parseroid.grammar.Grammar;
import org.ngscript.parseroid.grammar.GrammarLoader;
import org.ngscript.parseroid.table.LALRTable;
import org.ngscript.parseroid.table.TableGenerator;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * @author wssccc
 */
@Slf4j
public class ParserLoader {

    private LALRTable table;

    public static ParserLoader INSTANCE = new ParserLoader();

    private ParserLoader() {
        try {
            init();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public LALRTable getTable() {
        return table;
    }

    private void init() throws Exception {
        String bnfString = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("grammar/ngscript-bnf.txt"), StandardCharsets.UTF_8);
        String hash = DigestUtils.sha1Hex(bnfString);
        String cacheFilePath = System.getProperty("java.io.tmpdir") + File.separator + "ng_bnf_cache_" + hash + ".classdump";
        File cacheFile = new File(cacheFilePath);
        if (cacheFile.exists()) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(cacheFile))) {
                table = (LALRTable) ois.readObject();
                return;
            } catch (Exception ex) {
                log.warn("load parser table cache failed", ex);
            }
        }
        Grammar g = GrammarLoader.loadBnfString(bnfString);
        table = new TableGenerator(g).generate(false);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(cacheFile))) {
            oos.writeObject(table);
        }
    }
}

@@ -997,16 +997,71 @@
 harsets;
+%0Aimport java.nio.file.Path;%0Aimport java.nio.file.Paths;
 %0A%0A/**%0A *
@@ -1484,138 +1484,251 @@
     
-String bnfString = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream(%22grammar/ngscript-bnf.txt%22)
+InputStream resource = getClass().getResourceAsStream(%22grammar/ngscript-bnf.txt%22);%0A        if (resource == null) %7B%0A            throw new RuntimeException(%22Could not load grammar%22);%0A        %7D%0A        String bnfString = IOUtils.toString(resource
 , St
@@ -1787,17 +1787,19 @@
 tils.sha
-1
+256
 Hex(bnfS
@@ -1821,16 +1821,81 @@
  String 
+tableCacheFile = %22ng_bnf_cache_%22 + hash + %22.table%22;%0A        Path 
 cacheFil
@@ -1902,16 +1902,26 @@
 ePath = 
+Paths.get(
 System.g
@@ -1952,65 +1952,25 @@
 ir%22)
- + File.separator + %22ng_bnf_cache_%22 + hash + %22.classdump%22
+, tableCacheFile)
 ;%0A  
@@ -1996,17 +1996,8 @@
 e = 
-new File(
 cach
@@ -2005,16 +2005,24 @@
 FilePath
+.toFile(
 );%0A     
@@ -2289,16 +2289,26 @@
 g.warn(%22
+Failed to 
 load par
@@ -2326,15 +2326,8 @@
 ache
- failed
 %22, e
@@ -2346,32 +2346,68 @@
     %7D%0A        %7D%0A
+        // build parser table cache%0A
         Grammar 
@@ -2501,24 +2501,52 @@
 ate(false);%0A
+        // write cache file%0A
         try 

Fix parser table cache loader