Package org.rascalmpl.interpreter.matching

Source Code of org.rascalmpl.interpreter.matching.RegExpPatternValue

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Emilie Balland - (CWI)
*   * Paul Klint - Paul.Klint@cwi.nl - CWI
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.matching;

import static org.rascalmpl.interpreter.result.ResultFactory.makeResult;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.type.Type;
import org.rascalmpl.ast.AbstractAST;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.staticErrors.RedeclaredVariable;
import org.rascalmpl.interpreter.staticErrors.SyntaxError;
import org.rascalmpl.semantics.dynamic.RegExpLiteral;
import org.rascalmpl.semantics.dynamic.RegExpLiteral.InterpolationElement;

public class RegExpPatternValue extends AbstractMatchingResult  {
  private final List<InterpolationElement> regexp;
  private Pattern pat;            // The Pattern resulting from compiling the regexp
 
  private List<String> patternVars;      // The variables occurring in the regexp
  private Matcher matcher;          // The actual regexp matcher
  String subject;                // Subject string to be matched
  private boolean initialized = false;    // Has matcher been initialized?
  private boolean firstMatch;            // Is this the first match?
  private boolean hasNext;          // Are there more matches?
 
  private int start;              // start of last match in current subject
  private int end;              // end of last match in current subject
 
  private boolean iWroteItMySelf;
 
 
//  private static HashMap<String,Matcher> matcherCache =
//    new HashMap<String,Matcher>();
 
  public RegExpPatternValue(IEvaluatorContext ctx, AbstractAST x, java.util.List<RegExpLiteral.InterpolationElement> regexp, List<String> patternVars) {
    super(ctx, x);
   
    this.regexp = regexp;
    this.patternVars = patternVars;
    initialized = false;
    this.iWroteItMySelf = false;
  }
 
  private String interpolate(IEvaluatorContext env) {
    StringBuilder b = new StringBuilder();
   
    for (RegExpLiteral.InterpolationElement elem : regexp) {
      b.append(elem.getString(env));
    }
   
    return b.toString();
  }
 
 

  @Override
  public Type getType(Environment ev, HashMap<String,IVarPattern> patternVars) {
    return tf.stringType();
  }

  @Override
  public void initMatch(Result<IValue> subject) {
    super.initMatch(subject);
   
    Type runType = subject.getValue().getType();
   
    if(runType.isSubtypeOf(tf.stringType())) {
      this.subject = ((IString) subject.getValue()).getValue();
    }
    else {
      hasNext = false;
      return;
    }
   
    initialized = firstMatch = hasNext = true;
   
    try {
      String RegExpAsString = interpolate(ctx);
      pat = Pattern.compile(RegExpAsString);
    } catch (PatternSyntaxException e){
      throw new SyntaxError(e.getMessage(), ctx.getCurrentAST().getLocation());
    }
  }
 
  @Override
  public boolean hasNext() {
    return initialized && (firstMatch || hasNext);
  }
 
  @Override
  public boolean mayMatch(Type subjectType, Environment env) {
    return subjectType.equivalent(tf.stringType());
  }
 
  public int getStart(){
    return start;
  }
 
  public int getEnd(){
    return end;
  }
 
  private boolean findMatch(){
    while(matcher.find()){
      for (int nVar = 0; nVar < patternVars.size(); nVar++){
        java.lang.String binding = matcher.group(1+nVar);
        if(binding != null){
          java.lang.String name = patternVars.get(nVar);
          ctx.getCurrentEnvt().storeVariable(name, makeResult(tf.stringType(), ctx.getValueFactory().string(binding), ctx));
        }
      }
      start = matcher.start(0);
      end = matcher.end(0);
      return true;
    }
    hasNext = false;
    return false;
  }
 
  @Override
  public boolean next(){
    if(firstMatch){
      firstMatch = false;
// TODO Commented out caching code since it does not seem to help;
//      matcher = matcherCache.get(RegExpAsString);
//      if(matcher == null){
        matcher = pat.matcher(subject);
//        matcherCache.put(RegExpAsString, matcher);
//      } else
//        matcher.reset(subject);
      IString empty = ctx.getValueFactory().string("");
     
      // Initialize all pattern variables to ""
      for(String name : patternVars){
        if(!this.iWroteItMySelf
            && !ctx.getCurrentEnvt().declareVariable(tf.stringType(), name))
          throw new RedeclaredVariable(name, ctx.getCurrentAST());
        ctx.getCurrentEnvt().storeVariable(name, makeResult(tf.stringType(), empty, ctx));
      }
      this.iWroteItMySelf = true;
    }
   
    try {
      return findMatch();
    }
    catch (ArrayIndexOutOfBoundsException e) {
      throw new ImplementationError("Unexpected error in mapping to Java regex:" + interpolate(ctx), ctx.getCurrentAST().getLocation());
    }
  }
 
  @Override
  public List<IVarPattern> getVariables(){
    List<IVarPattern> res = new LinkedList<IVarPattern>();
    for(String name : patternVars){
      res.add(new RegExpVar(name));
    }
    return res;
  }
 
  @Override
  public String toString(){
    return "RegExpPatternValue(" + regexp + ", " + patternVars + ")";
  }

  @Override
  public AbstractAST getAST() {
    return ctx.getCurrentAST();
  }
 
  public boolean bindingInstance() {
    return this.iWroteItMySelf;
  }
}
TOP

Related Classes of org.rascalmpl.interpreter.matching.RegExpPatternValue

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.