Package org.lilystudio.smarty4j.statement

Source Code of org.lilystudio.smarty4j.statement.Block

package org.lilystudio.smarty4j.statement;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.lilystudio.smarty4j.Analyzer;
import org.lilystudio.smarty4j.Engine;
import org.lilystudio.smarty4j.Operation;
import org.lilystudio.smarty4j.ParseException;
import org.lilystudio.smarty4j.Template;
import org.lilystudio.smarty4j.TemplateReader;
import org.lilystudio.smarty4j.expression.IExpression;
import org.lilystudio.smarty4j.expression.ObjectExpression;
import org.objectweb.asm.MethodVisitor;

/**
* 区块函数语句节点虚基类,区块函数指的是函数内部包含其它函数或文本,需要拥有结束标签的函数,
* 在模板分析过程中,系统首先调用函数的初始化方法,然后解析函数的参数,
* 然后设置函数的父函数,最后解析函数的内部数据。
*
* @see org.lilystudio.smarty4j.NullWriter
*
* @version 1.0.0, 2010/10/01
* @author 欧阳先伟
* @since Smarty 1.0
*/
public abstract class Block extends Function implements IBlockFunction {

  /** ASM名称 */
  public static final String NAME = Block.class.getName().replace('.', '/');

  /** 函数区块中的全部子语句 */
  protected List<IStatement> children;

  public void addStatement(IStatement child) throws ParseException {
    if (children == null) {
      children = new ArrayList<IStatement>();
    }
    children.add(child);
  }

  @Override
  public void process(Template template, TemplateReader in, String left,
      String right) {
    StringBuilder text = new StringBuilder(64);

    Engine engine = template.getEngine();
    boolean debug = engine.isDebug();
    next: while (true) {
      String line;

      try {
        line = in.readLine();
      } catch (IOException e) {
        // 出现异常的概率极低
        throw new RuntimeException("数据读入异常");
      }

      if (line == null) {
        // 文档已经结束, 如果不是文档函数本身, 则块状函数没有正常结束
        String name = getName();
        if (name == null) {
          try {
            addStatement(new TextStatement(text.toString()));
          } catch (ParseException e) {
            in.addMessage(e);
          }
        } else {
          in.addMessage("没有找到" + name + "的结束标签");
        }
        return;
      }

      try {
        // 对smarty标签进行词法分析
        Object[] words = Analyzer.lexical(line, left, right);
        if (words != null) {
          int size = words.length;
          int wordSize = 2;
          for (int i = 2; i < size;) {
            words[wordSize++] = words[i];
            if (words[i] instanceof ObjectExpression) {
              try {
                i = Analyzer.mergeModifier(engine, template, words, i + 1,
                    size, (ObjectExpression) words[i]);
              } catch (ParseException e) {
                in.addMessage(e);
                continue next;
              }
            } else {
              i++;
            }
          }

          int leftStart = (Integer) words[0];
          int rightEnd = (Integer) words[1];
          text.append(line.substring(0, leftStart));
          // 将当前标签至上一个标签之间的内容设置成文本节点
          addStatement(new TextStatement(text.toString()));
          in.move(leftStart);
          text.setLength(0);
          in.unread(line.substring(rightEnd));
          if (wordSize > 2) {
            Object word2 = words[2];
            // 区块函数的结束标签
            if (Operation.C_DIV == word2) {
              // 结束标签内不能有参数, 必须是{/[NAME]}的方式,
              // 并且结束标签必须与当前块函数相同
              String name = getName();
              Object word3 = words[3];
              if ((wordSize == 4) && word3.equals(name)) {
                return;
              }
              if (name == null) {
                in.addMessage("多余的结束标签");
              } else {
                in.addMessage("错误的结束标签");
              }
            } else {
              // 结束标签没有实质上的处理, 不标记行号,
              // 只要不是结束标签就要标记行号
              if (debug && in.isNewline()) {
                addStatement(new DebugStatement(in.getLineNumber()));
              }
              // smarty的注释语法是两头均为'*'号
              if (Operation.C_MUL == word2) {
                if (wordSize == 3 || Operation.C_MUL != words[wordSize - 1]) {
                  in.addMessage("错误的注释语法");
                }
              } else if (word2 instanceof IExpression) {
                // 如果第一个词是对象表达式, 则是输出语句
                addStatement(new PrintStatement(wordSize > 3 ? Analyzer
                    .mergeExpression(words, 2, wordSize, Operation.OBJECT)
                    : (IExpression) word2));
              } else if (word2 instanceof String) {
                String word = (String) word2;
                // 首个词是字符串, 是函数开始语句
                IFunction function = (IFunction) engine.createNode(word, true);
                function.init(template, word);
                function.syntax(template, words, wordSize);
                if (function.setParent(this)) {
                  addStatement(function);
                }
                function.process(template, in, left, right);
              } else {
                try {
                  addStatement(new PrintStatement(Analyzer.mergeExpression(
                      words, 2, wordSize, Operation.OBJECT)));
                } catch (ParseException e) {
                  in.addMessage("无法识别的语法");
                }
              }
            }
          } else {
            in.addMessage("无法识别的语法");
          }
        } else {
          text.append(line);
        }
      } catch (ParseException e) {
        in.addMessage(e);
      } catch (Exception e) {
        in.addMessage(e.getMessage());
      }
    }
  }

  @Override
  public void scan(Template template) {
    super.scan(template);
    if (children != null) {
      for (IStatement statement : children) {
        statement.scan(template);
      }
    }
  }

  public void parse(MethodVisitor mw, int local,
      Map<String, Integer> variableNames) {
    if (children != null) {
      for (IStatement child : children) {
        child.parse(mw, local, variableNames);
      }
    }
  }
}
TOP

Related Classes of org.lilystudio.smarty4j.statement.Block

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.