· 7 years ago · Dec 01, 2018, 03:48 PM
1#ifndef PARSER_CPP_
2#define PARSER_CPP_
3
4#include "parser.h"
5
6// parses the input string into database commands
7bool Parser::parse(std::string input) {
8 vector<string> tokens = tokenizer(input);
9
10 if(debug) {
11 cout << "Tokens: ";
12 for(int i = 0; i<tokens.size();i++) cout << "<" << tokens[i] << "> ";
13 cout << endl;
14 }
15
16 if(tokens.size()>0) {
17 string first = tokens[0];
18 consumeTokens(tokens,1);
19
20 if (first=="OPEN") return open_cmd(tokens); // done
21 else if (first=="CLOSE") return close_cmd(tokens); // done
22 else if (first=="WRITE") return write_cmd(tokens); // done
23 else if (first=="EXIT") return exit_cmd(tokens); // done
24 else if (first=="SHOW") return show_cmd(tokens); // done
25 else if (tokens.size()>1&&tokens[0]=="<-") return query(tokens,first);
26
27 else if (first=="CREATE") {
28 if(tokens.size()>1) {
29 string relation_name;
30 if(isIdentifier(tokens[1])) {
31 relation_name = tokens[1];
32 // write the input string to the map
33 commands[relation_name].push_back(input);
34 return create_cmd(tokens);
35 }
36 else {
37 if(debug) cout << "Invalid command, relation name is not an identifier\n";
38 return false;
39 }
40 }
41 else {
42 if(debug) cout << "Invalid command, expected more tokens\n";
43 return false;
44 }
45 }
46 else if (first=="UPDATE") {
47 string relation_name = tokens[0];
48 commands[relation_name].push_back(input);
49 return update_cmd(tokens); // done, except for conditionals
50 }
51 else if (first=="INSERT") {
52 string relation_name = tokens[1];
53 commands[relation_name].push_back(input);
54 return insert_cmd(tokens); // the first case is done
55 }
56 else if (first=="DELETE") {
57 string relation_name;
58 if(tokens.size()>0) {
59 relation_name = tokens[1];
60 commands[relation_name].push_back(input);
61 return delete_cmd(tokens);
62 }
63 else if(debug) {
64 cout << "Command invalid, expected tokens after DELETE";
65 return false;
66 }
67 }
68 else if (first=="DEBUG") {
69 if(tokens[0]=="true"||tokens[0]=="TRUE") setDebug(true);
70 else if(tokens[0]=="false"||tokens[0]=="FALSE") setDebug(false);
71 else return false;
72 if(debug) cout << "\n\nEntered debug mode!\n\n";
73 else cout << "\n\nExited debug mode!\n\n";
74 return true;
75 }
76 else if (debug) {
77 cout << "invalid command/query!\ncommand is " + first + "\n" + "input is \n";
78 for(int i = 0; i<tokens.size();i++) cout << tokens[i] << " ";
79 return false;
80 }
81 }
82}
83
84// opens a relation from a .db file
85bool Parser::open_cmd(vector<string> tokens) {
86 string relation_name;
87
88 // syntax checks
89 if(tokens.size() <= 2 ) {
90 if(isIdentifier(tokens[0])) relation_name = tokens[0];
91 else {
92 if(debug) cout << "Command is invalid, identifier is not valid\n";
93 return false;
94 }
95 if(tokens.size()==2&&tokens[1]==";") if(debug) cout << "Command valid\n";
96 else {
97 if(debug) cout << "Command is invalid, no semi-colon\n";
98 return false;
99 }
100 }
101 else {
102 if(debug) cout << "Command is invalid, too many tokens after OPEN\n";
103 return false;
104 }
105
106 // opens the relation file specified in the command
107 ifstream file;
108 string file_name = relation_name + ".db";
109 file.open(file_name.c_str());
110
111 // structure to store the list of command from the relation file
112 vector<string> command_list;
113
114 // for ( all lines in the file)
115 string line;
116 file.peek();
117 while(!file.eof()) {
118 // read the line in
119 line = "";
120 getline(file,line);
121
122 // write the line to commands for the relation that was opened
123 command_list.push_back(line);
124
125 // parse the line
126 parse(line);
127
128 // sets the eof flag if the end of the file has been reached
129 file.peek();
130 }
131
132 file.close();
133
134 // stores the list of commands for the relation into a map within the parser class
135 if(command_list.size() > 0) commands.insert(pair<string, vector<string> >(relation_name,command_list));
136 return true;
137}
138
139// creates a .db file for a relation
140bool Parser::write_cmd(vector<string> tokens) {
141 // syntax checks
142 if(tokens.size() <= 2 ) {
143 if(isIdentifier(tokens[0])) string relation_name = tokens[0];
144 else {
145 if(debug) cout << "Command is invalid, identifier is not valid\n";
146 return false;
147 }
148 if(tokens.size()==2&&tokens[1]==";") if(debug) cout << "Command valid\n";
149 else {
150 if(debug) cout << "Command is invalid, no semi-colon\n";
151 return false;
152 }
153 }
154 else {
155 if(debug) cout << "Command is invalid, too many tokens after WRITE\n";
156 return false;
157 }
158
159 string relation_name = tokens[0];
160
161 ofstream file;
162 string file_name = relation_name + ".db";
163
164 // checks to see if the relation has any commands
165 // associated with it
166 bool exists = commands.count(relation_name)==1;
167
168 if(exists) {
169 file.open(file_name.c_str());
170 file.close();
171 return true;
172 }
173 else {
174 if(debug) cout << "Command invalid, relation does not exist.";
175 return false;
176 }
177}
178
179// deletes the parser object
180bool Parser::exit_cmd(vector<string> tokens) {
181 if(tokens[0]==";"&&tokens.size()==1) {
182 if(debug) cout << "Command valid\n";
183 //delete this;
184 return true;
185 }
186
187 else if(tokens[0]!=";") if(debug) cout << "Invalid command, expeced a semicolon\n";
188
189 else if(debug) cout << "Invalid command, too many tokens after EXIT\n";
190
191 return false;
192}
193
194// outputs a view or relation to the command line
195bool Parser::show_cmd(vector<string> tokens) {
196
197 if(tokens.size() <= 2 ) {
198 if(isIdentifier(tokens[0])) string relation_name = tokens[0];
199 else {
200 if(debug) cout << "Command is invalid, identifier is not valid\n";
201 return false;
202 }
203 if(tokens.size()==2&&tokens[1]==";"&&debug) cout << "Command valid\n";
204 else {
205 if(debug) cout << "Command is invalid, no semi-colon\n";
206 return false;
207 }
208 }
209 else {
210 if(debug) cout << "Command is invalid, too many tokens after SHOW\n";
211 return false;
212 }
213
214 string relation_name = tokens[0];
215
216 Relation* rel = database->find_relation(relation_name);
217
218 if(rel==NULL) {
219 std::map<std::string, Relation* >::iterator itr = views.find(relation_name);
220 rel = itr->second;
221 if(itr!=views.end()) {
222 cout << *rel;
223 }
224 }
225
226 else {
227 cout << *rel;
228 }
229 return true;
230}
231
232// writes the relation back to a .db file and removes it from the database
233bool Parser::close_cmd(vector<string> tokens) {
234 if(tokens.size() <= 2 ) {
235 if(isIdentifier(tokens[0])) string relation_name = tokens[0];
236 else {
237 if(debug) cout << "Command is invalid, identifier is not valid\n";
238 return false;
239 }
240 if(tokens.size()==2&&tokens[1]==";") {
241 if(debug) cout << "Command valid\n";
242 }
243 else {
244 if(debug) cout << "Command is invalid, no semi-colon\n";
245 return false;
246 }
247 }
248 else {
249 if(debug) cout << "Command is invalid, too many tokens after CLOSE\n";
250 return false;
251 }
252
253 /////////////////////////////////////////////////////////
254 // open the file for the relation
255 string relation_name = tokens[0];
256
257 ofstream file;
258 string file_name = relation_name + ".db";
259
260 file.open(file_name.c_str(), fstream::trunc);
261
262 ////////////////////////////////////////////////////////
263 // write back the contents of commands for that relation
264
265 // retrieve the vector of commands from the commands map, if the relation exists
266 vector<string> command_list;
267
268 bool exists = commands.count(relation_name)==1;
269
270 //cerr << exists << endl;
271 if(exists) command_list = commands[relation_name];
272
273 // write the commands back to the file
274
275 if(!exists) {
276 //cout << "doesnt exist";
277 file.close();
278 remove(file_name.c_str());
279 }
280
281 else if( file.is_open()
282 && file.good())
283 {
284 for(int i = 0; i<command_list.size(); i++) file << command_list[i] << endl;
285 file.close();
286
287 // remove the relation from the database
288 database->delRelation(relation_name);
289
290 return true;
291 }
292}
293
294// creates a relation in the database
295bool Parser::create_cmd(vector<string> tokens) {
296
297 // checks syntax
298 if( tokens[0]=="TABLE"
299 && isIdentifier(tokens[1]))
300 {
301 string relation_name = tokens[1];
302
303 // checks syntax
304 if(tokens[2]=="(") {
305 consumeTokens(tokens,3);
306 vector<Attribute> relation_header;
307
308 // consumes header information until the parentheses are closed
309 while( tokens[0] != ")"
310 && isIdentifier(tokens[0]))
311 {
312 if(tokens[1]=="INTEGER") {
313 relation_header.push_back(std::pair<DATA_TYPE,string>(INTEGER,tokens[0]));
314 consumeTokens(tokens,2);
315 }
316
317 else if(tokens[1]=="FLOAT") {
318 relation_header.push_back(std::pair<DATA_TYPE,string>(FLOAT,tokens[0]));
319 consumeTokens(tokens,2);
320 }
321
322 // if we use the varchar length argument, change the number of consumed tokens to 5
323 else if(tokens[1]=="VARCHAR") {
324 if( tokens[2]=="("
325 && isNumber(tokens[3])
326 && tokens[4]==")") {
327 relation_header.push_back(std::pair<DATA_TYPE,string>(VARCHAR,tokens[0]));
328 consumeTokens(tokens,5);
329 }
330 else if(tokens[2]!="(") {
331 if(debug) cout << "Command is invalid, expected (\n";
332 return false;
333 }
334 else if(tokens[4]!=")") {
335 if(debug) cout << "Command is invalid, expected )\n";
336 return false;
337 }
338 else {
339 if(debug) cout << "Command is invalid, expected integer size\n";
340 return false;
341 }
342 }
343
344 // consumes two tokens if the input is invalid
345 else {
346 consumeTokens(tokens,2);
347 if(debug) cout << "Command is invalid, type not valid\n";
348 return false;
349 }
350 }
351
352 // consumes the closing parentheses
353 consumeTokens(tokens,1);
354
355 vector<string> key_header;
356
357 // checks to see if a primary key is specified
358 if( tokens[0]=="PRIMARY"
359 && tokens[1]=="KEY"
360 && tokens[2]=="(")
361 {
362 consumeTokens(tokens,3);
363 while(tokens[0]!=")") {
364 key_header.push_back(tokens[0]);
365 consumeTokens(tokens,1);
366 }
367 }
368 else {
369 if(debug) cout << "Command invalid, no primary key identified\n";
370 return false;
371 }
372
373 // adds the relation specified by the create command to the database
374 Relation new_relation(relation_header,key_header);
375 if(database->addRelation(relation_name,new_relation)) {
376 if(tokens[tokens.size()-1]==";") {
377 if(debug) cout << "Command valid\n";
378 return true;
379 }
380 else {
381 if(debug) if(debug) cout << "Command invalid, expected semicolon\n";
382 return false;
383 }
384 }
385
386 else {
387 if(debug) cout << "Command invalid, relation already exists\n";
388 return false;
389 }
390
391 tokens.clear();
392 }
393 else {
394 if(debug) cout << "Command is invalid, expected a parentheses after the identifier";
395 return false;
396 }
397 }
398 else if(tokens[0]!="TABLE") {
399 if(debug) cout << "Command is invalid, expected TABLE after CREATE\n";
400 return false;
401 }
402 else {
403 if(debug) cout << "Command is invalid, relation name is not an identifier\n";
404 return false;
405 }
406}
407
408bool Parser::update_cmd(vector<string> tokens) {
409 if(tokens.size()!=0)
410 {
411 string relation_name = tokens[0];
412
413 if(!isIdentifier(relation_name)) {
414 if(debug) cout << "Command invalid, relation name is not an identifer\n";
415 return false;
416 }
417
418 consumeTokens(tokens,1);
419
420 if(tokens[0]=="SET") {
421 consumeTokens(tokens,1);
422 vector<pair<string, string> > update_info;
423 while(tokens[0]!="WHERE") {
424 if( isIdentifier(tokens[0])
425 && tokens[1]=="="
426 && tokens[2]!="WHERE") {
427 update_info.push_back(pair<string, string>(tokens[0], tokens[2]));
428 consumeTokens(tokens,3);
429 }
430 else {
431 if(debug) cout << "Command invalid, attribute conditionals are not valid\n";
432 return false;
433 }
434 }
435
436 Relation* updated_relation = database->find_relation(relation_name);
437
438 if(updated_relation!=NULL) {
439 if(tokens[tokens.size()-1]==";") {
440 if(debug) cout << "Command valid\n";
441
442 // WRITE FUNCTIONALITY HERE
443
444 return true;
445 }
446 else {
447 if(debug) cout << "Command invalid, expected semicolon\n";
448 return false;
449 }
450 }
451
452 else {
453 if(debug) cout << "Command invalid, relation does not exist\n";
454 return false;
455 }
456
457 }
458
459 else {
460 if(debug) cout << "Command invalid, SET expected after relation name\n";
461 return false;
462 }
463 }
464 else {
465 if(debug) cout << "Command invalid, no tokens after UPDATE\n";
466 return false;
467 }
468}
469
470// inserts a relatoin into the database
471bool Parser::insert_cmd(vector<string> tokens) {
472 // syntax check
473 if(tokens.size()!=0&&tokens[0]=="INTO"){
474 string relation_name;
475
476 // syntax check
477 if(tokens.size()>1) relation_name = tokens[1];
478 else {
479 if(debug) cout << "Command invalid, no tokens after INTO\n";
480 return false;
481 }
482
483 consumeTokens(tokens,2);
484
485 // determines which form of the INSERT command is in tokens,
486 // and executes the correct helper function
487 bool isFromRelation = false;
488 for(int i = 0; i<tokens.size(); i++) {
489 if(tokens[i]=="RELATION") isFromRelation=true;
490 }
491 if(isFromRelation) return insert_from(tokens,relation_name);
492 else return insert(tokens,relation_name);
493
494 }
495 else if(tokens.size()==0) {
496 if(debug) cout << "Command invalid, no tokens after INSERT\n";
497 return false;
498 }
499 else {
500 if(debug) cout << "Command invalid, expected INTO after INSERT\n";
501 return false;
502 }
503}
504
505// the addTuple function is not working, it returns false when we insert a tuple
506bool Parser::insert(vector<string> tokens, string relation_name) {
507 if( tokens[0]=="VALUES"
508 && tokens[1]=="FROM"
509 && tokens[2]=="(") {
510 consumeTokens(tokens,3);
511 Tuple newTuple;
512
513 while(tokens[0]!=")") {
514
515 if(tokens[0]=="\""&&tokens[2]=="\"") {
516 newTuple.addVarchar(tokens[1]);
517 consumeTokens(tokens, 3);
518 }
519
520 else if(containsDecimal(tokens[0])) {
521 newTuple.addFloat(::atof(tokens[0].c_str()));
522 consumeTokens(tokens, 1);
523 }
524
525 else {
526 newTuple.addInt(::atoi(tokens[0].c_str()));
527 consumeTokens(tokens, 1);
528 }
529 }
530
531 Relation* insert_relation = database->find_relation(relation_name);
532
533 if(insert_relation!=NULL) {
534 if(tokens[tokens.size()-1]!=";") {
535 if(debug) cout << "Command invalid, expected semicolon\n";
536 return false;
537 }
538 else if(insert_relation->addTuple(newTuple)) {
539 if(debug) cout << "Command valid\n";
540 return true;
541 }
542 else {
543 if(debug) cout << "Command invalid, tuple insertion failed";
544 return false;
545 }
546 }
547
548 else {
549 if(debug) cout << "Command invalid, relation does not exist\n";
550 return false;
551 }
552
553 //if(insert_relation!=NULL) delete insert_relation;
554 //if(debug) cout << " GOT PAST THE DELETE\n";
555 }
556 else {
557 if(debug) cout << "Command invalid, expected VALUES FROM ()\n";
558 return false;
559 }
560}
561
562bool Parser::insert_from(vector<string> tokens, string relation_name) {
563 if(debug) cout << "Command valid.\n";
564 return true;
565}
566
567bool Parser::delete_cmd(vector<string> tokens) {
568 if(tokens.size()>1&&tokens[0]=="FROM") {
569 consumeTokens(tokens,1);
570 string relation_name;
571 if(isIdentifier(relation_name)) relation_name = tokens[0];
572 else
573
574 consumeTokens(tokens,1);
575 if(tokens[0]=="WHERE") {
576 if(tokens[tokens.size()-1]==";")
577 {
578 // WRITE FUNCIONALITY HERE
579 if(debug) cout << "Command valid\n";
580 return true;
581 }
582 else {
583 if(debug) cout << "Command invalid, expected semicolon\n";
584 return false;
585 }
586 }
587 else {
588 if(debug) cout << "Command invalid, expected WHERE after relation name\n";
589 return false;
590 }
591 }
592 else {
593 if(debug) cout << "Command invalid, expected relation name after FROM\n";
594 return false;
595 }
596}
597
598// queries the database with the query stored in tokens,
599// and stores it in the view called view_name
600bool Parser::query(vector<string> tokens, string view_name){
601 if(isIdentifier(view_name)&&tokens[tokens.size()-1]==";") {
602 tokens.pop_back();
603 consumeTokens(tokens,1);
604 // separate into atomic expressions
605 if(atomic_expression(tokens)) {
606 if(debug) cout << "Command valid\n";
607 return true;
608 }
609 else {
610 if(debug) cout << "Invalid command, bad atomic expression\n";
611 return false;
612 }
613 }
614 else if(!isIdentifier(view_name)) {
615 if(debug) cout << "Invalid command, view name is not an identifier\n";
616 return false;
617 }
618 else {
619 if(debug) cout << "Invalid command, expected semicolon\n";
620 return false;
621 }
622}
623
624bool Parser::atomic_expression(vector<string> tokens) {
625
626 if(tokens[0]=="("&&tokens[tokens.size()-1]==")") {
627 consumeTokens(tokens,1);
628 tokens.pop_back();
629 return atomic_expression(tokens);
630 }
631
632 // conditional for project and rename atomic expressions
633 else if(tokens[0]=="project"||tokens[0]=="rename") {
634 if(tokens[1]=="(") {
635 consumeTokens(tokens,2);
636 vector<string> attributes;
637 while(tokens.size()!=0&&tokens[0]!=")") {
638 attributes.push_back(tokens[0]);
639 consumeTokens(tokens,1);
640 }
641 if(tokens.size()==0) {
642 if(debug) cout << "Command not valid, expected an atomic expression after the attribute list\n";
643 return false;
644 }
645 else {
646 consumeTokens(tokens,1);
647 return atomic_expression(tokens);
648 }
649 }
650 else {
651 if(debug) cout << "Command not valid, expected )\n";
652 return false;
653 }
654 }
655
656 // conditional for select atomic expression
657 else if(tokens[0]=="select") {
658 consumeTokens(tokens,1);
659 if(tokens[0]=="(") {
660 consumeTokens(tokens,1);
661 vector<string> conditionals;
662 while(tokens[0]!=")") {
663 conditionals.push_back(tokens[0]);
664 consumeTokens(tokens,1);
665 }
666 if(tokens.size()==0) {
667 if(debug) cout << "Command not valid, expected an atomic expression after the conditional\n";
668 return false;
669 }
670 else if(conditional(conditionals)) {
671 consumeTokens(tokens,1);
672 return atomic_expression(tokens);
673 }
674 else {
675 if(debug) cout << "Command not valid, expected a valid conditional\n";
676 return false;
677 }
678 }
679 else {
680 if(debug) cout << "Command not valid, expected )\n";
681 return false;
682 }
683 }
684
685 // conditional for union, difference, and product
686 else if (isRelationOperator(tokens)!=-1) {
687 int check = isRelationOperator(tokens);
688 vector<string> atom1;
689 vector<string> atom2;
690 //if(debug) cout << "Atom 1: ";
691 for(int i = 0; i<check;i++) {
692 atom1.push_back(tokens[i]);
693 //if(debug) cout << tokens[i] << " ";
694 }
695 //if(debug) cout << "\nAtom 2: ";
696 for(int i = check+1; i<tokens.size(); i++) {
697 atom2.push_back(tokens[i]);
698 //if(debug) cout << tokens[i] <<" ";
699 }
700 //if(debug) cout << endl;
701 return atomic_expression(atom1) && atomic_expression(atom2);
702 }
703
704 else {
705 if(isIdentifier(tokens[0])) return true;
706 else {
707 if(debug) cout << "Command not valid, expected a valid identifer\n";
708 return false;
709 }
710 }
711}
712
713bool Parser::conditional (vector<string> tokens) {
714 int delimiter;
715 int paren_count = 0;
716
717
718 // if redundant surrounding parentheses exists, deletes them
719 if(tokens[0]=="("&&tokens[tokens.size()-1]==")") {
720 paren_count++;
721 for(int i = 1; i<tokens.size(); i++) {
722 if(tokens[i]=="(") paren_count++;
723 else if(tokens[i]==")") paren_count--;
724
725 if(paren_count==0) {
726 if(i==tokens.size()-1) {
727 consumeTokens(tokens,1);
728 tokens.pop_back();
729 //for(int j=0;j<tokens.size();j++) cout << "<" << tokens[j] << "> ";
730 //return true;
731 return conditional(tokens);
732 }
733 else break;
734 }
735
736 }
737 }
738
739 paren_count = 0;
740 vector<string> conditional1;
741 vector<string> conditional2;
742 for(int i = 0; i<tokens.size(); i++) {
743 if(tokens[i]=="(") paren_count++;
744 else if(tokens[i]==")") paren_count--;
745 if( paren_count==0
746 && tokens[i]=="||") {
747 for(int j = 0; j<i; j++) conditional1.push_back(tokens[j]);
748 for(int k = i+1; k<tokens.size(); k++) conditional2.push_back(tokens[k]);
749 return conditional(conditional1) || conditional(conditional2);
750 }
751 }
752
753 paren_count=0;
754 for(int i = 0; i<tokens.size(); i++) {
755 if(tokens[i]=="(") paren_count++;
756 else if(tokens[i]==")") paren_count--;
757 if( paren_count==0
758 && tokens[i]=="&&") {
759 for(int j = 0; j<i; j++) conditional1.push_back(tokens[j]);
760 for(int k = i+1; k<tokens.size(); k++) conditional2.push_back(tokens[k]);
761 return conditional(conditional1) && conditional(conditional2);
762 }
763 }
764
765 for (int i=0;i<tokens.size();++i){
766 cout << tokens[i] << endl;
767
768 }
769
770
771
772 if(tokens.size()==3) {
773 if(debug) cout << "IT WORKED!!!\n";
774 return true;
775 }
776 else {
777 if(debug) cout << "GETTING MORE THAN THREE TOKENS :(\n";
778 return false;
779 }
780}
781
782// determines if the token string contains a relation operator (+, -, or *)
783// if it does, returns the index in the vector of the highest level token
784// if it does not, returns -1
785int Parser::isRelationOperator(vector<string> tokens) {
786 int open_count = 0;
787 int closed_count = 0;
788 int token_count = 0;
789 while(tokens.size()!=0) {
790 if(tokens[0]=="(") {
791 open_count++;
792 consumeTokens(tokens,1);
793 }
794 else if(tokens[0]==")") {
795 closed_count++;
796 consumeTokens(tokens,1);
797 }
798 else if(open_count==closed_count) {
799 if(tokens[0]=="+"||tokens[0]=="-"||tokens[0]=="*")
800 return token_count;
801 else consumeTokens(tokens,1);
802 }
803 token_count++;
804 }
805 return -1;
806}
807
808// helper function to identify if a string contains only alphanumeric characters
809bool Parser::isIdentifier(string ident) {
810 // returns false if the first character is not a letter
811 if(!isalpha(ident[0])) return false;
812
813 for(int i = 0; i<ident.size(); i++) {
814 if(!isalnum(ident[i])&&ident[i]!='_') return false;
815 }
816 return true;
817}
818
819bool Parser::isNumber(string ident) {
820 // returns false if the first character is not a letter
821 for(int i = 0; i<ident.size(); i++) {
822 if(!isdigit(ident[i])) return false;
823 }
824 return true;
825}
826
827bool Parser::containsDecimal(string number) {
828 if(isdigit(number[0])) {
829 for(int i = 0; i<number.size(); i++) {
830 if(number[i]=='.') return true;
831 }
832 return false;
833 }
834}
835
836// consumes the number of tokens specified in num from the tokens vector
837void Parser::consumeTokens(vector<string> &tokens, int num) {
838 for(int i = 0; i<num; i++) {
839 tokens.erase(tokens.begin());
840 }
841 /*
842 cout << "new tokens: ";
843 for(int i = 0; i<tokens.size(); i++) {
844 cout << "<" << tokens[i] << "> ";
845 }
846 */
847}
848
849// testing class, allows you to type a single database command into the command line
850int main() {
851 Parser *p = new Parser();
852 string command="";
853 //p->conditional(tokenizer("(a != b && c < d || e > f)"));
854 while(p!=NULL||command!="exit") {
855 cout << "\nEnter a database command or query >> ";
856 getline(cin, command);
857 p->parse(command);
858
859 }
860 return 0;
861}
862
863#endif