diff options
author | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2005-12-19 13:49:03 +0000 |
---|---|---|
committer | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2005-12-19 13:49:03 +0000 |
commit | ac849228490d5a0e2d3f048d649297d5c59b6ade (patch) | |
tree | 6314f2c06f37e67dec5827c3f94e25cf844a085c /src/compiler/scala/tools/nsc/matching/SequenceMatchers.scala | |
parent | d6c0efe5b4b89a0337f1cdcdabf8c607d81f4ae1 (diff) | |
download | scala-ac849228490d5a0e2d3f048d649297d5c59b6ade.tar.gz scala-ac849228490d5a0e2d3f048d649297d5c59b6ade.tar.bz2 scala-ac849228490d5a0e2d3f048d649297d5c59b6ade.zip |
Switching to the new build system and to the ne...
Switching to the new build system and to the new build system. This is a
MAJOR commit, so be careful when updating.
Diffstat (limited to 'src/compiler/scala/tools/nsc/matching/SequenceMatchers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/matching/SequenceMatchers.scala | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/SequenceMatchers.scala b/src/compiler/scala/tools/nsc/matching/SequenceMatchers.scala new file mode 100644 index 0000000000..d2d8aa7414 --- /dev/null +++ b/src/compiler/scala/tools/nsc/matching/SequenceMatchers.scala @@ -0,0 +1,173 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author buraq + */ +// $Id$ + +package scala.tools.nsc.matching; + +import java.util._ ; + +/** 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. + */ + +trait SequenceMatchers: TransMatcher { + + import global._; + + class SequenceMatcher { + + // Console.println("CONSTR SEQUENCEMATCHER"); + final val IGNORED = new Integer(42); + + var _m: PartialMatcher = _; + + var bbuild: BindingBerrySethi = null; + + /** collects variables + * @return all variables bound by this binding nfa + */ + def collectNfaVariables(nfa: NondetWordAutom): Set = { + val seqVars = new HashSet(); + var j = 0; + while(j < nfa.nstates) { + if( nfa.qbinders( j ) != null ) + seqVars.addAll( nfa.qbinders( j ) ); + j = j + 1 + } + seqVars; + } + + + /** translates the det/switching automaton to scala code + * precondition: pat.type() corresponds to element type + */ + def addBinderToBody( pat1:Tree , body:Tree ): Tree = { + if( bbuild == null ) + bbuild = new BindingBerrySethi; + + val elementType1 = getElemType_Sequence( pat1.tpe ); + + // (a) build *binding* nfa (sequential machine) + val left = bbuild.automatonFrom( pat1, IGNORED ); + val right = bbuild.revnfa; + + // (b) determinize + translate L + + val dLeft = new DetWordAutom( left ); + + val ltis = new LeftTracerInScala { + val dfa = dLeft; + val owner = _m.owner; + val selector = _m.selector; + val elementType = elementType1; + } + + val trace = ltis.getTrace(); + + // (c) determinize + translate R + + val dRight = new DetWordAutom( right, left, dLeft ); + + val seqVars1 = collectNfaVariables( left ); + //System.out.println("seqVars here are:"+seqVars); + val rtis = new RightTracerInScala { + val dfa = dRight; + val owner = _m.owner; + val pat = pat1; + val seqVars = seqVars1; + val elementType = elementType1; + } + + // !!! Tree stms2 = rtis.getStms( theTrace, cunit, body ); + // !!! gen.mkBlock_( body.pos, trace, stms2 ); + val stms2 = rtis.getStms( trace, cunit, body ); + stms2; + } + + private def buildNfas( pat:scala.List[Tree] ): Array[NondetWordAutom] = { + val build = new BerrySethi; + val manyNfa = new Array[NondetWordAutom]( pat.length ); + var i = 0; + val it = pat.elements; + while( i < pat.length ) { + manyNfa( i ) = build.automatonFrom( it.next, new Integer( i )); + i = i + 1; + //manyNfa[ i ].print(); + } + 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 + */ + def construct(_m: PartialMatcher, pat: scala.List[Tree] , body: scala.List[Tree] , defcase1: Tree, doBinding: Boolean ): Unit = { + var defaultCase = defcase1; + this._m = _m; + //assert body.length == pat.length; + if( defaultCase == null ) + defaultCase = ThrowMatchError( _m.pos, resultType ); + + val seqType = pat( 0 ).tpe; + val elementType1 = getElemType_Sequence( seqType ); + + // STEP 1 - build nfas for each pattern + + val manyNfa = buildNfas( pat ); + + // STEP 2 - recognizing + + // (a) merge nfas into one if necessary + val nfa = if(pat.length > 1) + new NondetWordAutom( manyNfa ) + else + manyNfa( 0 ); + + //nfa.print(); + + // (b) determinize + val dfa1 = new DetWordAutom( nfa ); + + // (c) translate to scala code + val scalaAut = + new WordAutomInScala{ + val dfa = dfa1; + val owner = _m.owner; + val optim = settings.target == "jvm"; + val elementType = elementType1; + } + scalaAut.translate(); + + // STEP 3 - binding + + var newbody: scala.List[Tree] = Nil; + if( !doBinding ) + newbody = body; + else { // this is done in the body of the matching case + var i = 0; + while(i < body.length) { + if( !containsBinding( pat( i ) ) ) + newbody = body( i ) :: newbody; // no need for binding + else + newbody = addBinderToBody( pat( i ), body( i ) ) :: newbody; + i = i + 1; + } + newbody = newbody.reverse; + } + _m.tree = scalaAut.getMatcherSwitch( _m.selector, + defaultCase, + newbody ); + } // construct (PartialMatcher, Tree[], Tree[], Tree, boolean ) + + } // class SequenceMatcher +} |