<commit_before>/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002-2003, LAMP/EPFL         **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac.ast.parser;

import scalac.Unit;
import scalac.ast.*;
import scalac.util.Name;
import Tree.*;
import java.util.HashMap;

import scalac.util.Names;

/** contains algorithms for `checking' and `normalizing' patterns
 *
 *  @author  <NAME>
 *  @version 1.0
 */

public class PatternNormalizer {

    /** the compilation unit - needed for error reporting
     */
    Unit unit;

    /** the tree factory
     */
    public TreeFactory make;

    // constructor ... unit is needed to display errors

    public PatternNormalizer( Unit unit ) {
	this.unit = unit;
        this.make = unit.global.make;
    }

    //
    ///////// CHECKING patterns for well-formedness ///////////////////////////////
    //

    int seqDepth;

    /** checks whether TO DO TO DO TO DO
     *  - @-recursion occurs only at the end just below a sequence
     *  returns true if the tree is ok.
     *  inSeq: flag, true if we are in a sequence '[' ... ']'
     *  t: the tree to be checked
     */
    protected boolean check1( Tree t, boolean inAlt ) {
	switch( t ) {

	case Literal( _ ):
	    return true;

	case Apply( _, Tree[] args ):
              seqDepth++;
              boolean res = check1( args, inAlt );
              seqDepth--;
              return res;

	case Sequence( Tree[] trees ): // this is a hack to disallow deep binding
              seqDepth++;
              boolean res = check1( trees, inAlt );
              seqDepth--;
              return res;

	case Alternative( Tree[] trees ):
	    return check1( trees, true );

	case Bind( Name var, Tree tree ):
	    if(( inAlt )
	       &&( var.toString().lastIndexOf("$") == -1)) {

		unit.error( t.pos,
			      "variable binding not allowed under alternative");
		return false;
	    }
            if(( seqDepth > 2 )
               &&( var.toString().lastIndexOf("$") == -1)) {
		unit.error( t.pos,
			      "sorry, deep binding not implemented");
		return false;
            }
	    this.boundVars.put( var /*t.symbol()*/, Boolean.FALSE );
	    /*
              boolean result = check( tree, inSeq );
              if(((Boolean) this.boundVars.get( t.symbol() ))
	      .booleanValue()) { // occurs recursively
	      // do something to RESTRICT recursion
              }
	    */
	    return check1( tree, inAlt );

	case Typed( _, _):
	    return true;

	case Ident( Name var ):
	    if (inAlt && var.isVariable() && var != Names.PATTERN_WILDCARD &&
		var.lastPos((byte)'$') == -1) {
		unit.error( t.pos,
			    "variable not allowed under alternative");
		return false;
	    }
              /*
              System.out.println( t.symbol().toString() );
              */
	    if(( this.boundVars.containsKey( var /*t.symbol()*/ ))
	       &&( var.toString().lastIndexOf("$") == -1)) {
		  unit.error( t.pos,
			      "recursive patterns not allowed");

		  //this.boundVars.put( t.symbol(), Boolean.TRUE ); //mark recursive
                    //System.out.println( t.symbol() + "occurs recursively");
              }

	    return true;

	case Select( _, _ ):
	    return true;

	default:
	    unit.error( t.pos, "whut'z dis ?"+t.toString()); // never happens
	}
	return false;

    }

    /** checkPat for every tree in array of trees, see below
     */
      protected boolean check1( Tree[] trees, boolean inAlt ) {
	for( int i = 0; i < trees.length; i++ )
	    if( !check1(  trees[ i ], inAlt ))
		return false;
	return true;
    }

      // if this map contains a symbol as a key, it is bound.
      // if this symbol is mapped to Boolean.True, it occurs recursively
    HashMap/*Name=>Boolean*/ boundVars;

      /**  method
       */
      public boolean check( Tree pat ) {
            this.boundVars = new HashMap();
            if( TreeInfo.isRegularPattern( pat ) )
                  seqDepth = 0;
            else
                  seqDepth = -32;  // don't care about sequences. see above
            return check1( pat, false );<commit_msg>do not allow top-level sequence patterns<commit_after>/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002-2003, LAMP/EPFL         **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac.ast.parser;

import scalac.Unit;
import scalac.ast.*;
import scalac.util.Name;
import Tree.*;
import java.util.HashMap;

import scalac.util.Names;

/** contains algorithms for `checking' and `normalizing' patterns
 *
 *  @author  <NAME>
 *  @version 1.0
 */

public class PatternNormalizer {

    /** the compilation unit - needed for error reporting
     */
    Unit unit;

    /** the tree factory
     */
    public TreeFactory make;

    // constructor ... unit is needed to display errors

    public PatternNormalizer( Unit unit ) {
	this.unit = unit;
        this.make = unit.global.make;
    }

    //
    ///////// CHECKING patterns for well-formedness ///////////////////////////////
    //

    int seqDepth;

    /** checks whether TO DO TO DO TO DO
     *  - @-recursion occurs only at the end just below a sequence
     *  returns true if the tree is ok.
     *  inSeq: flag, true if we are in a sequence '[' ... ']'
     *  t: the tree to be checked
     */
    protected boolean check1( Tree t, boolean inAlt ) {
	switch( t ) {

	case Literal( _ ):
	    return true;

	case Apply( _, Tree[] args ):
              seqDepth++;
              boolean res = check1( args, inAlt );
              seqDepth--;
              return res;

	case Sequence( Tree[] trees ): // this is a hack to disallow deep binding
              seqDepth++;
              boolean res = check1( trees, inAlt );
              seqDepth--;
              return res;

	case Alternative( Tree[] trees ):
	    return check1( trees, true );

	case Bind( Name var, Tree tree ):
	    if(( inAlt )
	       &&( var.toString().lastIndexOf("$") == -1)) {

		unit.error( t.pos,
			      "variable binding not allowed under alternative");
		return false;
	    }
            if(( seqDepth > 2 )
               &&( var.toString().lastIndexOf("$") == -1)) {
		unit.error( t.pos,
			      "sorry, deep binding not implemented");
		return false;
            }
	    this.boundVars.put( var /*t.symbol()*/, Boolean.FALSE );
	    /*
              boolean result = check( tree, inSeq );
              if(((Boolean) this.boundVars.get( t.symbol() ))
	      .booleanValue()) { // occurs recursively
	      // do something to RESTRICT recursion
              }
	    */
	    return check1( tree, inAlt );

	case Typed( _, _):
	    return true;

	case Ident( Name var ):
	    if (inAlt && var.isVariable() && var != Names.PATTERN_WILDCARD &&
		var.lastPos((byte)'$') == -1) {
		unit.error( t.pos,
			    "variable not allowed under alternative");
		return false;
	    }
              /*
              System.out.println( t.symbol().toString() );
              */
	    if(( this.boundVars.containsKey( var /*t.symbol()*/ ))
	       &&( var.toString().lastIndexOf("$") == -1)) {
		  unit.error( t.pos,
			      "recursive patterns not allowed");

		  //this.boundVars.put( t.symbol(), Boolean.TRUE ); //mark recursive
                    //System.out.println( t.symbol() + "occurs recursively");
              }

	    return true;

	case Select( _, _ ):
	    return true;

	default:
	    unit.error( t.pos, "whut'z dis ?"+t.toString()); // never happens
	}
	return false;

    }

    /** checkPat for every tree in array of trees, see below
     */
      protected boolean check1( Tree[] trees, boolean inAlt ) {
	for( int i = 0; i < trees.length; i++ )
	    if( !check1(  trees[ i ], inAlt ))
		return false;
	return true;
    }

      // if this map contains a symbol as a key, it is bound.
      // if this symbol is mapped to Boolean.True, it occurs recursively
    HashMap/*Name=>Boolean*/ boundVars;

      /**  method
       */
      public boolean check( Tree pat ) {
            this.boundVars = new HashMap();

            //reject top-level sequence patterns
            switch( pat ) {
                case Sequence( _ ):
                    unit.error( pat.pos,
                                "sequences not allowed here");
                    return false;
                case Alternative( Tree args[] ):
                    for( int i = 0; i < args.length; i++ )
                        switch( args[i] ) {
                        case Sequence( _ ):
                            unit.error( args[i].pos,
                                        "sequences not allowed here");
                            return false;
                        }
            }



            // reject deep binding
            if( TreeInfo.isRegularPattern( pat ) )
                  seqDepth = 0;
            else
                  seqDepth = -32;  // don't care about sequences. see above
            return check1( pat, false );
{'fraction_non_alphanumeric': 0.13487638085218306, 'fraction_numerical': 0.005786428195686481, 'mean_word_length': 1.4652489626556016, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 17, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6808730', 'n_tokens_mistral': 2804, 'n_tokens_neox': 2596, 'n_words': 791}