/** * Initialize Table * ================================ * * The following reads in the PEG in the passed filename and converts the * grammar specification into a set of tokens for traversal when parsing other files * according to said grammar. */ void Parser::initializeTable(Scanner& input) { // These regexes are used to read in a custom PEG grammar. // Refer to /grammars/arithmetic.peg for a more thorough explanation // on the grammar. Note all other terms can be manipulated just // by reading in the remainder of a line or reading in words. Regex arrowOperator = Regex::fromPool("pparser-arrow", "\\->"); Regex markedWord = Regex::fromPool("pparser-marked-word", "\\A+'?"); // On any given line, the first two terminals should be the nonterminal // being defined and the arrow operator or we've encountered a comment. while(input.peek() != EOF) { if(input.peek() == PPARSER_COMMENT) { input.readLine(); } else { // First read in nonterminal and find start if possible std::string nonterminal = input.next(markedWord); if(nonterminal.back() == PPARSER_START) { nonterminal.pop_back(); if(start.empty()) { start = nonterminal; } else { throw InvalidGrammar("Multiple starting nonterminals", input.getCurrentState()); } } // Can now read in the arrow operator input.next(arrowOperator); // Rest of line is dedicated to definition table[nonterminal] = std::make_shared<Choices>(input); } } // Must have at least one starting nonterminal if(start.empty()) { throw InvalidGrammar("No starting nonterminal specified"); } }
Inst ExtManager::parseExtInstMnemo(Scanner& scanner, Brigantine& bw, int* vx) const { assert(scanner.peek().kind() == EExtInstName); // Parse mnemo prefix adding suffices until there is an extension which can handle it. // This prefix has the form <vendor>_<extension> string prefix = scanner.scan().text(); while (!isMnemoPrefix(prefix) && scanner.peek().kind() == EExtInstSuff) { prefix += scanner.scan().text(); } // Parse remaining part of instruction mnemo (typically in the form <opcode>_<suff>) if (const Extension* e = getByPrefix(prefix)) return e->parseInstMnemo(prefix, scanner, bw, vx); // Enabled extensions failed to parse this mnemo. // Search for a disabled extension which might have handled it const char* s = 0; for (unsigned i = 0; i < size(); ++i) { if (!isEnabled[i] && (s = extension[i]->matchInstMnemo(prefix)) != 0) { scanner.syntaxError(string("Instruction \"") + s + "\" cannot be used (extension \"" + extension[i]->getName() + "\" is not enabled)"); return Inst(); } } // Extensions (including disabled) cannot handle this mnemo if (!hasEnabled()) scanner.scan(); // show offending token scanner.syntaxError("Undefined instruction"); return Inst(); }