Package org.sugarj.driver.declprovider

Source Code of org.sugarj.driver.declprovider.SourceToplevelDeclarationProvider

package org.sugarj.driver.declprovider;

import static org.sugarj.common.Log.log;

import java.io.IOException;
import java.text.ParseException;
import java.util.concurrent.TimeoutException;

import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.jsglr.client.FilterException;
import org.spoofax.jsglr.client.InvalidParseTableException;
import org.spoofax.jsglr.client.SGLR;
import org.spoofax.jsglr.client.imploder.IToken;
import org.spoofax.jsglr.client.imploder.ImploderAttachment;
import org.spoofax.jsglr.shared.SGLRException;
import org.spoofax.jsglr.shared.TokenExpectedException;
import org.strategoxt.lang.StrategoException;
import org.sugarj.common.ATermCommands;
import org.sugarj.common.FileCommands;
import org.sugarj.common.Log;
import org.sugarj.common.path.Path;
import org.sugarj.driver.Driver;
import org.sugarj.driver.IncrementalParseResult;
import org.sugarj.driver.RetractableTokenizer;
import org.sugarj.driver.RetractableTreeBuilder;
import org.sugarj.util.Pair;

public class SourceToplevelDeclarationProvider implements ToplevelDeclarationProvider {

  private Driver driver;
  private String lastRemainingInput;
  private String remainingInput;
  private final int hash;
  private RetractableTreeBuilder treeBuilder;

  public SourceToplevelDeclarationProvider(Driver driver, String source) {
    this.driver = driver;
    this.remainingInput = source;
    this.treeBuilder = new RetractableTreeBuilder();
    hash = source.hashCode();
    // XXX need to load ANY parse table, preferably an empty one.
  }

  @Override
  public IStrategoTerm getNextToplevelDecl(boolean recovery, boolean lookahead) throws IOException, ParseException, InvalidParseTableException, SGLRException {
    IncrementalParseResult parseResult = parseNextToplevelDeclaration(remainingInput, recovery, lookahead);
    lastRemainingInput = remainingInput;
    remainingInput = parseResult.getRest();
    return parseResult.getToplevelDecl();
  }

  private IncrementalParseResult parseNextToplevelDeclaration(String input, boolean recovery, boolean lookahead)
      throws IOException, ParseException, InvalidParseTableException, TokenExpectedException, SGLRException {
    int start = treeBuilder.getTokenizer() == null ? 0 : treeBuilder.getTokenizer().getStartOffset();
    log.beginTask("parsing", "PARSE next toplevel declaration.", Log.CORE);
    try {
      Pair<IStrategoTerm, Integer> parseResult = null;
     
      try {
        parseResult = driver.currentParse(input, treeBuilder, recovery);
      } catch (SGLRException e) {
        if (e.getCause() instanceof TimeoutException)
          parseResult = driver.currentParse(input, treeBuilder, false);
       
        if (parseResult == null)
          throw e;
      }

      if (parseResult == null || parseResult.a == null)
        throw new ParseException("could not parse toplevel declaration in:\n" + input, -1);

      IStrategoTerm toplevelDecl = parseResult.a;
      String rest = input.substring(Math.min(parseResult.b, input.length()));

      if (input.equals(rest))
        if (driver.getParser().getCollectedErrors().isEmpty())
          throw new SGLRException(driver.getParser(), "empty toplevel declaration parse rule");
        else
          throw driver.getParser().getCollectedErrors().iterator().next();
     
//      try {
//        if (!rest.isEmpty())
//          inputTreeBuilder.retract(restTerm);
//      } catch (Throwable t) {
//        t.printStackTrace();
//      }
     
      Path tmpFile = FileCommands.newTempFile("aterm");
      FileCommands.writeToFile(tmpFile, toplevelDecl.toString());
      log.log("next toplevel declaration parsed: " + tmpFile, Log.PARSE);

      return new IncrementalParseResult(toplevelDecl, rest);
    } catch (Exception e) {
//      if (!recovery)
//        throw new SGLRException(driver.getParser(), "parsing failed", e);
     
      String msg = e.getClass().getName() + " " + e.getLocalizedMessage() != null ? e.getLocalizedMessage() : e.toString();
     
      if (!(e instanceof StrategoException) && !(e instanceof ParseException) && (!(e instanceof SGLRException) || (e instanceof FilterException)))
        e.printStackTrace();
      else
        log.logErr(msg, Log.DETAIL);
     
      if (!treeBuilder.isInitialized()) {
        SGLR parser = driver.getParser();
        if (parser == null && (e instanceof SGLRException))
          parser = ((SGLRException) e).getParser();
        if (parser == null)
          return new IncrementalParseResult(ATermCommands.factory.makeString(input), "");
        treeBuilder.initializeTable(parser.getParseTable(), 0, 0, 0);
        treeBuilder.initializeInput(input, null);
      }
      else if (treeBuilder.getTokenizer().getStartOffset() > start) {
        IToken token = treeBuilder.getTokenizer().getTokenAtOffset(start);
        ((RetractableTokenizer) treeBuilder.getTokenizer()).retractTo(token.getIndex());
        treeBuilder.setOffset(start);
      }
     
      IToken right = treeBuilder.getTokenizer().makeToken(start + input.length() - 1, IToken.TK_STRING, true);
      IToken left = treeBuilder.getTokenizer().getTokenAtOffset(start);
      treeBuilder.getTokenizer().makeToken(treeBuilder.getTokenizer().getStartOffset() - 1, IToken.TK_EOF, true);
      IStrategoTerm term = ATermCommands.factory.makeString(input);
      ImploderAttachment.putImploderAttachment(term, false, "String", left, right);
      if (!lookahead)
        driver.setErrorMessage(term, msg);
      return new IncrementalParseResult(term, "");
    } finally {
      log.endTask();
    }
  }

  @Override
  public void retract(IStrategoTerm term) {
    if (lastRemainingInput == null)
      throw new IllegalStateException("cannot retract now");

    if (term != null) {
      remainingInput = lastRemainingInput;
      lastRemainingInput = null;
      treeBuilder.retract(term);
    }
  }

  @Override
  public boolean hasNextToplevelDecl() {
    return !remainingInput.isEmpty();
  }

  @Override
  public int getSourceHashCode() {
    return hash;
  }

  @Override
  public IToken getStartToken() {
    if (treeBuilder != null && treeBuilder.getTokenizer() != null)
      return treeBuilder.getTokenizer().getTokenAt(0);
    return null;
  }

}
TOP

Related Classes of org.sugarj.driver.declprovider.SourceToplevelDeclarationProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.