package scalac.transformer.matching ; import scalac.*; import scalac.ast.Tree; import Tree.*; //import scala.compiler.printer.TextTreePrinter ; // DEBUGGING\ //import scala.compiler.printer.XMLAutomPrinter ; // DEBUGGING\ import scalac.transformer.TransMatch.Matcher ; import scalac.ast.* ; import scalac.symtab.* ; import java.util.* ; import ch.epfl.lamp.util.Position; /** constructs a matcher for a sequence pattern. plays two roles in * described in design pattern Builder. * is the "Director" for "Builder" class BerrySethi. * is the "Builder" for "Director" class TransMatch. */ public class SequenceMatcher extends PatternTool { final static Integer IGNORED = new Integer(42); CodeFactory cf; Matcher _m; //Tree pat[]; //Tree body[]; BindingBerrySethi bbuild = null; /** translates the det/switching automaton to scala code * precondition: pat.type() corresponds to element type */ Tree addBinderToBody( Tree pat, Tree body ) { if( bbuild == null ) bbuild = new BindingBerrySethi(); Type elementType = cf.getElemType_Sequence( pat.getType() ); // (a) build *binding* nfa (sequential machine) NondetWordAutom left = bbuild.automatonFrom( pat, IGNORED ); NondetWordAutom right = bbuild.revnfa; // (b) determinize + translate L DetWordAutom dLeft = new DetWordAutom( left ); LeftTracerInScala ltis = new LeftTracerInScala( dLeft, elementType, _m.owner, _m.selector, cf); Tree trace = ltis.getTrace(); Tree theTrace = gen.Ident( cf.pos, ltis.resultSym ); // (c) determinize + translate R DetWordAutom dRight = new DetWordAutom( right, left, dLeft ); Set seqVars = NondetWordAutom.collectVariables( left ); //System.out.println("seqVars here are:"+seqVars); final RightTracerInScala rtis = new RightTracerInScala( dRight, seqVars, _m.owner, cf, pat, elementType ); Tree stms2[] = rtis.getStms( theTrace, unit, body ); // paste statements together Tree items[] = new Tree[ 1 + stms2.length ]; items[ 0 ] = trace; System.arraycopy( stms2, 0, items, 1, stms2.length ); return gen.mkBlock( body.pos, items ); } private NondetWordAutom[] buildNfas( Tree[] pat ) { BerrySethi build = new BerrySethi(); NondetWordAutom manyNfa[] = new NondetWordAutom[ pat.length ]; for( int i = 0; i < pat.length; i++ ) { manyNfa[ i ] = build.automatonFrom( pat[ i ], new Integer( i )); //manyNfa[ i ].print(); } return manyNfa; } /** constructs a word recognizer from an array of patterns which * should all be SequencePatterns ( no wildcard * ) * precondition: pat.type corresponds to element type * @param _m Matcher object, holds the result * @param pat the (Sequence) patterns * @param body the bodies * @param defaultCase code that is run when nothing matches. may be null, it * becomes a ThrowMatchError then * @param doBinding flasg that indicates whether variables should be bound */ public void construct( Matcher _m, Tree[] pat, Tree[] body, Tree defaultCase, boolean doBinding ) { this._m = _m; //this.pat = pat; //this.body = body; assert body.length == pat.length; if( defaultCase == null ) defaultCase = cf.ThrowMatchError( cf.pos, _m.resultType ); this.cf = new CodeFactory( unit, _m.pos ); Type seqType = pat[ 0 ].getType(); Type elementType = cf.getElemType_Sequence( seqType ); // STEP 1 - build nfas for each pattern NondetWordAutom manyNfa[] = buildNfas( pat ); // STEP 2 - recognizing // (a) merge nfas into one if necessary NondetWordAutom nfa = (pat.length > 1) ? new NondetWordAutom( manyNfa ) : manyNfa[ 0 ]; //nfa.print(); // (b) determinize DetWordAutom dfa = new DetWordAutom( nfa ); // (c) translate to scala code WordAutomInScala scalaAut = new WordAutomInScala( dfa, elementType, _m.owner, cf, unit.global.target == Global.TARGET_JVM ); scalaAut.translate(); // STEP 3 - binding Tree newbody[]; if( !doBinding ) newbody = body; else { // this is done in the body of the matching case newbody = new Tree[body.length]; for( int i = 0; i < body.length; i++ ) if( !CollectVariableTraverser.containsBinding( pat[ i ] ) ) newbody[ i ] = body[ i ]; // no need for binding else newbody[ i ] = addBinderToBody( pat[ i ], body[ i ] ); } _m.tree = scalaAut.getMatcherSwitch( _m.selector, defaultCase, newbody, _m.resultType ); } // construct (Matcher, Tree[], Tree[], Tree, boolean ) /** constructor, invoked by AlgebraicMatcher */ SequenceMatcher( Unit unit ) { super( unit ); } } // class SequenceMatcher