Package anvil.script.statements

Source Code of anvil.script.statements.Statement

/*
* $Id: Statement.java,v 1.47 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script.statements;

import anvil.Location;
import anvil.core.Any;
import anvil.core.Array;
import anvil.codec.Source;
import anvil.codec.Target;
import anvil.codec.ExceptionHandler;
import anvil.parser.Tag;
import anvil.ErrorListener;
import anvil.script.compiler.ByteCompiler;
import anvil.script.Context;
import anvil.script.expression.Expression;
import anvil.script.parser.TemplateParser;
import anvil.script.Grammar;
import anvil.script.Scope;
import anvil.script.Type;
import anvil.java.util.Holder;
import java.io.IOException;
import java.util.Hashtable;

/**
* class Statement
*
* @author: Jani Lehtim�ki
*/
public abstract class Statement
{

  static final public Statement EMPTY = new Statement(null, null)
  {
  };
 

  static final public String DEFAULT_NAMESPACE = "anvil";

  public static final int CONTENT_PRESERVE = 0;
  public static final int CONTENT_COMPRESS = 1;
  public static final int CONTENT_PACK     = 2;
  public static final int CONTENT_SILENT   = 3;
 
  public static final String[] CONTENT_PROCESSING = {
    "preserve",
    "compress",
    "pack",
    "silent"
  };

  static final public int ST_INVALID       = -1;
  static final public int ST_NONE          =  0;

  static final public int ST_BREAK         =  1;
  static final public int ST_CALL          =  2;
  static final public int ST_CASE          =  3;
  static final public int ST_CATCH         =  4;
  static final public int ST_CDATA         =  5;
  static final public int ST_CLASS         =  6;
  static final public int ST_COMPRESS      =  7;
  static final public int ST_CONST         =  8;
  static final public int ST_CONTINUE      =  9;
  static final public int ST_DEFAULT       = 10;
  static final public int ST_DO            = 11;
  static final public int ST_DOCUMENT      = 12;
  static final public int ST_ELSE          = 13;
  static final public int ST_ELSEIF        = 14;
  static final public int ST_ENDCASE       = 15;
  static final public int ST_ENDDEFAULT    = 16;
  static final public int ST_ENDEVAL       = 17;
  static final public int ST_ENDFOR        = 18;
  static final public int ST_ENDFOREACH    = 19;
  static final public int ST_ENDFUNCTION   = 20;
  static final public int ST_ENDIF         = 21;
  static final public int ST_ENDMODULE     = 22;
  static final public int ST_ENDREPLACE    = 23;
  static final public int ST_ENDSWITCH     = 24;
  static final public int ST_ENDWHILE      = 25;
  static final public int ST_EVAL          = 27;
  static final public int ST_FINALLY       = 28;
  static final public int ST_FOR           = 29;
  static final public int ST_FOREACH       = 30;
  static final public int ST_FUNCTION      = 31;
  static final public int ST_IF            = 32;
  static final public int ST_IMPORT        = 33;
  static final public int ST_INTERFACE     = 34;
  static final public int ST_INVOKE        = 35;
  static final public int ST_MODULE        = 36;
  static final public int ST_PRESERVE      = 37;
  static final public int ST_PRINT         = 38;
  static final public int ST_REPLACE       = 39;
  static final public int ST_RETURN        = 40;
  static final public int ST_SILENT        = 41;
  static final public int ST_SWITCH        = 42;
  static final public int ST_TAG           = 43;
  static final public int ST_THROW         = 44;
  static final public int ST_TRY           = 45;
  static final public int ST_VAR           = 46;
  static final public int ST_WHILE         = 47;
  static final public int ST_ASSERT        = 49;
  static final public int ST_EXIT          = 50;
  static final public int ST_BLOCK         = 51;
  static final public int ST_CUSTOM_TAG    = 52;
  static final public int ST_SYNCHRONIZED  = 53;
  static final public int ST_YIELD         = 54;
  static final public int ST_ENDCLASS      = 55;
  static final public int ST_NAMESPACE     = 56;
  static final public int ST_ENDNAMESPACE  = 57;
  static final public int ST_IMPLICIT_BLOCK = 58;
  static final public int ST_PACK          = 59;
 
  static final private Hashtable _tags = new Hashtable();

  static
  {
    _tags.put("module", new Integer(ST_MODULE));
    _tags.put("/module", new Integer(ST_ENDMODULE));

    _tags.put("import", new Integer(ST_IMPORT));

    _tags.put("var", new Integer(ST_VAR));
    _tags.put("const", new Integer(ST_CONST));

    _tags.put("function", new Integer(ST_FUNCTION));
    _tags.put("/function", new Integer(ST_ENDFUNCTION));

    _tags.put("print", new Integer(ST_PRINT));
    _tags.put("replace", new Integer(ST_REPLACE));
    _tags.put("/replace", new Integer(ST_ENDREPLACE));

    _tags.put("if", new Integer(ST_IF));
    _tags.put("else", new Integer(ST_ELSE));
    _tags.put("elseif", new Integer(ST_ELSEIF));
    _tags.put("/if", new Integer(ST_ENDIF));

    _tags.put("while", new Integer(ST_WHILE));
    _tags.put("/while", new Integer(ST_ENDWHILE));

    _tags.put("return", new Integer(ST_RETURN));
    _tags.put("break", new Integer(ST_BREAK));
    _tags.put("continue", new Integer(ST_CONTINUE));

    _tags.put("switch", new Integer(ST_SWITCH));
    _tags.put("case", new Integer(ST_CASE));
    _tags.put("/case", new Integer(ST_ENDCASE));
    _tags.put("default", new Integer(ST_DEFAULT));
    _tags.put("/default", new Integer(ST_ENDDEFAULT));
    _tags.put("/switch", new Integer(ST_ENDSWITCH));

    _tags.put("foreach", new Integer(ST_FOREACH));
    _tags.put("/foreach", new Integer(ST_ENDFOREACH));

    _tags.put("for", new Integer(ST_FOR));
    _tags.put("/for", new Integer(ST_ENDFOR));

    _tags.put("eval", new Integer(ST_EVAL));
    _tags.put("/eval", new Integer(ST_ENDEVAL));

    _tags.put("preserve", new Integer(ST_PRESERVE));
    _tags.put("compress", new Integer(ST_COMPRESS));
    _tags.put("silent", new Integer(ST_SILENT));

    _tags.put("call", new Integer(ST_CALL));
    _tags.put("invoke", new Integer(ST_INVOKE));

    _tags.put("class", new Integer(ST_CLASS));
    _tags.put("/class", new Integer(ST_ENDCLASS));

    _tags.put("namespace", new Integer(ST_NAMESPACE));
    _tags.put("/namespace", new Integer(ST_ENDNAMESPACE));

  }


  public static int getTagId(Tag tag)
  {
    Integer id = (Integer)_tags.get(tag.getName().toLowerCase());
    if (id != null) {
      return id.intValue();
    } else {
      return ST_INVALID;
    }
  }


  private Location  _location;
  private Statement _parent;


  public Statement(Statement parent)
  {
    _parent = parent;
  }

 

  public Statement(Location location)
  {
    _location = location;
  }


  public Statement(Statement parent, Location location)
  {
    _parent = parent;
    _location = location;
  }


  public int typeOf()
  {
    return ST_NONE;
  }
 

  public String name()
  {
    return "statement";
  }


  public void setLocation(Location location)
  {
    _location = location;
  }


  public Location getLocation()
  {
    return _location;
  }


  public Statement getParentStatement()
  {
    return _parent;
  }
   

  public void setParentStatement(Statement parent)
  {
    _parent = parent;
  }


  public boolean hasEnd()
  {
    return false;
  }

 
  public boolean isStaticRegion()
  {
    return getParentStatement().isStaticRegion();
  }
 
 
  public boolean hasStaticContent()
  {
    return false;
  }
 
 
  public String getStaticContent()
  {
    return "";
  }
 

  public BlockStatement getBlockStatement()
  {
    Statement stmt = getChildStatement();
    if (stmt instanceof BlockStatement) {
      return (BlockStatement)stmt;
    } else {
      throw new RuntimeException("Child '"+stmt+"' is not instance of BlockStatement");
    }
  }  


  public void addChild(Statement statement)
  { 
    getBlockStatement().add(statement);
  }

 
  public Statement getChildStatement()
  {
    return null;
  }  


  public void setChildStatement(Statement child)
  {
    //throw new RuntimeException("Statement.setChildStatement called at "+this.getClass());
  }  



  public void parse(TemplateParser parser, Tag tag)
  {
  }


  public void importExternals(ErrorListener context)
  {
  }


  public void check(ErrorListener context)
  {
  }
 

  public Jumps eliminate(ErrorListener context)
  {
    return new Jumps();
  }


  private void doAddCharacters(TemplateParser parser, String cdata)
  {
    FunctionStatement function = getFunctionStatement();
    if (function != null) {
      switch(function.getContentState()) {
      case CONTENT_SILENT:
        return;
      case CONTENT_PRESERVE:
        break;
      case CONTENT_COMPRESS:
        cdata = compress(cdata);
        break;
      case CONTENT_PACK:
        cdata = pack(cdata);
        break;
      }
    }
    if (cdata.length() == 0) {
      return;
    }
    addChild(new CharacterDataStatement(this, parser.getLocation(), cdata));
  }
 

  public void onCharacters(TemplateParser parser, String cdata)
  {
    if ((cdata.length() >= 11) &&
        cdata.startsWith("<!--/*") && cdata.endsWith("*/-->")) {
      return;
    }

    if (cdata.indexOf("${") >= 0) {
      StringBuffer buffer = new StringBuffer();
      int n = cdata.length();
      for(int i=0; i<n; i++) {
        char ch = cdata.charAt(i);

        if ((ch == '\\') && (i+1<n)) {
          buffer.append(cdata.charAt(++i));
         
        } else if ((ch == '$') && (i+2<n)) {
          ch = cdata.charAt(++i);
          if (ch != '{') {
            buffer.append('$');
            buffer.append(ch);
            continue;
          }
         
          if (buffer.length()>0) {
            doAddCharacters(parser, buffer.toString());
          }
          buffer.setLength(0);
         
          boolean singleQuote = false;
          boolean doubleQuote = false;
          int nesting = 1;
         
          while(i+1<n && nesting>0) {
            ch = cdata.charAt(++i);
            switch(ch) {
            case '{':
              if (!singleQuote || !doubleQuote) {
                nesting++;
              }
              buffer.append(ch);
              break;
            case '}':
              if (!singleQuote || !doubleQuote) {
                nesting--;
              }
              if (nesting>0) {
                buffer.append(ch);
              }
              break;
            case '\\':
              if (i+1<n) {
                char nextch = cdata.charAt(++i);
                if (nextch == '}' || nextch == '{') {
                  buffer.append(nextch);
                } else {
                  buffer.append(ch);
                  buffer.append(nextch);
                }
              }
              break;
            case '\'':
              if (!doubleQuote) {
                singleQuote = !singleQuote;
              }
              buffer.append(ch);
              break;
            case '"':
              if (!singleQuote) {
                doubleQuote = !doubleQuote;
              }
              buffer.append(ch);
              break;
             
            default:
              buffer.append(ch);
            }
          }
         
          Expression expr = Grammar.parseExpression(buffer.toString(), getLocation(), parser);
          if (expr.isConstant()) {
            addChild(new CharacterDataStatement(this, parser.getLocation(), expr.eval().toString()));
          } else {
            addChild(new PrintStatement(this, parser.getLocation(), expr));
          }
          buffer.setLength(0);
         
        } else {
          buffer.append(ch);
        }
       
      }
     
      if (buffer.length()>0) {
        doAddCharacters(parser, buffer.toString());
      }
     
    } else {
      doAddCharacters(parser, cdata);
    }
  }
 

   public anvil.script.statements.taglib.Tag getTag(String ns, String name)
   {
     Statement parent = getParentStatement();
     if (parent != null) {
       return parent.getTag(ns, name);
     } else {
       return null;
     }
   }


  public boolean onTag(TemplateParser parser, int type, Tag tag)
  {
    Statement statement = null;
    boolean addblock = false;
    BlockStatement block = getBlockStatement();
   
    switch(type) {
    case ST_TAG:
      {
        String ns = tag.getNamespace();
        String name = tag.getName();
        anvil.script.statements.taglib.Tag tagdef = getTag(ns, name);
        if (tagdef != null) {
          statement = new CustomTagStatement(block, parser.getLocation(), tagdef, tag);
          addblock = statement.hasEnd();
          break;
        }
        FunctionStatement function = getFunctionStatement();
        if (function == null || function.getContentState() != Statement.CONTENT_SILENT) {
          onCharacters(parser, tag.toString());
        }
        return true;
      }

    case ST_EVAL:
      statement = new EvalStatement(block, parser.getLocation());
      addblock = true;
      break;

    case ST_PRINT:
      statement = new PrintStatement(block, parser.getLocation());
      break;

    case ST_CALL:
      statement = new CallStatement(block, parser.getLocation());
      break;

    case ST_INVOKE:
      statement = new InvokeStatement(block, parser.getLocation());
      break;
     
    case ST_RETURN:
      statement = new ReturnStatement(block, parser.getLocation());
      break;


    case ST_PACK:
      statement = new PackStatement(block, parser.getLocation());
      break;


    case ST_PRESERVE:
      statement = new PreserveStatement(block, parser.getLocation());
      break;

    case ST_COMPRESS:
      statement = new CompressStatement(block, parser.getLocation());
      break;

    case ST_SILENT:
      statement = new SilentStatement(block, parser.getLocation());
      break;

    case ST_IF:
      statement = new IfStatement(block, parser.getLocation());
      addblock = true;
      break;

    case ST_REPLACE:
      statement = new ReplaceStatement(block, parser.getLocation());
      break;

    case ST_WHILE:
      statement = new WhileStatement(block, parser.getLocation());
      addblock = true;
      break;

    case ST_FOREACH:
      statement = new ForeachStatement(block, parser.getLocation());
      addblock = true;
      break;

    case ST_FOR:
      statement = new ForStatement(block, parser.getLocation());
      addblock = true;
      break;

    case ST_SWITCH:
      statement = new SwitchStatement(block, parser.getLocation());
      break;

    case ST_BREAK:
      if (!allowBreak()) {
        parser.error(getLocation(), "Useless break, no valid enclosing statements open");
      } else {
        statement = new BreakStatement(block, parser.getLocation());
      }
      break;

    case ST_CONTINUE:
      if (!allowContinue()) {
        parser.error(getLocation(), "Useless continue, no valid enclosing statements open");
      } else {
        statement = new ContinueStatement(block, parser.getLocation());
      }
      break;
    }


    if (statement == null) {
      return false;
    }
   
    statement.parse(parser, tag);

    addChild(statement);
    if (statement.hasEnd()) {
      parser.push(statement);
      if (addblock) {
        statement.setChildStatement(
          new ImplicitBlockStatement(statement, statement.getLocation()));
      }
    }
   
    return true;
  }


  public boolean onProcessingInstruction(TemplateParser parser, String data)
  {
    onCharacters(parser, "<?" + data + "?>");
    return true;
  }


  public CatchStatement getCatchStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt.typeOf() == ST_CATCH) {
        return (CatchStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


  public ModuleStatement getModuleStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt.typeOf() == ST_MODULE) {
        return (ModuleStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


  public ClassStatement getClassStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt.typeOf() == ST_CLASS)  {
        return (ClassStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


  public InterfaceStatement getInterfaceStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt.typeOf() == ST_INTERFACE)  {
        return (InterfaceStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


  public FunctionStatement getFunctionStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt.typeOf() == ST_FUNCTION)  {
        return (FunctionStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


  public DefinitionStatement getDefinitionStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt instanceof DefinitionStatement)  {
        return (DefinitionStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;   
  }
 

  public DefinitionStatement getScopeStatement()
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt instanceof DefinitionStatement && stmt.typeOf() != ST_FUNCTION)  {
        return (DefinitionStatement)stmt;
      }
      stmt = stmt.getParentStatement();
    }
    return null;   
  }
   
 

  public Type lookupAnyDeclaration(String name)
  {
    Statement stmt = this;
    while(stmt != null) {
      switch(stmt.typeOf()) {
      case Statement.ST_MODULE:
      case Statement.ST_CLASS:
      case Statement.ST_INTERFACE:
      case Statement.ST_NAMESPACE:
      case Statement.ST_FUNCTION:
        {
          DefinitionStatement defstmt = (DefinitionStatement)stmt;
          Type type = defstmt.lookupDeclaration(name);
          if (type != null) {
            return type;
          }
        }
        break;
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


  public boolean isDeclared(String name)
  {
    return (lookupAnyDeclaration(name) != null);
  }
 

  public boolean allowBreak()
  {
    Statement stmt = this;
    while(stmt != null) {
      switch(stmt.typeOf()) {
      case Statement.ST_BLOCK:
      case Statement.ST_WHILE:
      case Statement.ST_DO:
      case Statement.ST_FOREACH:
      case Statement.ST_FOR:
      case Statement.ST_SWITCH:
        return true;
      case Statement.ST_IF:
      case Statement.ST_TRY:
      case Statement.ST_CATCH:
      case Statement.ST_FINALLY:
      case Statement.ST_SYNCHRONIZED:
      case Statement.ST_IMPLICIT_BLOCK:
        break;
      default:
        return false;
      }
      stmt = stmt.getParentStatement();
    }
    return false;
  }


  public boolean allowContinue()
  {
    Statement stmt = this;
    while(stmt != null) {
      switch(stmt.typeOf()) {
      case Statement.ST_BLOCK:
      case Statement.ST_WHILE:
      case Statement.ST_DO:
      case Statement.ST_FOREACH:
      case Statement.ST_FOR:
        return true;
      case Statement.ST_SWITCH:
      case Statement.ST_IF:
      case Statement.ST_TRY:
      case Statement.ST_CATCH:
      case Statement.ST_FINALLY:
      case Statement.ST_SYNCHRONIZED:
      case Statement.ST_IMPLICIT_BLOCK:
        break;
      default:
        return false;
      }
      stmt = stmt.getParentStatement();
    }
    return false;
  }
 

  public boolean allowYield()
  {
    Statement stmt = this;
    while(stmt != null) {
      switch(stmt.typeOf()) {
      case ST_FUNCTION:
        return true;
      case Statement.ST_FINALLY:
      case Statement.ST_SYNCHRONIZED:
        return false;
      case Statement.ST_TRY:
        {
          TryStatement trystmt = (TryStatement)stmt;
          if (trystmt.getFinally() != null) {
            return false;
          }
        }
        break;
      default:
        break;
      }
      stmt = stmt.getParentStatement();
    }
    return true;
 
 

  public boolean allowLabel(String label)
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt instanceof Labeled) {
        String candidate = ((Labeled)stmt).getLabel();
        if ((candidate != null) && (label.equals(candidate))) {
          return true;
        }
      }
      stmt = stmt.getParentStatement();
    }
    return false;
  }
 
 
  public int getLabelDepth(String label)
  {
    int depth = 0;
    Statement stmt = this;
    while(stmt != null) {
      if (stmt instanceof Labeled) {
        String candidate = ((Labeled)stmt).getLabel();
        if ((candidate != null) && (label.equals(candidate))) {
          return depth;
        }
        depth++;
      }
      stmt = stmt.getParentStatement();
    }
    return -1;
  }
 
 
 
  public Labeled getLabeled(String label, boolean iscont)
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt instanceof Labeled) {
        Labeled labeled = (Labeled)stmt;
        if (label != null) {
          String candidate = labeled.getLabel();
          if ((candidate != null) && (label.equals(candidate))) {
            if (!iscont || stmt.typeOf() != ST_SWITCH) {
              return labeled;
            }
          }
        } else {
          return labeled;
        }
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }

 
  public SwitchStatement getSwitch(String label)
  {
    Statement stmt = this;
    while(stmt != null) {
      if (stmt.typeOf() == ST_SWITCH) {
        SwitchStatement select = (SwitchStatement)stmt;
        if (label != null) {
          String candidate = select.getLabel();
          if ((candidate != null) && (label.equals(candidate))) {
            return select;
          }
        } else {
          return select;
        }
      }
      stmt = stmt.getParentStatement();
    }
    return null;
  }


 
  public void compile(ByteCompiler context)
  {
  }

 
  public boolean isBlocked()
  {
    return false;
  }
 

  public boolean callFinalizer()
  {
    return false;
  }

  public int getTypeRef(anvil.codec.ConstantPool pool, int type)
  {
    return 0;
  }


  public static final String compress(String cdata)
  {
    if (cdata.charAt(0) == '<') {
      return cdata;
    }
   
    int n = cdata.length();
    int i = 0;
    char ch;
    char pad = ' ';
    StringBuffer buffer = new StringBuffer(n);

    while(i<n) {
      ch = cdata.charAt(i);
      if (Character.isWhitespace(ch)) {
        pad = (ch == '\n') ? '\n' : ' ';
        while( (++i) < n ) {
          ch = cdata.charAt(i);
          if (!Character.isWhitespace(ch)) {
            break;
          }
          if (ch == '\n') {
            pad = '\n';
          }
        }
        buffer.append(pad);
      } else {
        buffer.append(ch);
        i++;
      }
    }
   
    return buffer.toString();
  }



  public static final String pack(String cdata)
  {
    if (cdata.charAt(0) == '<') {
      return cdata;
    }
   
    int length = cdata.length();
   
    int end = length;
   
    for(; end > 0; end--) {
      if (!Character.isWhitespace(cdata.charAt(end-1))) {
        break;
      }
    }
   
    int start = 0;
    for(; start<end; start++) {
      if (!Character.isWhitespace(cdata.charAt(start))) {
        break;
      }
    }
   
    StringBuffer buffer = new StringBuffer(end - start + 1);
    int i = start;
    while(i < end) {
      char ch = cdata.charAt(i);
      if (Character.isWhitespace(ch)) {
        char pad = ' ';
        while(true) {
          if (ch == '\n') {
            pad= '\n';
          }         
          if (i++ >= end) {
            break;
          }
          ch = cdata.charAt(i);
          if (!Character.isWhitespace(ch)) {
            break;
          }
        }
        buffer.append(pad);
      } else {
        buffer.append(ch);
        i++;
      }
    }
   
    return buffer.toString();
  }




  public final String parseLabel(TemplateParser parser, Tag tag)
  {
    String label = tag.getValue("label");
    if (label != null) {
      if (!Grammar.isValidIdentifier(label)) {
        parser.error(getLocation(), "Label '"+label+"' is not a valid identifier");
        return null;
      }
     
      if (allowLabel(label)) {
        parser.error(getLocation(), "Label '"+label+"' is already declared");
        return null;
      }
    }
    return label;
  }


  public int getContentState()
  {
    return getParentStatement().getContentState();
  }


}
TOP

Related Classes of anvil.script.statements.Statement

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.