/* * main.cpp * * Created on: Jun 3, 2010 * Author: Peter Goodman * Version: $Id$ */ #include #include #include #include #include #include "peg.h" #define D(x) x int main(int argc, char **argv) { unsigned num_vars(0); unsigned grammar_offset(0); unsigned var_names_offset(0); std::stringstream ss; for(int i(1); (i + 1) < argc; i += 2) { if(0 == strcmp("-num", argv[i])) { ss << argv[i + 1]; ss >> num_vars; } else if(0 == strcmp("-grammar", argv[i])) { grammar_offset = i + 1; } else if(0 == strcmp("-vars", argv[i])) { var_names_offset = i + 1; } } if(0 == num_vars || 0 == grammar_offset || 0 == var_names_offset) { std::cout << "Required Options:\n" << "\t-num : the number of productions.\n" << "\t-grammar : the grammar, encoded as described below.\n" << "\t-vars : comma separated list of var names.\n\n" << "\tThe following grammar:\n" << "\t\tA -> A B / a A / b\n" << "\t\tB -> b B / c\n\n" << "\tWould be formatted as:\n" << "\t\tA:@A @B/a @A/b;@B:b @B c;\n\n"; return 0; } // initialize peg::Grammar grammar; peg::Production *prod(0); peg::Variable **var_by_id = new peg::Variable *[num_vars]; std::vector var_names(num_vars); std::map *> var_by_name; for(unsigned i(0); i < num_vars; ++i) { var_by_id[i] = new peg::Variable(grammar); } // parse, one rule per line unsigned var_id(0); char buffer[1024] = {0}; unsigned buffer_offset(0); std::string prod_name; std::string var_name; char *coded_grammar(0); // parse the var names coded_grammar = argv[var_names_offset]; for(; *coded_grammar; ++var_id) { assert(isalpha(*coded_grammar)); buffer_offset = 0; while(isalpha(*coded_grammar)) { buffer[buffer_offset++] = *coded_grammar++; buffer[buffer_offset] = '\0'; } var_name = buffer; var_by_name[var_name] = var_by_id[var_id]; var_by_id[var_id]->setName(var_name); if(',' == *coded_grammar) { assert(*++coded_grammar); } } // parse the grammar coded_grammar = argv[grammar_offset]; bool at_start_of_rule(false); D( std::cout << "Grammar:\n"; ) for(; *coded_grammar; ) { assert(isalpha(*coded_grammar)); buffer_offset = 0; while(isalpha(*coded_grammar)) { buffer[buffer_offset++] = *coded_grammar++; buffer[buffer_offset] = '\0'; } prod_name = buffer; assert(':' == *coded_grammar++); at_start_of_rule = true; while(*coded_grammar) { // variable if('@' == *coded_grammar) { buffer_offset = 0; ++coded_grammar; while(isalpha(*coded_grammar)) { buffer[buffer_offset++] = *coded_grammar++; buffer[buffer_offset] = '\0'; } var_name = buffer; if(at_start_of_rule) { at_start_of_rule = false; prod = &(*(var_by_name[prod_name]) >> *(var_by_name[var_name])); D( std::cout << '\t' << prod_name << " -> " << var_name; ) } else { *prod << *(var_by_name[var_name]); D( std::cout << " " << var_name; ) } continue; } else if(';' == *coded_grammar) { D( std::cout << '\n'; ) ++coded_grammar; break; } else if(' ' == *coded_grammar) { ++coded_grammar; assert(';' != *coded_grammar); assert('/' != *coded_grammar); assert(isgraph(*coded_grammar)); } else if('/' == *coded_grammar) { at_start_of_rule = true; D( std::cout << '\n'; ) ++coded_grammar; // token } else if(isgraph(*coded_grammar)) { if(at_start_of_rule) { at_start_of_rule = false; prod = &(*(var_by_name[prod_name]) >> *coded_grammar); D( std::cout << '\t' << prod_name << " -> " << *coded_grammar; ) } else { *prod << *coded_grammar; D( std::cout << " " << *coded_grammar; ) } ++coded_grammar; } else { assert(false); } } } D( std::cout << '\n'; ) std::vector user_string; user_string.reserve(1024); while(true) { std::cout << "\n>> "; memset(buffer, 0, 1024 * sizeof(char)); std::cin.getline(buffer, 1023); if('\0' == buffer[0]) { break; } user_string.clear(); for(buffer_offset = 0; buffer[buffer_offset]; ++buffer_offset) { if(isgraph(buffer[buffer_offset])) { user_string.push_back(buffer[buffer_offset]); } } grammar.contains(*(var_by_id[0]), user_string); } // cleanup for(unsigned i(0); i < num_vars; ++i) { delete var_by_id[i]; } delete [] var_by_id; return 0; }