/** * jetbrick-template * http://subchen.github.io/jetbrick-template/ * * Copyright 2010-2014 Guoqiang Chen. All rights reserved. * Email: subchen@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrick.template.parser.code; import java.util.HashMap; import java.util.Map; import jetbrick.template.parser.support.TypedKlass; /** * 带作用域的 Code */ public class ScopeCode extends Code { protected final ScopeCode parent; // 父作用域 protected final String indent; protected final Map<String, TypedKlass> symbols; // 定义的符号表 protected Code bodyCode; public ScopeCode(ScopeCode parent, String indent) { this.parent = parent; this.indent = indent; this.symbols = new HashMap<String, TypedKlass>(); } // 查找已经定义的变量类型 public TypedKlass resolve(String name, boolean deep) { TypedKlass klass = symbols.get(name); if (klass != null) { return klass; } if (!deep && this instanceof MethodCode) return null; if (parent != null) { klass = parent.resolve(name, deep); } return klass; } // 尝试在当前作用域下定义一个变量,如果已经定义,则返回 false public boolean define(String name, TypedKlass typedKlass) { return define(name, typedKlass, false); } // 尝试在当前作用域下定义一个变量,如果已经定义,则返回 false public boolean define(String name, TypedKlass typedKlass, boolean isGlobalContext) { if (resolve(name, false) != null) { return false; } symbols.put(name, typedKlass); if (isGlobalContext) { // 注意:不光要当前的作用域定义,也要在Global作用域定义,防止后面重定义 lookupMethodCode().addContext(name, typedKlass); } return true; } /** * 向上查找 MethodCode */ private MethodCode lookupMethodCode() { ScopeCode c = this; while (c != null) { if (c instanceof MethodCode) { return (MethodCode) c; } c = c.parent; } return null; } public ScopeCode push() { return new ScopeCode(this, indent + " "); } public ScopeCode pop() { return parent; } public BlockCode createBlockCode(int initialCapacity) { return new BlockCode(initialCapacity, indent); } public LineCode createLineCode(String source) { return new LineCode(indent + source + "\n"); } public TagCode createTagCode() { return new TagCode(this, indent); } public MacroCode createMacroCode() { return new MacroCode(this); } public void setBodyCode(Code code) { this.bodyCode = code; } @Override public String toString() { return bodyCode.toString(); } }