001: /* Generated By:JJTree: Do not edit this line. JJTParserState.java */
002:
003: package org.apache.velocity.runtime.parser;
004:
005: import org.apache.velocity.runtime.parser.node.Node;
006:
007: class JJTParserState {
008: private java.util.Stack nodes;
009: private java.util.Stack marks;
010:
011: private int sp; // number of nodes on stack
012: private int mk; // current mark
013: private boolean node_created;
014:
015: JJTParserState() {
016: nodes = new java.util.Stack();
017: marks = new java.util.Stack();
018: sp = 0;
019: mk = 0;
020: }
021:
022: /* Determines whether the current node was actually closed and
023: pushed. This should only be called in the final user action of a
024: node scope. */
025: boolean nodeCreated() {
026: return node_created;
027: }
028:
029: /* Call this to reinitialize the node stack. It is called
030: automatically by the parser's ReInit() method. */
031: void reset() {
032: nodes.removeAllElements();
033: marks.removeAllElements();
034: sp = 0;
035: mk = 0;
036: }
037:
038: /* Returns the root node of the AST. It only makes sense to call
039: this after a successful parse. */
040: Node rootNode() {
041: return (Node) nodes.elementAt(0);
042: }
043:
044: /* Pushes a node on to the stack. */
045: void pushNode(Node n) {
046: nodes.push(n);
047: ++sp;
048: }
049:
050: /* Returns the node on the top of the stack, and remove it from the
051: stack. */
052: Node popNode() {
053: if (--sp < mk) {
054: mk = ((Integer) marks.pop()).intValue();
055: }
056: return (Node) nodes.pop();
057: }
058:
059: /* Returns the node currently on the top of the stack. */
060: Node peekNode() {
061: return (Node) nodes.peek();
062: }
063:
064: /* Returns the number of children on the stack in the current node
065: scope. */
066: int nodeArity() {
067: return sp - mk;
068: }
069:
070: void clearNodeScope(Node n) {
071: while (sp > mk) {
072: popNode();
073: }
074: mk = ((Integer) marks.pop()).intValue();
075: }
076:
077: void openNodeScope(Node n) {
078: marks.push(new Integer(mk));
079: mk = sp;
080: n.jjtOpen();
081: }
082:
083: /* A definite node is constructed from a specified number of
084: children. That number of nodes are popped from the stack and
085: made the children of the definite node. Then the definite node
086: is pushed on to the stack. */
087: void closeNodeScope(Node n, int num) {
088: mk = ((Integer) marks.pop()).intValue();
089: while (num-- > 0) {
090: Node c = popNode();
091: c.jjtSetParent(n);
092: n.jjtAddChild(c, num);
093: }
094: n.jjtClose();
095: pushNode(n);
096: node_created = true;
097: }
098:
099: /* A conditional node is constructed if its condition is true. All
100: the nodes that have been pushed since the node was opened are
101: made children of the the conditional node, which is then pushed
102: on to the stack. If the condition is false the node is not
103: constructed and they are left on the stack. */
104: void closeNodeScope(Node n, boolean condition) {
105: if (condition) {
106: int a = nodeArity();
107: mk = ((Integer) marks.pop()).intValue();
108: while (a-- > 0) {
109: Node c = popNode();
110: c.jjtSetParent(n);
111: n.jjtAddChild(c, a);
112: }
113: n.jjtClose();
114: pushNode(n);
115: node_created = true;
116: } else {
117: mk = ((Integer) marks.pop()).intValue();
118: node_created = false;
119: }
120: }
121: }
|