James 7 年 前
コミット
f4d2c03dd0

+ 72 - 0
src/main/java/com/jfinal/template/stat/ast/Case.java

@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2011-2019, James Zhan 詹波 (jfinal@126.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 com.jfinal.template.stat.ast;
+
+import com.jfinal.template.Env;
+import com.jfinal.template.TemplateException;
+import com.jfinal.template.expr.ast.ExprList;
+import com.jfinal.template.io.Writer;
+import com.jfinal.template.stat.Location;
+import com.jfinal.template.stat.ParseException;
+import com.jfinal.template.stat.Scope;
+
+/**
+ * Case
+ */
+public class Case extends Stat implements CaseSetter {
+	
+	private ExprList exprList;
+	private Stat stat;
+	private Case nextCase;
+	
+	public Case(ExprList exprList, StatList statList, Location location) {
+		if (exprList.length() == 0) {
+			throw new ParseException("The parameter of #case directive can not be blank", location);
+		}
+		
+		this.exprList = exprList;
+		this.stat = statList.getActualStat();
+	}
+	
+	public void setNextCase(Case nextCase) {
+		this.nextCase = nextCase;
+	}
+	
+	public void exec(Env env, Scope scope, Writer writer) {
+		throw new TemplateException("#case 指令的 exec 不能被调用", location);
+	}
+	
+	boolean execIfMatch(Object switchValue, Env env, Scope scope, Writer writer) {
+		Object[] valueArray = exprList.evalExprList(scope);
+		
+		for (Object value : valueArray) {
+			if (value == switchValue) {
+				stat.exec(env, scope, writer);
+				return true;
+			}
+			
+			if (value != null && value.equals(switchValue)) {
+				stat.exec(env, scope, writer);
+				return true;
+			}
+		}
+		
+		return nextCase != null ? nextCase.execIfMatch(switchValue, env, scope, writer) : false;
+	}
+}
+
+

+ 24 - 0
src/main/java/com/jfinal/template/stat/ast/CaseSetter.java

@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2011-2019, James Zhan 詹波 (jfinal@126.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 com.jfinal.template.stat.ast;
+
+/**
+ * CaseSetter
+ */
+public interface CaseSetter {
+	public void setNextCase(Case nextCase);
+}

+ 39 - 0
src/main/java/com/jfinal/template/stat/ast/Default.java

@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2011-2019, James Zhan 詹波 (jfinal@126.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 com.jfinal.template.stat.ast;
+
+import com.jfinal.template.Env;
+import com.jfinal.template.io.Writer;
+import com.jfinal.template.stat.Scope;
+
+/**
+ * Default
+ * 
+ * #switch 指令内部的 #default 指令
+ */
+public class Default extends Stat {
+	
+	private Stat stat;
+	
+	public Default(StatList statList) {
+		this.stat = statList.getActualStat();
+	}
+	
+	public void exec(Env env, Scope scope, Writer writer) {
+		stat.exec(env, scope, writer);
+	}
+}

+ 105 - 0
src/main/java/com/jfinal/template/stat/ast/Switch.java

@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2011-2019, James Zhan 詹波 (jfinal@126.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 com.jfinal.template.stat.ast;
+
+import com.jfinal.template.Env;
+import com.jfinal.template.expr.ast.Expr;
+import com.jfinal.template.expr.ast.ExprList;
+import com.jfinal.template.io.Writer;
+import com.jfinal.template.stat.Location;
+import com.jfinal.template.stat.ParseException;
+import com.jfinal.template.stat.Scope;
+
+/**
+ * Switch
+ * 
+ * #switch 指令与 Java 12 switch 新特性的设计相似: http://openjdk.java.net/jeps/325
+ * 
+ * 在与 java 老版本指令基本用法相同的基础上,主要变化与特性有:
+ * 1: 移除 java 语法中的 fall-through semantics,即不需要 break 关键字进行断开
+ * 2: 不引入 #break 指令,代码更少、更优雅
+ * 3: #case 参数可使用多个用逗号分隔的表达式,每个表达式求值后与 #switch 参数求值后比较,
+ *    从根本上消除了 #break 指令的必要性
+ * 4: #case 支持任意类型数据与表达式(java 语言只支持少数常量类型)
+ * 
+ * <pre>
+ * 示例:
+ *   #switch (v)
+ *      #case (1, 2, 3)
+ *         ...
+ *      #case (999)
+ *         ...
+ *      #case (expr)
+ *         ...
+ *      #default
+ *         ...
+ *   #end
+ * 
+ * 如上所示,#case 指令中可以用逗号分隔开多个值,上述逗号表达式的值 1、2、3 只要
+ * 有一个与 switch 指定的参数 v 相等的话,该 case 分支就会被执行
+ * 
+ * 上述代码中的第三个 #case 指令中使用了 expr,也就是说 #case 指令除了支持常量以外
+ * 还支持表达式
+ * </pre>
+ */
+public class Switch extends Stat implements CaseSetter {
+	
+	private Expr expr;
+	private Case nextCase;
+	private Default _default;
+	
+	public Switch(ExprList exprList, Location location) {
+		if (exprList.length() == 0) {
+			throw new ParseException("The parameter of #switch directive can not be blank", location);
+		}
+		this.expr = exprList.getActualExpr();
+	}
+	
+	public void setNextCase(Case nextCase) {
+		this.nextCase = nextCase;
+	}
+	
+	public void setDefault(Default _default, Location location) {
+		if (this._default != null) {
+			throw new ParseException("The #default case of #switch directive is already defined", location);
+		}
+		this._default = _default;
+	}
+	
+	public void exec(Env env, Scope scope, Writer writer) {
+		Object switchValue = expr.eval(scope);
+		
+		if (nextCase != null && nextCase.execIfMatch(switchValue, env, scope, writer)) {
+			return ;
+		}
+		
+		if (_default != null) {
+			_default.exec(env, scope, writer);
+		}
+	}
+	
+	public boolean hasEnd() {
+		return true;
+	}
+}
+
+
+
+
+
+
+