浏览代码

添加 #returnIf(expr) 指令

James 2 年之前
父节点
当前提交
ff80a70760
共有 2 个文件被更改,包括 44 次插入38 次删除
  1. 25 21
      src/main/java/com/jfinal/template/stat/Parser.java
  2. 19 17
      src/main/java/com/jfinal/template/stat/Symbol.java

+ 25 - 21
src/main/java/com/jfinal/template/stat/Parser.java

@@ -30,29 +30,29 @@ import com.jfinal.template.stat.ast.*;
  * DLRD (Double Layer Recursive Descent) Parser
  */
 public class Parser {
-	
+
 	private static final Token EOF = new Token(Symbol.EOF, -1);
-	
+
 	private int forward = 0;
 	private List<Token> tokenList;
 	private StringBuilder content;
 	private String fileName;
 	private Env env;
-	
+
 	public Parser(Env env, StringBuilder content, String fileName) {
 		this.env = env;
 		this.content = content;
 		this.fileName = fileName;
 	}
-	
+
 	private Token peek() {
 		return tokenList.get(forward);
 	}
-	
+
 	private Token move() {
 		return tokenList.get(++forward);
 	}
-	
+
 	private Token matchPara(Token name) {
 		Token current = peek();
 		if (current.symbol == Symbol.PARA) {
@@ -61,7 +61,7 @@ public class Parser {
 		}
 		throw new ParseException("Can not match the parameter of directive #" + name.value(), getLocation(name.row));
 	}
-	
+
 	private void matchEnd(Token name) {
 		if (peek().symbol == Symbol.END) {
 			move();
@@ -69,7 +69,7 @@ public class Parser {
 		}
 		throw new ParseException("Can not match the #end of directive #" + name.value(), getLocation(name.row));
 	}
-	
+
 	public StatList parse() {
 		EngineConfig ec = env.getEngineConfig();
 		tokenList = new Lexer(content, fileName, ec.getKeepLineBlankDirectives()).scan();
@@ -80,7 +80,7 @@ public class Parser {
 		}
 		return statList;
 	}
-	
+
 	private StatList statList() {
 		List<Stat> statList = new ArrayList<Stat>();
 		while (true) {
@@ -88,22 +88,22 @@ public class Parser {
 			if (stat == null) {
 				break ;
 			}
-			
+
 			if (stat instanceof Define) {
 				env.addFunction((Define)stat);
 				continue ;
 			}
-			
+
 			// 过滤内容为空的 Text 节点,通常是处于两个指令之间的空白字符被移除以后的结果,详见 TextToken.deleteBlankTails()
 			if (stat instanceof Text && ((Text)stat).isEmpty()) {
 				continue ;
 			}
-			
+
 			statList.add(stat);
 		}
 		return new StatList(statList);
 	}
-	
+
 	private Stat stat() {
 		Token name = peek();
 		switch (name.symbol) {
@@ -136,7 +136,7 @@ public class Parser {
 			para = matchPara(name);
 			statList = statList();
 			Stat ret = new If(parseExprList(para), statList, getLocation(name.row));
-			
+
 			Stat current = ret;
 			for (Token elseIfToken=peek(); elseIfToken.symbol == Symbol.ELSEIF; elseIfToken=peek()) {
 				move();
@@ -192,6 +192,10 @@ public class Parser {
 		case RETURN:
 			move();
 			return Return.me;
+		case RETURN_IF:
+			move();
+			para = matchPara(name);
+			return new ReturnIf(parseExprList(para), getLocation(name.row));
 		case ID:
 			Class<? extends Directive> dire = env.getEngineConfig().getDirective(name.value());
 			if (dire == null) {
@@ -201,7 +205,7 @@ public class Parser {
 			move();
 			para = matchPara(name);
 			ret.setExprList(parseExprList(para));
-			
+
 			if (ret.hasEnd()) {
 				statList = statList();
 				ret.setStat(statList.getActualStat());
@@ -220,7 +224,7 @@ public class Parser {
 			move();
 			para = matchPara(name);
 			Switch _switch = new Switch(parseExprList(para), getLocation(name.row));
-			
+
 			CaseSetter currentCaseSetter = _switch;
 			for (Token currentToken=peek(); ; currentToken=peek()) {
 				if (currentToken.symbol == Symbol.CASE) {
@@ -245,18 +249,18 @@ public class Parser {
 					break ;
 				}
 			}
-			
+
 			matchEnd(name);
 			return _switch;
 		default :
 			throw new ParseException("Syntax error: can not match the token: " + name.value(), getLocation(name.row));
 		}
 	}
-	
+
 	private Location getLocation(int row) {
 		return new Location(fileName, row);
 	}
-	
+
 	private Stat createDirective(Class<? extends Directive> dire, Token name) {
 		try {
 			return dire.newInstance();
@@ -264,11 +268,11 @@ public class Parser {
 			throw new ParseException(e.getMessage(), getLocation(name.row), e);
 		}
 	}
-	
+
 	private ExprList parseExprList(Token paraToken) {
 		return new ExprParser((ParaToken)paraToken, env.getEngineConfig(), fileName).parseExprList();
 	}
-	
+
 	private ForCtrl parseForCtrl(Token paraToken) {
 		return new ExprParser((ParaToken)paraToken, env.getEngineConfig(), fileName).parseForCtrl();
 	}

+ 19 - 17
src/main/java/com/jfinal/template/stat/Symbol.java

@@ -23,11 +23,11 @@ import java.util.Map;
  * Symbol
  */
 enum Symbol {
-	
+
 	TEXT("text", false),
-	
+
 	OUTPUT("output", true),
-	
+
 	DEFINE("define", true),
 	CALL("call", true),
 	CALL_IF_DEFINED("callIfDefined", true),
@@ -35,7 +35,7 @@ enum Symbol {
 	SET_LOCAL("setLocal", true),
 	SET_GLOBAL("setGlobal", true),
 	INCLUDE("include", true),
-	
+
 	FOR("for", true),
 	IF("if", true),
 	ELSEIF("elseif", true),
@@ -44,19 +44,20 @@ enum Symbol {
 	CONTINUE("continue", false),
 	BREAK("break", false),
 	RETURN("return", false),
-	
+	RETURN_IF("returnIf", true),
+
 	SWITCH("switch", true),
 	CASE("case", true),
 	DEFAULT("default", false),
-	
+
 	ID("ID", false),				// 标识符:下划线或字母开头 ^[A-Za-z_][A-Za-z0-9_]*$
 	PARA("PARA", false),
-	
+
 	EOF("EOF", false);
-	
+
 	private final String name;
 	private final boolean hasPara;	// 是否有参
-	
+
 	@SuppressWarnings("serial")
 	private static final Map<String, Symbol> keywords = new HashMap<String, Symbol>(64) {{
 		put(Symbol.IF.getName(), IF);
@@ -67,39 +68,40 @@ enum Symbol {
 		put(Symbol.BREAK.getName(), BREAK);
 		put(Symbol.CONTINUE.getName(), CONTINUE);
 		put(Symbol.RETURN.getName(), RETURN);
-		
+		put(Symbol.RETURN_IF.getName(), RETURN_IF);
+
 		put(Symbol.SWITCH.getName(), SWITCH);
 		put(Symbol.CASE.getName(), CASE);
 		put(Symbol.DEFAULT.getName(), DEFAULT);
-		
+
 		put(Symbol.DEFINE.getName(), DEFINE);
 		put(Symbol.SET.getName(), SET);
 		put(Symbol.SET_LOCAL.getName(), SET_LOCAL);
 		put(Symbol.SET_GLOBAL.getName(), SET_GLOBAL);
 		put(Symbol.INCLUDE.getName(), INCLUDE);
 	}};
-	
+
 	private Symbol(String name, boolean hasPara) {
 		this.name = name;
 		this.hasPara = hasPara;
 	}
-	
+
 	public String getName() {
 		return name;
 	}
-	
+
 	public String toString() {
 		return name;
 	}
-	
+
 	boolean hasPara() {
 		return hasPara;
 	}
-	
+
 	boolean noPara() {
 		return !hasPara;
 	}
-	
+
 	public static Symbol getKeywordSym(String name) {
 		return keywords.get(name);
 	}