Source code: com/k_int/util/CCL/CCLToRPNParser.java
1 // Title: CCLToRPNParser
2 // @version: $Id: CCLToRPNParser.java,v 1.11 2003/05/09 12:54:44 rob_tice Exp $
3 // Copyright: Copyright (C) 2001, Knowledge Integration Ltd.
4 // @author: Ian Ibbotson ( ian.ibbotson@k-int.com )
5 // Company: KI
6 // Description: Take a CCL string and parse it into an RPN tree.
7 //
8
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2.1 of
13 // the license, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place - Suite
23 // 330, Boston, MA 02111-1307, USA.
24 //
25
26 package com.k_int.util.CCL;
27
28 /**
29 * @author Ian Ibbotson
30 * @version $Id: CCLToRPNParser.java,v 1.11 2003/05/09 12:54:44 rob_tice Exp $
31 */
32
33
34 // Import auxillary Java classes
35 import java.io.*;
36 import java.util.*;
37 import com.k_int.util.RPNQueryRep.*;
38 import com.k_int.util.LoggingFacade.*;
39
40 /**
41 * Simple test of CCL Parser, extends the Base parser and listens for
42 * parse tokens, convert the stream of tokens into prefix notation.
43 *
44 * N.B. This class needs some work... It's still quite clunky and not too intuitive...
45 *
46 */
47
48 public class CCLToRPNParser extends BaseCCLParser
49 {
50 private Stack op_stack = new Stack();
51 private int pos = 0;
52 private RootNode root = null;
53 private Stack rpn_branch_stack = new Stack();
54 private QueryNode current_leaf = null;
55 private LinkedList prefix_list = new LinkedList();
56 private LinkedList postfix_list = new LinkedList();
57 private CCLConfig config = null;
58
59 private static LoggingContext cat = LogContextFactory.getContext("CCLToRPNParser");
60
61 public CCLToRPNParser(Reader r, CCLConfig c)
62 {
63 super (r, c);
64 this.config=c;
65 }
66
67 public RootNode parseCCL()
68 {
69 // Special sentinel so we know when parsing is complete.
70 visitOpenBrace();
71 this.parse();
72 // Special sentinel so we know when parsing is complete.
73 visitCloseBrace();
74
75 prefix_list = CCLHelper.postfixToPrefix(postfix_list);
76
77 cat.debug(prefix_list);
78
79 root = new RootNode();
80 root.setAttrset(config.getDefaultAttrset());
81 rpn_branch_stack.push(root);
82 current_leaf=root.getChild();
83 to_rpn(root);
84
85 // System.out.println("\n\nAt end of parse: "+prefix_list.toString()+"\n\n");
86
87 return root;
88 }
89
90 private void to_rpn (QueryNode parent)
91 {
92 cat.debug("toRpn");
93
94 Object o = prefix_list.get(pos++);
95
96 if ( o instanceof CCLHelper.OpNode )
97 {
98 cat.debug("Processing op node");
99 CCLHelper.OpNode on = (CCLHelper.OpNode) o;
100 QueryNode n = (QueryNode)rpn_branch_stack.peek();
101 ComplexNode complex = parent.expandChild(current_leaf);
102
103 // Different with different ops
104 switch ( on.op )
105 {
106 case CCLLexer.AND:
107 complex.setOp(1);
108 break;
109 case CCLLexer.OR:
110 complex.setOp(2);
111 break;
112 case CCLLexer.NOT:
113 complex.setOp(3);
114 break;
115 }
116
117 rpn_branch_stack.push(complex);
118
119 current_leaf = complex.getLHS();
120 to_rpn(complex);
121
122 current_leaf = complex.getRHS();
123 to_rpn(complex);
124
125 rpn_branch_stack.pop();
126 }
127 else // Assume it's a TermNode
128 {
129 cat.debug("Processing term node");
130 CCLHelper.TermNode tn = (CCLHelper.TermNode) o;
131 AttrPlusTermNode aptn = (AttrPlusTermNode)current_leaf;
132 aptn.setTerm(tn.term);
133
134 // Are there any attributes for this tn
135 if ( ( tn.attrs != null ) && ( tn.attrs.size() > 0 ) )
136 {
137 // Process those qualifiers
138 for (Enumeration e = tn.attrs.elements(); e.hasMoreElements(); )
139 addQualifier((String)e.nextElement(), aptn);
140 }
141 else
142 {
143 // Use the Defaults
144 addQualifier("default", aptn);
145 }
146 }
147 }
148
149 private void addQualifier(String qualifier, AttrPlusTermNode aptn)
150 {
151 Vector v = (Vector)config.lookup(qualifier);
152 if ( v != null )
153 {
154 for(Enumeration e=v.elements(); e.hasMoreElements(); )
155 {
156 ConfigTriple t = ( ConfigTriple ) e.nextElement();
157 aptn.setAttr(t.attrset,
158 new Integer(Integer.parseInt(t.attrtype.toString())),
159 t.attrval);
160 }
161 }
162 else
163 System.err.println("Unable to lookup qualifier \""+qualifier+"\"");
164 }
165
166 public void visitOp(int op)
167 {
168 // Pop any operators of Equal or Higher presidence off the stack
169 while ( ( op_stack.size() > 0 ) &&
170 ( op_stack.peek() instanceof CCLHelper.OpNode ) &&
171 ( ((CCLHelper.OpNode)op_stack.peek()).op >= op ) )
172 postfix_list.addLast(op_stack.pop());
173
174 op_stack.push(new CCLHelper.OpNode(op));
175 }
176
177 public void visitCompleteRestriction(Vector attrs, Object value)
178 {
179 postfix_list.addLast(new CCLHelper.TermNode(value.toString(),attrs));
180 }
181
182 public void visitOpenBrace()
183 {
184 op_stack.push(new CCLHelper.OpenBrace());
185 }
186
187 public void visitCloseBrace()
188 {
189 // Pop everything off the operator stack until we reach a (
190 Object o = op_stack.pop();
191 while ( ( ! ( o instanceof CCLHelper.OpenBrace ) ) && ( op_stack.size() > 0 ) )
192 {
193 postfix_list.addLast(o);
194 o = op_stack.pop();
195 }
196 }
197
198 public boolean isCCLQualifier(String s)
199 {
200 if ( config.lookup(s) != null )
201 return true;
202
203 return false;
204 }
205 }