| /* |
| [The "BSD license"] |
| Copyright (c) 2005-2009 Terence Parr |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| 2. Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| 3. The name of the author may not be used to endorse or promote products |
| derived from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| package org.antlr.runtime.tree; |
| |
| import org.antlr.runtime.Token; |
| import org.antlr.runtime.CommonToken; |
| |
| public class TreePatternParser { |
| protected TreePatternLexer tokenizer; |
| protected int ttype; |
| protected TreeWizard wizard; |
| protected TreeAdaptor adaptor; |
| |
| public TreePatternParser(TreePatternLexer tokenizer, TreeWizard wizard, TreeAdaptor adaptor) { |
| this.tokenizer = tokenizer; |
| this.wizard = wizard; |
| this.adaptor = adaptor; |
| ttype = tokenizer.nextToken(); // kickstart |
| } |
| |
| public Object pattern() { |
| if ( ttype==TreePatternLexer.BEGIN ) { |
| return parseTree(); |
| } |
| else if ( ttype==TreePatternLexer.ID ) { |
| Object node = parseNode(); |
| if ( ttype==TreePatternLexer.EOF ) { |
| return node; |
| } |
| return null; // extra junk on end |
| } |
| return null; |
| } |
| |
| public Object parseTree() { |
| if ( ttype != TreePatternLexer.BEGIN ) { |
| throw new RuntimeException("no BEGIN"); |
| } |
| ttype = tokenizer.nextToken(); |
| Object root = parseNode(); |
| if ( root==null ) { |
| return null; |
| } |
| while ( ttype==TreePatternLexer.BEGIN || |
| ttype==TreePatternLexer.ID || |
| ttype==TreePatternLexer.PERCENT || |
| ttype==TreePatternLexer.DOT ) |
| { |
| if ( ttype==TreePatternLexer.BEGIN ) { |
| Object subtree = parseTree(); |
| adaptor.addChild(root, subtree); |
| } |
| else { |
| Object child = parseNode(); |
| if ( child==null ) { |
| return null; |
| } |
| adaptor.addChild(root, child); |
| } |
| } |
| if ( ttype != TreePatternLexer.END ) { |
| throw new RuntimeException("no END"); |
| } |
| ttype = tokenizer.nextToken(); |
| return root; |
| } |
| |
| public Object parseNode() { |
| // "%label:" prefix |
| String label = null; |
| if ( ttype == TreePatternLexer.PERCENT ) { |
| ttype = tokenizer.nextToken(); |
| if ( ttype != TreePatternLexer.ID ) { |
| return null; |
| } |
| label = tokenizer.sval.toString(); |
| ttype = tokenizer.nextToken(); |
| if ( ttype != TreePatternLexer.COLON ) { |
| return null; |
| } |
| ttype = tokenizer.nextToken(); // move to ID following colon |
| } |
| |
| // Wildcard? |
| if ( ttype == TreePatternLexer.DOT ) { |
| ttype = tokenizer.nextToken(); |
| Token wildcardPayload = new CommonToken(0, "."); |
| TreeWizard.TreePattern node = |
| new TreeWizard.WildcardTreePattern(wildcardPayload); |
| if ( label!=null ) { |
| node.label = label; |
| } |
| return node; |
| } |
| |
| // "ID" or "ID[arg]" |
| if ( ttype != TreePatternLexer.ID ) { |
| return null; |
| } |
| String tokenName = tokenizer.sval.toString(); |
| ttype = tokenizer.nextToken(); |
| if ( tokenName.equals("nil") ) { |
| return adaptor.nil(); |
| } |
| String text = tokenName; |
| // check for arg |
| String arg = null; |
| if ( ttype == TreePatternLexer.ARG ) { |
| arg = tokenizer.sval.toString(); |
| text = arg; |
| ttype = tokenizer.nextToken(); |
| } |
| |
| // create node |
| int treeNodeType = wizard.getTokenType(tokenName); |
| if ( treeNodeType==Token.INVALID_TOKEN_TYPE ) { |
| return null; |
| } |
| Object node; |
| node = adaptor.create(treeNodeType, text); |
| if ( label!=null && node.getClass()==TreeWizard.TreePattern.class ) { |
| ((TreeWizard.TreePattern)node).label = label; |
| } |
| if ( arg!=null && node.getClass()==TreeWizard.TreePattern.class ) { |
| ((TreeWizard.TreePattern)node).hasTextArg = true; |
| } |
| return node; |
| } |
| } |