001: /*
002: [The "BSD licence"]
003: Copyright (c) 2005-2007 Terence Parr
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in the
013: documentation and/or other materials provided with the distribution.
014: 3. The name of the author may not be used to endorse or promote products
015: derived from this software without specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.antlr.runtime.tree;
029:
030: import org.antlr.runtime.Token;
031: import org.antlr.runtime.CommonToken;
032:
033: public class TreePatternParser {
034: protected TreePatternLexer tokenizer;
035: protected int ttype;
036: protected TreeWizard wizard;
037: protected TreeAdaptor adaptor;
038:
039: public TreePatternParser(TreePatternLexer tokenizer,
040: TreeWizard wizard, TreeAdaptor adaptor) {
041: this .tokenizer = tokenizer;
042: this .wizard = wizard;
043: this .adaptor = adaptor;
044: ttype = tokenizer.nextToken(); // kickstart
045: }
046:
047: public Object pattern() {
048: if (ttype == TreePatternLexer.BEGIN) {
049: return parseTree();
050: } else if (ttype == TreePatternLexer.ID) {
051: Object node = parseNode();
052: if (ttype == TreePatternLexer.EOF) {
053: return node;
054: }
055: return null; // extra junk on end
056: }
057: return null;
058: }
059:
060: public Object parseTree() {
061: if (ttype != TreePatternLexer.BEGIN) {
062: System.out.println("no BEGIN");
063: return null;
064: }
065: ttype = tokenizer.nextToken();
066: Object root = parseNode();
067: if (root == null) {
068: return null;
069: }
070: while (ttype == TreePatternLexer.BEGIN
071: || ttype == TreePatternLexer.ID
072: || ttype == TreePatternLexer.PERCENT
073: || ttype == TreePatternLexer.DOT) {
074: if (ttype == TreePatternLexer.BEGIN) {
075: Object subtree = parseTree();
076: adaptor.addChild(root, subtree);
077: } else {
078: Object child = parseNode();
079: if (child == null) {
080: return null;
081: }
082: adaptor.addChild(root, child);
083: }
084: }
085: if (ttype != TreePatternLexer.END) {
086: System.out.println("no END");
087: return null;
088: }
089: ttype = tokenizer.nextToken();
090: return root;
091: }
092:
093: public Object parseNode() {
094: // "%label:" prefix
095: String label = null;
096: if (ttype == TreePatternLexer.PERCENT) {
097: ttype = tokenizer.nextToken();
098: if (ttype != TreePatternLexer.ID) {
099: return null;
100: }
101: label = tokenizer.sval.toString();
102: ttype = tokenizer.nextToken();
103: if (ttype != TreePatternLexer.COLON) {
104: return null;
105: }
106: ttype = tokenizer.nextToken(); // move to ID following colon
107: }
108:
109: // Wildcard?
110: if (ttype == TreePatternLexer.DOT) {
111: ttype = tokenizer.nextToken();
112: Token wildcardPayload = new CommonToken(0, ".");
113: TreeWizard.TreePattern node = new TreeWizard.WildcardTreePattern(
114: wildcardPayload);
115: if (label != null) {
116: node.label = label;
117: }
118: return node;
119: }
120:
121: // "ID" or "ID[arg]"
122: if (ttype != TreePatternLexer.ID) {
123: return null;
124: }
125: String tokenName = tokenizer.sval.toString();
126: ttype = tokenizer.nextToken();
127: if (tokenName.equals("nil")) {
128: return adaptor.nil();
129: }
130: String text = tokenName;
131: // check for arg
132: String arg = null;
133: if (ttype == TreePatternLexer.ARG) {
134: arg = tokenizer.sval.toString();
135: text = arg;
136: ttype = tokenizer.nextToken();
137: }
138:
139: // create node
140: int treeNodeType = (Integer) wizard.getTokenType(tokenName);
141: if (treeNodeType == Token.INVALID_TOKEN_TYPE) {
142: return null;
143: }
144: Object node;
145: node = adaptor.create(treeNodeType, text);
146: if (label != null
147: && node.getClass() == TreeWizard.TreePattern.class) {
148: ((TreeWizard.TreePattern) node).label = label;
149: }
150: if (arg != null
151: && node.getClass() == TreeWizard.TreePattern.class) {
152: ((TreeWizard.TreePattern) node).hasTextArg = true;
153: }
154: return node;
155: }
156: }
|