浏览代码

添加 keepLineBlank 支持,支持扩展指令像输出指令一样保留指令所在行前后空白字符以及行尾的字符 '\n'

James 6 年之前
父节点
当前提交
50b2832361
共有 2 个文件被更改,包括 42 次插入36 次删除
  1. 40 34
      src/main/java/com/jfinal/template/stat/Lexer.java
  2. 2 2
      src/main/java/com/jfinal/template/stat/Parser.java

+ 40 - 34
src/main/java/com/jfinal/template/stat/Lexer.java

@@ -18,6 +18,7 @@ package com.jfinal.template.stat;
 
 import java.util.ArrayList;
 import java.util.List;
+import com.jfinal.template.EngineConfig;
 
 /**
  * DKFF(Dynamic Key Feature Forward) Lexer
@@ -27,6 +28,8 @@ class Lexer {
 	static final char EOF = (char)-1;
 	static final int TEXT_STATE_DIAGRAM = 999;
 	
+	EngineConfig config;
+	
 	char[] buf;
 	int state = 0;
 	int lexemeBegin = 0;
@@ -38,7 +41,9 @@ class Lexer {
 	List<Token> tokens = new ArrayList<Token>();
 	String fileName;
 	
-	public Lexer(StringBuilder content, String fileName) {
+	public Lexer(EngineConfig config, StringBuilder content, String fileName) {
+		this.config = config;
+		
 		int len = content.length();
 		buf = new char[len + 1];
 		content.getChars(0, content.length(), buf, 0);
@@ -110,7 +115,7 @@ class Lexer {
 					para = scanPara("");
 					idToken = new Token(Symbol.OUTPUT, beginRow);
 					paraToken = new ParaToken(para, beginRow);
-					return addOutputToken(idToken, paraToken);
+					return addIdParaToken(idToken, paraToken);
 				}
 				if (CharTable.isLetter(peek())) {		// # id
 					state = 10;
@@ -472,31 +477,6 @@ class Lexer {
 		}
 	}
 	
-	// 输出指令不对前后空白与换行进行任何处理,直接调用 tokens.add(...)
-	boolean addOutputToken(Token idToken, Token paraToken) {
-		tokens.add(idToken);
-		tokens.add(paraToken);
-		previousTextToken = null;
-		return prepareNextScan(0);
-	}
-	
-	// 向前看后续是否跟随的是空白 + 换行或者是空白 + EOF,是则表示当前指令后续没有其它有用内容
-	boolean lookForwardLineFeedAndEof() {
-		int forwardBak = forward;
-		int forwardRowBak = forwardRow;
-		for (char c=peek(); true; c=next()) {
-			if (CharTable.isBlank(c)) {
-				continue ;
-			}
-			if (c == '\n' || c == EOF) {
-				return true;
-			}
-			forward = forwardBak;
-			forwardRow = forwardRowBak;
-			return false;
-		}
-	}
-	
 	/**
 	 * 带参指令处于独立行时删除前后空白字符,并且再删除一个后续的换行符
 	 * 处于独立行是指:向前看无有用内容,在前面情况成立的基础之上
@@ -509,32 +489,58 @@ class Lexer {
 		tokens.add(idToken);
 		tokens.add(paraToken);
 		
+		// 保留指令所在行空白字符
+		if (config.isKeepLineBlank(idToken.value())) {
+			prepareNextScan(0);
+		} else {
+			trimLineBlank();
+		}
+		
+		previousTextToken = null;
+		return true;
+	}
+	
+	// #set 这类指令,处在独立一行时,需要删除当前行的前后空白字符以及行尾字符 '\n'
+	void trimLineBlank() {
 		// if (lookForwardLineFeed() && (deletePreviousTextTokenBlankTails() || lexemeBegin == 0)) {
 		if (lookForwardLineFeedAndEof() && deletePreviousTextTokenBlankTails()) {
 			prepareNextScan(peek() != EOF ? 1 : 0);
 		} else {
 			prepareNextScan(0);
 		}
-		previousTextToken = null;
-		return true;
 	}
 	
 	// 处理前后空白的逻辑与 addIdParaToken() 基本一样,仅仅多了一个对于紧随空白的 next() 操作
 	boolean addNoParaToken(Token noParaToken) {
 		tokens.add(noParaToken);
+		
 		if (CharTable.isBlank(peek())) {
 			next();	// 无参指令之后紧随的一个空白字符仅为分隔符,不参与后续扫描
 		}
 		
-		if (lookForwardLineFeedAndEof() && deletePreviousTextTokenBlankTails()) {
-			prepareNextScan(peek() != EOF ? 1 : 0);
-		} else {
-			prepareNextScan(0);
-		}
+		trimLineBlank();
+		
 		previousTextToken = null;
 		return true;
 	}
 	
+	// 向前看后续是否跟随的是空白 + 换行或者是空白 + EOF,是则表示当前指令后续没有其它有用内容
+	boolean lookForwardLineFeedAndEof() {
+		int forwardBak = forward;
+		int forwardRowBak = forwardRow;
+		for (char c=peek(); true; c=next()) {
+			if (CharTable.isBlank(c)) {
+				continue ;
+			}
+			if (c == '\n' || c == EOF) {
+				return true;
+			}
+			forward = forwardBak;
+			forwardRow = forwardRowBak;
+			return false;
+		}
+	}
+	
 	/**
 	 * 1:当前指令前方仍然是指令 (previousTextToken 为 null),直接返回 true
 	 * 2:当前指令前方为 TextToken 时的处理逻辑与返回值完全依赖于 TextToken.deleteBlankTails()

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

@@ -71,7 +71,7 @@ public class Parser {
 	}
 	
 	public StatList parse() {
-		tokenList = new Lexer(content, fileName).scan();
+		tokenList = new Lexer(env.getEngineConfig(), content, fileName).scan();
 		tokenList.add(EOF);
 		StatList statList = statList();
 		if (peek() != EOF) {
@@ -207,11 +207,11 @@ public class Parser {
 				matchEnd(name);
 			}
 			return ret;
+		case EOF:
 		case PARA:
 		case ELSEIF:
 		case ELSE:
 		case END:
-		case EOF:
 		case CASE:
 		case DEFAULT:
 			return null;