【文章內(nèi)容簡介】
ee源代碼中,當(dāng)簡寫的不確定節(jié)點表達跟著一個括號表達式時,可能導(dǎo)致歧義。在那種情況下簡寫必須用完全寫法替代。例如:( ... ) N ( a() )上面表達式邏輯不清,你必須明確的使用條件式: ( ... ) N(true) ( a() ) 注意:節(jié)點描述符表達式不能有副作用,JJTree并沒有指定表達式將被計算多少次。需要注意:節(jié)點聲明可以放到一個非終結(jié)符聲明的后面,例如下面:Void Term() MyTerm:{……}{……}這樣當(dāng)對Term的展開成功時,就會生成一個名字為MyTerm的節(jié)點。也可以放到某個非終結(jié)符的展開的某一段的后面,例如:Void VarList():{…}{ Type (Var (Comma Var)*) list}l 不生成節(jié)點如果不希望jjTree生成以某個非終結(jié)符為根的分析子樹,可以在這個非終結(jié)符后面加一個聲明void。l 缺省的非終結(jié)符的聲明缺省的非終結(jié)符的聲明相當(dāng)于它后面聲明了一個跟它同名的(大寫)節(jié)點,例如:Void Term():{…}{…}相當(dāng)于Void Term()TERM:{…}{…}為了使對非終結(jié)符的處理采用void方式的處理,(缺省為假)。l 終結(jié)符節(jié)點的生成jjTree對于終結(jié)符的處理是不將它作為節(jié)點壓入,為了解決這個問題,我們可以在一個終結(jié)符的后面插入一個節(jié)點聲明,例如:Void A():{…}{ (BB) C()}一個節(jié)點的作用域是它對應(yīng)的非終結(jié)符或它前面控制的串展開時,可以用jjtThis訪問這個節(jié)點。 節(jié)點(Node)對象JJTree定義了一個所有語法分析樹節(jié)點必須實現(xiàn)的接口Node,這個接口定義諸如:設(shè)置節(jié)點的父節(jié)點、增加子節(jié)點、重新獲得子節(jié)點等操作方法。public interface Node { /* 一個節(jié)點成為當(dāng)前節(jié)點后,該方法被調(diào)用,表示可以添加它的孩子節(jié)點*/ public void jjtOpen()。 /** 所有孩子節(jié)點被添加后,調(diào)用該方法 */ public void jjtClose()。 /** 該對方法用來與父節(jié)點發(fā)生關(guān)聯(lián)*/ public void jjtSetParent(Node n)。 public Node jjtGetParent()。 /** 添加一個孩子節(jié)點n到孩子列表 */ public void jjtAddChild(Node n, int i)。 /** 該方法返回一個孩子節(jié)點,孩子自左至右,從0開始數(shù)數(shù),This method */ public Node jjtGetChild(int i)。 /** 返回孩子節(jié)點的數(shù)量 */ int jjtGetNumChildren()。}JJTree可以設(shè)置 “simple” 和 “multi”兩種模式之一。在“simple”[單一]模式下語法分析樹節(jié)點都是“SimpleNode”類型。而在“multi”模式下語法分析樹節(jié)點類型取決于節(jié)點的名字。如果你沒有提供實現(xiàn)“Node”接口的類,JJTree會為你生成一些基于“SimpleNode”的簡單實現(xiàn),你可以修改這個實現(xiàn)以適應(yīng)需求。 類SimpleNode該類實現(xiàn)了Node接口,如果它不存在,自動有JJTree創(chuàng)建。你可以用該類作為一個模版或超類,該類提供了一個遞歸遍歷/傾倒(dump)其節(jié)點和孩子節(jié)點的機制。例如{ ((SimpleNode)()).dump()。 }如果VISITOR選項被設(shè)置,另一個實用的方法是{ public void childrenAccept(MyParserVisitor visitor)。 }這對于實現(xiàn)前序和后序遍歷很有幫助。另一個有用的內(nèi)置 SimpleNode 方法是 jjtGetChild(int)public class SimpleNode implements Node { protected Node parent。 protected Node[] children。 protected int id。 protected eg1 parser。 public SimpleNode(int i) { id = i。 } public SimpleNode(eg1 p, int i) { this(i)。 parser = p。 } public void jjtOpen() { } public void jjtClose() { } public void jjtSetParent(Node n) { parent = n。 } public Node jjtGetParent() { return parent。 } public void jjtAddChild(Node n, int i) { if (children == null) { children = new Node[i + 1]。 } else if (i = ) { Node c[] = new Node[i + 1]。 (children, 0, c, 0, )。 children = c。 } children[i] = n。 } public Node jjtGetChild(int i) { return children[i]。 } public int jjtGetNumChildren() { return (children == null) ? 0 : 。 } /* You can override these two methods in subclasses of SimpleNode to customize the way the node appears when the tree is dumped. If your output uses more than one line you should override toString(String), otherwise overriding toString() is probably all you need to do. */ public String toString() { return [id]。 } public String toString(String prefix) { return prefix + toString()。 } /* Override this method if you want to customize how the node dumps out its children. */ public void dump(String prefix) { (toString(prefix))。 if (children != null) { for (int i = 0。 i 。 ++i) { SimpleNode n = (SimpleNode)children[i]。 if (n != null) { (prefix + )。 } } } }} 節(jié)點作用域和用戶行為 每個節(jié)點都有其作用域。這個作用域內(nèi)的用戶行為可以通過使用特殊標(biāo)志符“jjtThis”來訪問已被創(chuàng)建的節(jié)點。這個標(biāo)志符被隱含的聲明為節(jié)點的類型,這樣此節(jié)點的屬性、方法可以輕易的被訪問。A scope is the expansion unit immediately preceding the node decoration. This can be a parenthesized expression. When the production signature is decorated (perhaps implicitly with the default node), the scope is the entire right hand side of