-- added fancybox 1.3.1 to project, initially for showing screenshots. See documentat...
[Bookkeeping.git] / src / com / interrupt / bookkeeping / interpreter / lexer / Main.java
blobbcc3174b9c341d7d3c349d8ed75b0a0959163064
2 package com.interrupt.bookkeeping.interpreter.lexer;
5 import java.util.HashMap;
6 import java.util.Iterator;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
12 import org.apache.log4j.Logger;
14 import com.interrupt.bob.base.BobSystem;
16 import com.interrupt.bob.util.Util;
17 import com.interrupt.bookkeeping.cc.bkell.Bkell;
20 public class Main {
22 private Logger logger = Logger.getLogger(Main.class);
25 Problem 1: This synax is not recursive. Thus one cannot put commands into commands
26 Problem 2: Extracting raw XML from command line is very difficult to
28 -entry [A-Z-az0-9]*
29 -account [A-Za-z0-9]*
30 -journal [A-Za-z0-9]*
31 -name [A-Za-z0-9]*
32 -type [A-Za-z0-9]*
33 -counterWeight [[a-z]{5,6}]*
34 -amount [[0-9]+\.[0-9]+]*
35 -id [A-Z-az0-9]*
36 -entrynum [0-9]*
37 -date [[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}]*
39 (debit[,]?)*
40 (credit[,]?)*
41 (entry[,]?)*
43 create (token -opts(token.literal,...))
44 add ((token) token.literal,...)
45 remove ((token) token.literal,...)
46 reverse ((token) token.literal,...)
47 find (token -opts)
48 load (token -opts)
49 list (token -opts)
50 login
51 logout
52 exit
55 ** After reading user input, the Lexer must pass the below parameters to the Parser.
56 Each command will be processed iteratively, starting from each leaf node to the root command:
57 i) commad ii) token iii) options iv) token.literals
61 public Map symbolMap = new HashMap();
62 public Map commandMap = new HashMap();
65 public static void main(String args[]) {
67 Logger.getLogger(Main.class).debug( "Main Input: "+ args[0] );
69 String opt_entry = "-entry [A-Za-z0-9]*"; // opt.entry
70 String opt_account = "-account [A-Za-z0-9]*"; // opt.account
71 String opt_journal = "-journal [A-Za-z0-9]*"; // opt.journal
72 String opt_name = "-name [A-Za-z0-9]*"; // opt.name
73 String opt_type = "-type [A-Za-z0-9]*"; // opt.type
74 String opt_cweight = "-counterWeight [[a-z]{5,6}]*"; // opt.cweight
75 String opt_amount = "-amount ([0-9]+\\.[0-9]+)*"; // opt.amount
76 String opt_id = "-id [A-Za-z0-9]*"; // opt.id
77 String opt_entrynum = "-entrynum [0-9]*"; // opt.entrynum
78 String opt_date = "-date [[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}]*"; // opt.date
79 String opt_file = "-F [A-Za-z0-9]*"; // opt.file
81 String tok_debit_in = "(debit[,]?)*"; // token.in.debit
82 String tok_credit_in = "(credit[,]?)*"; // token.in.credit
83 String tok_entry_in = "(entry[,]?)*"; // token.in.entry
84 String tok_debit = "debit"; // token.debit
85 String tok_credit = "credit"; // token.credit
86 String tok_entry = "entry"; // token.entry
87 String tok_transaction = "transaction"; // token.transaction
88 String tok_journal = "journal"; // token.journal
89 String tok_account = "account"; // token.account
91 // TODO
92 // we also have to represent XML token literals
95 Main main = new Main();
96 main.symbolMap.put("opt.entry", opt_entry);
97 main.symbolMap.put("opt.account", opt_account);
98 main.symbolMap.put("opt.journal", opt_journal);
99 main.symbolMap.put("opt.name", opt_name);
100 main.symbolMap.put("opt.type", opt_type);
101 main.symbolMap.put("opt.cweight", opt_cweight);
102 main.symbolMap.put("opt.amount", opt_amount);
103 main.symbolMap.put("opt.id", opt_id);
104 main.symbolMap.put("opt.entrynum", opt_entrynum);
105 main.symbolMap.put("opt.date", opt_date);
106 main.symbolMap.put("opt.file", opt_file);
108 main.symbolMap.put("token.debit.in", tok_debit_in);
109 main.symbolMap.put("token.credit.in", tok_credit_in);
110 main.symbolMap.put("token.entry.in", tok_entry_in);
111 main.symbolMap.put("token.debit", tok_debit);
112 main.symbolMap.put("token.credit", tok_credit);
113 main.symbolMap.put("token.entry", tok_entry);
114 main.symbolMap.put("token.transaction", tok_transaction);
115 main.symbolMap.put("token.journal", tok_journal);
116 main.symbolMap.put("token.account", tok_account);
120 /* CREATE Commands
122 String cmd_create_debit = "create \\((${token.debit}){1} " +
123 "(((${opt.entry} ${opt.account} ${opt.amount}){1}|" +
124 "(${opt.id}){1})\\){1}";
126 String cmd_create_credit = "create \\((${token.credit}){1} " +
127 "(((${opt.entry} ${opt.account} ${opt.amount}){1}|" +
128 "(${opt.id}){1})\\){1}";
130 String cmd_create_entry = "create \\((${token.entry}){1} " +
131 "((${opt.entrynum} ${opt.journal} ${opt.date}){1}|" +
132 "(${opt.id}){1}){1} " +
133 "\\(${token.debit.in}|${token.credit.in}\\)\\)";
135 String cmd_create_transaction = "create \\((${token.transaction}){1} " +
136 "((${opt.name}){1}|" +
137 "(${opt.id}){1}){1} " +
138 "\\(${token.entry.in}\\)\\)";
140 String cmd_create_journal = "create \\((${token.journal})* " +
141 "((${opt.name}{1}|" +
142 "(${opt.id}){1}){1} " +
143 "\\(${token}[,]?)*\\)\\)";
145 /*String cmd_create_account = "create \\((${token.account})* " +
146 "((${opt.name}{1}|" +
147 "((${opt.type}{1}|" +
148 "(${opt.cweight}){1}){1} " +
149 "\\(${token}[,]?)*\\)\\)";
152 String cmd_create_account = "create \\(${token.account} "+
153 "((${opt.name}){1} (${opt.type}){1} (${opt.cweight}){1} "+
154 "\\((${token}[,]?)*\\)\\)";
157 String cmd_add = "add \\(\\(\\$\\{token\\})*\\) \\$\\{token\\}[,]?)*\\)";
158 String cmd_remove = "remove \\(\\(\\$\\{token\\})*\\) \\$\\{token\\}[,]?)*\\)";
159 String cmd_reverse = "reverse \\(\\(\\$\\{token\\})*) \\$\\{token\\}[,]?)*\\)";
160 String cmd_find = "find \\(\\$\\{token\\})* \\$\\{opts\\})*\\)";
161 String cmd_load = "load \\(\\$\\{token\\})* \\$\\{opts\\})*\\)";
162 String cmd_list = "list \\(\\$\\{token\\})* \\$\\{opts\\})*\\)";
163 String cmd_login = "login";
164 String cmd_logout = "logout";
165 String cmd_exit = "exit";
167 main.commandMap.put("cmd.create.debit", cmd_create_debit);
168 main.commandMap.put("cmd.create.credit", cmd_create_credit);
169 main.commandMap.put("cmd.create.entry", cmd_create_entry);
170 main.commandMap.put("cmd.create.transaction", cmd_create_transaction);
171 //main.commandMap.put("cmd.create.journal", cmd_create_journal);
172 //main.commandMap.put("cmd.create.account", cmd_create_account);
175 String substitution = "\\$\\{[A-Z-a-z0-9\\.]+\\}";
177 main.testCreateDebit(args[0]);
181 public void testCreateDebit(String input) {
184 /*String regex = "create \\((${token.debit}){1} " +
185 "((${opt.entry} ${opt.account} ${opt.amount}){1}|" +
186 "(${opt.id}){1})\\){1}";
188 String regex = null;
189 Set keyset = this.commandMap.keySet();
190 Iterator keyiterator = keyset.iterator();
191 while(keyiterator.hasNext()) {
193 String rkey = (String)keyiterator.next();
194 regex = (String)this.commandMap.get(rkey);
195 logger.debug("");
196 logger.debug("");
197 logger.debug("NEXT Key["+rkey+"] Pattern["+regex+"]");
200 String regex_sub = "\\$\\{[A-Z-a-z0-9\\.]+\\}";
201 //boolean matches_sub = Pattern.matches( regex_sub, regex );
202 boolean hasMatch = false;
203 Pattern pattern = Pattern.compile(regex_sub);
204 Matcher matcher = pattern.matcher(regex);
206 // find token & option substitutions
207 //logger.debug( "Substitution Matches / count["+matcher.groupCount()+"]: "+ matches_sub );
208 int lastIndex = 0;
209 StringBuffer newRegex = new StringBuffer();
210 int new_start_index = -1;
211 int new_end_index = -1;
212 while(matcher.find()) {
214 hasMatch = true;
216 //logger.debug("");
217 //logger.debug("Next Match / index["+matcher.start()+"]: "+ matcher.group());
219 String interpretable = regex.substring(matcher.start(), matcher.end());
220 String interpreted = Util.getInterpretableName(interpretable);
221 String interpretedPattern = (String)symbolMap.get(interpreted);
222 //logger.debug("Interpreted["+interpreted+"] / InterpretedPattern["+interpretedPattern+"]");
224 // match patterns on token & substitutions
225 Pattern pattern_in = null;
226 Matcher matcher_in = null;
227 if(interpretedPattern != null) {
229 pattern_in = Pattern.compile(interpretedPattern);
230 matcher_in = pattern_in.matcher(input);
232 if(matcher_in.find()) {
235 logger.debug(">>> INPUT["+interpretedPattern+"] / ["+interpretable+"] > Next Match["+matcher_in.group()+"]");
236 //logger.debug("Hmmm ["+regex.substring(matcher.start(), matcher.end())+"] / "+ !")*".equals(regex.substring(matcher.end(), matcher.end() + 2)));
237 if( !")*".equals(interpretedPattern.substring(interpretedPattern.length() - 2, interpretedPattern.length()) )){
239 // start index
240 if( '(' == regex.charAt(matcher.start() - 1) ) {
241 new_start_index = matcher.start() - 1;
243 else {
244 new_start_index = matcher.start();
247 // end index
248 if( "){1}".equals(regex.substring(matcher.end(), matcher.end() + 4))) {
249 new_end_index = matcher.end() + 4;
251 else {
252 new_end_index = matcher.end();
256 else {
258 new_start_index = matcher.start();
259 new_end_index = matcher.end();
262 newRegex.append(regex.substring(lastIndex, new_start_index));
263 newRegex.append(interpretedPattern);
264 lastIndex = new_end_index;
265 //logger.debug(">>> REPLACING in regex["+ newRegex.toString() +"]");
268 else {
271 logger.debug(">>> INPUT ["+interpretedPattern+"] / ["+interpretable+"] > NO MATCH ");
272 //logger.debug("Hmmm ["+regex.substring(matcher.start(), matcher.end())+"] / "+ !")*".equals(regex.substring(matcher.end(), matcher.end() + 2)));
273 if( !")*".equals(interpretedPattern.substring(interpretedPattern.length() - 2, interpretedPattern.length()) )){
275 // start index
276 if( '(' == regex.charAt(matcher.start() - 1) ) {
277 new_start_index = matcher.start() - 1;
279 else {
280 new_start_index = matcher.start();
283 // end index
284 if(
285 "){1}".equals(regex.substring(matcher.end(), matcher.end() + 4))
286 ) {
287 new_end_index = matcher.end() + 4;
289 else {
290 new_end_index = matcher.end();
294 else {
296 new_start_index = matcher.start();
297 new_end_index = matcher.end();
300 newRegex.append(regex.substring(lastIndex, new_start_index));
301 newRegex.append("__no_pattern__");
302 lastIndex = new_end_index;
303 //logger.debug(">>> REPLACING in regex["+ newRegex.toString() +"]");
311 if(hasMatch) {
313 newRegex.append(regex.substring(new_end_index));
314 String regexFinal = newRegex.toString();
315 logger.debug(" >>> FINAL regex["+ regexFinal +"]");
316 logger.debug(" >>> FINAL input["+input+"]");
318 Pattern patternFinal = Pattern.compile(regexFinal);
319 Matcher matcherFinal = patternFinal.matcher(input);
320 logger.debug(" >>> FINAL Matches["+ matcherFinal.matches()+"]");
324 // TODO
325 // now collect i) token ii) options iii) token.literals