程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> JSP編譯成Servlet(一)語法樹的生成——語法解析

JSP編譯成Servlet(一)語法樹的生成——語法解析

編輯:關於JSP

JSP編譯成Servlet(一)語法樹的生成——語法解析


一般來說,語句按一定規則進行推導後會形成一個語法樹,這種樹狀結構有利於對語句結構層次的描述。同樣Jaspe對JSP語法解析後也會生成一棵樹,這棵樹各個節點包含了不同的信息,但對於JSP來說解析後的語法樹比較簡單,只有一個父節點和n個子節點。例如node1是表示形如的注釋節點,節點裡面包含了一個表示注釋字符串的屬性;而node2則可能是表示形如<%= a+b %>的表達式節點,節點裡面包含一個表示表達式的屬性,同樣地其他節點可能表示JSP的其他語法,有了這棵樹我們就可以很方便地生成對應的Servlet。

\

現在看看怎樣解析生成這棵樹的,

①首先定義樹數據結構,其中parent指向父節點,nodes是此節點的子節點,且nodes應該是有序的列表,這樣能保證與解析順序一致。另外由於每個節點的屬性不同,Node類只提供公共的部分屬性,對於不同節點其他屬性需要繼承Node額外實現。

public class Node {

private Node parent;

private List nodes;

private String text;

private Attributes attrs;

}

public class RootNode{}

public class CommentNode{}

public class PageNode{}

public class IncludeNode{}

public class TaglibNode{}

②其次需要一個讀取JSP文件的工具類,此工具類主要提供對JSP文件的字符操作,其中有個cursor變量用於表示目前解析位置,主要的方法則包括判斷是否到達文件末尾的hasMoreInput方法,獲取下個字符的nextChar方法,獲取某個范圍內的字符組成的字符串getText方法,匹配是否包含某字符串的matches方法,跳過空格符的skipSpaces方法,以及跳轉到某個字符串的skipUntil方法。有了這些輔助操作就可以開始讀取解析語法了。

public class JspReader{

private int cursor;

public int getCursor(){ return cursor ; }

boolean hasMoreInput(){...}

public int nextChar(){...}

public String getText(int start,int end){...}

boolean matches(String string){...}

int skipSpaces(){...}

int skipUntil(String limit){...}

}

③需要一個JSP語法解析器對JSP進行解析,這裡為了簡單說明只解析注釋語法、<@page .../%>頁面指令、<[email protected]../%>包含指令、<[email protected]../%>標簽指令。假設對index.jsp進行語法解析,匹配到<%--則表示注釋語法,獲取其中的注釋文字並創建commentNode節點作為根節點的子節點,如果匹配到<%@則有三種可能,所以需要進一步解析,即對應頁面指令、包含指令和標簽指令等的解析。最後解析出來的就是如圖所示的一棵語法樹。

public class Parser{

public RootNode parse(){

JspReader reader = new JspReader("index.jsp");

RootNode root = new RootNode();

while (reader.hasMoreInput()) {

if (reader.matches("<%--")) {

int start = reader.getCursor();

reader.skipUntil("--%>");

int end = reader.getCursor();

CommentNode commentNode = new CommentNode ();

commentNode.setText(reader.getText(start, stop));

commentNode.setParent(parent);

parent.getList().add(commentNode);

} else if (reader.matches("<%@")) {

if (reader.matches("page")) {

解析<[email protected]../%>裡面的屬性生成attrs

PageNode pageNode = new PageNode ();

pageNode.setAttributes(attrs);

pageNode.setParent(parent);

parent.getList().add(pageNode);

} else if (reader.matches("include")) {

解析<[email protected]../%>裡面的屬性生成attrs

IncludeNode includeNode = new IncludeNode ();

includeNode.setAttributes(attrs);

includeNode.setParent(parent);

parent.getList().add(includeNode);

} else if (reader.matches("taglib")) {

解析<[email protected]../%>裡面的屬性生成attrs

TaglibNode taglibNode = new TaglibNode ();

taglibNode.setAttributes(attrs);

taglibNode.setParent(parent);

parent.getList().add(taglibNode);

}

}

}

return root;

}

}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved