KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > bnf > Bnf


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.bnf;
6
7 import java.io.ByteArrayInputStream JavaDoc;
8 import java.io.InputStreamReader JavaDoc;
9 import java.io.Reader JavaDoc;
10 import java.sql.ResultSet JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.Random JavaDoc;
15 import java.util.StringTokenizer JavaDoc;
16
17 import org.h2.server.web.DbContextRule;
18 import org.h2.tools.Csv;
19 import org.h2.util.Resources;
20 import org.h2.util.StringUtils;
21
22 public class Bnf {
23     
24     static boolean COMBINE_KEYWORDS;
25     
26     private static final String JavaDoc SEPARATORS = " [](){}|.,\r\n<>:-+*/=<\">!'";
27     private static final long MAX_PARSE_TIME = 100;
28     
29     private Random JavaDoc random;
30     private HashMap JavaDoc ruleMap = new HashMap JavaDoc();
31     private String JavaDoc syntax;
32     private String JavaDoc currentToken;
33     private String JavaDoc[] tokens;
34     private char firstChar;
35     private int index;
36     private Rule lastRepeat;
37     private ArrayList JavaDoc statements;
38     private String JavaDoc currentTopic;
39     
40     /**
41      * Create an instance using the grammar specified in the CSV file.
42      *
43      * @param csv if not specified, the help.csv is used
44      * @return a new instance
45      */

46     public static Bnf getInstance(Reader JavaDoc csv) throws Exception JavaDoc {
47         Bnf bnf = new Bnf();
48         if(csv == null) {
49             byte[] data = Resources.get("/org/h2/res/help.csv");
50             csv = new InputStreamReader JavaDoc(new ByteArrayInputStream JavaDoc(data));
51         }
52         bnf.parse(csv);
53         return bnf;
54     }
55     
56     Bnf() {
57         this.random = new Random JavaDoc();
58         random.setSeed(1);
59     }
60     
61     void addFixedRule(String JavaDoc name, int fixedType) {
62         Rule rule = new RuleFixed(fixedType);
63         addRule(name, 0, "Fixed", rule);
64     }
65     
66     RuleHead addRule(String JavaDoc topic, int id, String JavaDoc section, Rule rule) {
67         RuleHead head = new RuleHead(id, section, topic, rule);
68         if(ruleMap.get(StringUtils.toLowerEnglish(topic)) != null) {
69             throw new Error JavaDoc("already exists: " + topic);
70         }
71         ruleMap.put(StringUtils.toLowerEnglish(topic), head);
72         return head;
73     }
74     
75     public Random JavaDoc getRandom() {
76         return random;
77     }
78
79     public HashMap JavaDoc getRuleMap() {
80         return ruleMap;
81     }
82     
83     public void parse(Reader JavaDoc csv) throws Exception JavaDoc {
84         Rule functions = null;
85         statements = new ArrayList JavaDoc();
86         ResultSet JavaDoc rs = Csv.getInstance().read(csv, null);
87         for(int id=0; rs.next(); id++) {
88             String JavaDoc section = rs.getString("SECTION").trim();
89             if(section.startsWith("System")) {
90                 continue;
91             }
92             String JavaDoc topic = StringUtils.toLowerEnglish(rs.getString("TOPIC").trim());
93             topic = StringUtils.replaceAll(topic, " ", "");
94             topic = StringUtils.replaceAll(topic, "_", "");
95             syntax = rs.getString("SYNTAX").trim();
96             currentTopic = section;
97             if(section.startsWith("Function")) {
98                 int end = syntax.indexOf(':');
99                 syntax = syntax.substring(0, end);
100             }
101             tokens = tokenize();
102             index = 0;
103             Rule rule = parseRule();
104             if(section.startsWith("Command")) {
105                 rule = new RuleList(rule, new RuleElement(";\n\n", currentTopic), false);
106             }
107             RuleHead head = addRule(topic, id, section, rule);
108             if(section.startsWith("Function")) {
109                 if(functions == null) {
110                     functions = rule;
111                 } else {
112                     functions = new RuleList(rule, functions, true);
113                 }
114             } else if(section.startsWith("Commands")) {
115                 statements.add(head);
116             }
117         }
118         addRule("@func@", 0, "Function", functions);
119         addFixedRule("@ymd@", RuleFixed.YMD);
120         addFixedRule("@hms@", RuleFixed.HMS);
121         addFixedRule("@nanos@", RuleFixed.NANOS);
122         addFixedRule("anythingExceptSingleQuote", RuleFixed.ANY_EXCEPT_SINGLE_QUOTE);
123         addFixedRule("anythingExceptDoubleQuote", RuleFixed.ANY_EXCEPT_DOUBLE_QUOTE);
124         addFixedRule("anythingUntilEndOfLine", RuleFixed.ANY_UNTIL_EOL);
125         addFixedRule("anythingUntilEndComment", RuleFixed.ANY_UNTIL_END);
126         addFixedRule("anything", RuleFixed.ANY_WORD);
127         addFixedRule("@hexStart@", RuleFixed.HEXSTART);
128         addFixedRule("@concat@", RuleFixed.CONCAT);
129         addFixedRule("@az_@", RuleFixed.AZ_);
130         addFixedRule("@af@", RuleFixed.AF);
131         addFixedRule("@digit@", RuleFixed.DIGIT);
132     }
133         
134     public String JavaDoc getSyntax(String JavaDoc rule, String JavaDoc syntax) {
135         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(syntax, SEPARATORS, true);
136         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
137         while(tokenizer.hasMoreTokens()) {
138             String JavaDoc s = tokenizer.nextToken();
139             if(s.length() == 1 || StringUtils.toUpperEnglish(s).equals(s)) {
140                 buff.append(s);
141                 continue;
142             }
143             String JavaDoc section = null;
144             int id = -1;
145             for(int i=0; i<s.length(); i++) {
146                 String JavaDoc test = StringUtils.toLowerEnglish(s.substring(i));
147                 RuleHead r = (RuleHead)ruleMap.get(test);
148                 if(r != null) {
149                     id = r.id;
150                     section = r.section;
151                     break;
152                 }
153             }
154             if(id == -1) {
155                 buff.append(s);
156                 continue;
157             }
158             String JavaDoc page = "grammar.html";
159             if(section.startsWith("Data Types")) {
160                 page = "datatypes.html";
161             } else if(section.startsWith("Functions")) {
162                 page = "functions.html";
163             }
164             buff.append("<a HREF=\""+page+"#sql"+id+"\">");
165             buff.append(s);
166             buff.append("</a>");
167         }
168         return buff.toString();
169     }
170     
171     private Rule parseRule() {
172         read();
173         Rule r= parseOr();
174         return r;
175     }
176     
177     private Rule parseOr() {
178         Rule r = parseList();
179         if(firstChar == '|') {
180             read();
181             r = new RuleList(r, parseOr(), true);
182         }
183         lastRepeat = r;
184         return r;
185     }
186     
187     private Rule parseList() {
188         Rule r = parseToken();
189         if(firstChar != '|' && firstChar != ']' && firstChar != '}' && firstChar != 0) {
190             r = new RuleList(r, parseList(), false);
191         }
192         lastRepeat = r;
193         return r;
194     }
195     
196     private Rule parseToken() {
197         Rule r;
198         if((firstChar >= 'A' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'z')) {
199             // r = new RuleElement(currentToken+ " syntax:" + syntax);
200
r = new RuleElement(currentToken, currentTopic);
201         } else if(firstChar == '[') {
202             read();
203             Rule r2 = parseOr();
204             boolean repeat = false;
205             if(r2.last() instanceof RuleRepeat) {
206                 repeat = true;
207             }
208             r = new RuleOptional(r2, repeat);
209             if(firstChar != ']') {
210                 throw new Error JavaDoc("expected ], got " + currentToken + " syntax:" + syntax);
211             }
212         } else if(firstChar == '{') {
213             read();
214             r = parseOr();
215             if(firstChar != '}') {
216                 throw new Error JavaDoc("expected }, got " + currentToken+ " syntax:" + syntax);
217             }
218         } else if("@commadots@".equals(currentToken)) {
219             r = new RuleList(new RuleElement(",", currentTopic), lastRepeat, false);
220             r = new RuleRepeat(r);
221         } else if("@dots@".equals(currentToken)) {
222             r = new RuleRepeat(lastRepeat);
223         } else {
224             r = new RuleElement(currentToken, currentTopic);
225         }
226         lastRepeat = r;
227         read();
228         return r;
229     }
230
231     private void read() {
232         if(index < tokens.length) {
233             currentToken = tokens[index++];
234             firstChar = currentToken.charAt(0);
235         } else {
236             currentToken = "";
237             firstChar = 0;
238         }
239     }
240     
241     private String JavaDoc[] tokenize() {
242         ArrayList JavaDoc list = new ArrayList JavaDoc();
243         syntax = StringUtils.replaceAll(syntax, "yyyy-MM-dd", "@ymd@");
244         syntax = StringUtils.replaceAll(syntax, "hh:mm:ss", "@hms@");
245         syntax = StringUtils.replaceAll(syntax, "nnnnnnnnn", "@nanos@");
246         syntax = StringUtils.replaceAll(syntax, "function", "@func@");
247         syntax = StringUtils.replaceAll(syntax, "0x", "@hexStart@");
248         syntax = StringUtils.replaceAll(syntax, ",...", "@commadots@");
249         syntax = StringUtils.replaceAll(syntax, "...", "@dots@");
250         syntax = StringUtils.replaceAll(syntax, "||", "@concat@");
251         syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@");
252         syntax = StringUtils.replaceAll(syntax, "A-Z|_", "@az_@");
253         syntax = StringUtils.replaceAll(syntax, "a-f", "@af@");
254         syntax = StringUtils.replaceAll(syntax, "A-F", "@af@");
255         syntax = StringUtils.replaceAll(syntax, "0-9", "@digit@");
256         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(syntax, SEPARATORS, true);
257         while(tokenizer.hasMoreTokens()) {
258             String JavaDoc s = tokenizer.nextToken();
259             if(s.length() == 1) {
260                 if(" \r\n".indexOf(s.charAt(0))>=0) {
261                     continue;
262                 }
263             }
264             list.add(s);
265         }
266         return (String JavaDoc[]) list.toArray(new String JavaDoc[0]);
267     }
268
269     public HashMap JavaDoc getNextTokenList(String JavaDoc query) {
270         HashMap JavaDoc next = new HashMap JavaDoc();
271         Sentence sentence = new Sentence();
272         sentence.next = next;
273         sentence.text = query;
274         for(int i=0; i<statements.size(); i++) {
275             RuleHead head = (RuleHead) statements.get(i);
276             if(!head.section.startsWith("Commands")) {
277                 continue;
278             }
279             sentence.max = System.currentTimeMillis() + MAX_PARSE_TIME;
280             head.getRule().addNextTokenList(query, sentence);
281         }
282         return next;
283     }
284
285     public void linkStatements() {
286         HashMap JavaDoc ruleMap = getRuleMap();
287         for(Iterator JavaDoc it = ruleMap.values().iterator(); it.hasNext(); ) {
288             RuleHead r = (RuleHead) it.next();
289             r.getRule().setLinks(ruleMap);
290         }
291     }
292     
293     public void updateTopic(String JavaDoc topic, DbContextRule rule) {
294         topic = StringUtils.toLowerEnglish(topic);
295         RuleHead head = (RuleHead) ruleMap.get(topic);
296         if(head == null) {
297             head = new RuleHead(0, "db", topic, rule);
298             ruleMap.put(topic, head);
299             statements.add(head);
300         } else {
301             head.rule = rule;
302         }
303     }
304     
305     public void updateTopic(String JavaDoc topic, String JavaDoc[] array) {
306         topic = StringUtils.toLowerEnglish(topic);
307         ArrayList JavaDoc list = new ArrayList JavaDoc();
308         for(int i=0; i<array.length; i++) {
309             list.add(new RuleElement(array[i], true, topic));
310         }
311         RuleList rule = new RuleList(list, true);
312         RuleHead head = (RuleHead) ruleMap.get(topic);
313         if(head == null) {
314             head = new RuleHead(0, "db", topic, rule);
315             ruleMap.put(topic, head);
316             statements.add(head);
317         } else {
318             head.rule = rule;
319         }
320     }
321
322     public ArrayList JavaDoc getStatements() {
323         return statements;
324     }
325
326 }
327
Popular Tags