zoukankan      html  css  js  c++  java
  • JSP编译成Servlet(一)语法树的生成——语法解析

    一般来说,语句按一定规则进行推导后会形成一个语法树,这样的树状结构有利于对语句结构层次的描写叙述。相同JasperJSP语法解析后也会生成一棵树,这棵树各个节点包括了不同的信息,但对于JSP来说解析后的语法树比較简单,仅仅有一个父节点和n个子节点。比如node1是表示形如<!-- 字符串 -->的凝视节点,节点里面包括了一个表示凝视字符串的属性;而node2则可能是表示形如<%= a+b %>的表达式节点。节点里面包括一个表示表达式的属性,相同地其它节点可能表示JSP的其它语法,有了这棵树我们就能够非常方便地生成相应的Servlet

     

        如今看看如何解析生成这棵树的,

    ①首先定义树数据结构,当中parent指向父节点,nodes是此节点的子节点,且nodes应该是有序的列表,这样能保证与解析顺序一致。另外因为每一个节点的属性不同,Node类仅仅提供公共的部分属性,对于不同节点其它属性须要继承Node额外实现。

    public class Node {

    private Node parent;

    private List<Node> 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 .../%>页面指令、<%@include.../%>包括指令、<%@taglib.../%>标签指令。

    如果对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")) {

                        解析<%@page.../%>里面的属性生成attrs

                        PageNode pageNode = new PageNode ();

                        pageNode.setAttributes(attrs);

                        pageNode.setParent(parent);

                        parent.getList().add(pageNode);

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

                        解析<%@include.../%>里面的属性生成attrs

                        IncludeNode includeNode = new IncludeNode ();

                        includeNode.setAttributes(attrs);

                        includeNode.setParent(parent);

                        parent.getList().add(includeNode);

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

                        解析<%@taglib.../%>里面的属性生成attrs

                        TaglibNode taglibNode = new TaglibNode ();

                        taglibNode.setAttributes(attrs);

                        taglibNode.setParent(parent);

                        parent.getList().add(taglibNode);

                    }

                }

            }

            return root;

        }

    }



    点击订购作者《Tomcat内核设计剖析》




  • 相关阅读:
    python 文件读写操作(转抄)
    kubernetes之kubeadmin安装部署
    bash之字符串处理(核心重点)
    blocking and nonblocking
    文件格式转换
    解压.asar
    Cocos Creator Editor 编辑器扩展记录
    CocosCreator 警告:Please set node's active instead of rigidbody's enabled
    Unity 垂直翻转位图颜色数据
    CocosCreator 动态设置属性在Properties面板显示/隐藏
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7159575.html
Copyright © 2011-2022 走看看