bool Parser::forward_if_next_is(char c) { bool result = next_is(c); if (result) forward(); return result; }
ParsingResult<ast::Type *> Parser::type() { ParsingResult<ast::Type *> result; ast::Type *result_type = nullptr; StringParsingResult next_identifier = identifier(); if (next_identifier.ok) { if (next_identifier.result == "String") { result_type = new ast::StringType; } if (next_identifier.result == "i32") { result_type = new ast::I32Type; } } if (result_type) { while (next_is('[')) { forward(); // parse digit... if (forward_if_next_is(']')) { ast::ArrayType *array = new ast::ArrayType; array->of.reset(result_type); array->dynamic = true; result_type = array; } } } if (result_type) { result.ok = true; result.result = result_type; } return result; }
std::shared_ptr<Token> Lexer::scan() { skip_whitespace(); switch (peek) { case '=': if (next_is('=')) { return std::make_shared<Word>(Tag::EQUALS, "=="); } else { return std::make_shared<Token>('='); } break; default: break; } // Numbers: [0-9]+(\.[0-9]+f?)? if (isdigit(peek)) { std::stringstream buffer; buffer << peek; while (next() && isdigit(peek)) { buffer << peek; } if (peek == '.') { buffer << peek; while (next() && isdigit(peek)) { buffer << peek; } if (peek == 'f') { return std::make_shared<Word>(Tag::FLOAT, buffer.str()); } else { return std::make_shared<Word>(Tag::DOUBLE, buffer.str()); } } else { if (isalpha(peek)) { if (peek == 'f') { if (next() && isalpha(peek)) { throw "Invalid number at line"; } return std::make_shared<Word>(Tag::FLOAT, buffer.str()); } else { throw "Invalid number"; } } return std::make_shared<Word>(Tag::INTEGER, buffer.str()); } } // Identifiers [a-zA-Z][a-zA-Z0-9]+ if (isalpha(peek)) { std::stringstream buffer; buffer << peek; while (next() && isalnum(peek)) { buffer << peek; } std::string lexeme = buffer.str(); auto iterator = words.find(lexeme); if (iterator != words.end()) { return iterator->second; } else { auto token = std::make_shared<Word>(Tag::IDENTIFIER, lexeme); reserve(token); return token; } } // Strings. auto string = match_string(); if (string != nullptr) { return string; } auto token = std::make_shared<Token>(peek); clean_peek(); return token; }
ParsingResult<ast::Signature *> Parser::signature() { ParsingResult<ast::Signature *> result; StringParsingResult next_identifier = identifier(); if (!next_identifier.ok) return result; skip(); ast::Type *return_type; if (forward_if_next_is('#')) { ParsingResult<ast::Type *> preturn_type = type(); if (!preturn_type) return fail<ast::Signature *>(); return_type = preturn_type.result; } else { return_type = new ast::VoidType(); } skip(); std::vector<std::tuple<std::string, std::string, ast::Type *>> list; bool fallback = false; do { if (fallback) { // We do a loop without consume anything, try to consume one forward(); } fallback = true; std::string ralias; std::string ridentifier; StringParsingResult palias = alias(); if (palias) { skip(); ralias = palias.result; } StringParsingResult pidentifier = identifier(); if (pidentifier) { skip(); ridentifier = pidentifier.result; if (forward_if_next_is('#')) { ParsingResult<ast::Type *> ptype = type(); if (!ptype) throw "An argument in not typed"; list.push_back(std::make_tuple(ralias, ridentifier, ptype.result)); fallback = false; } } skip(); } while (!next_is('{')); ast::Signature *signature = new ast::Signature; signature->identifier = next_identifier.result; signature->ret.reset(return_type); for (const std::tuple<std::string, std::string, ast::Type *> &l : list) { signature->params.emplace_back(); signature->params.back().type.reset(std::get<2>(l)); signature->params.back().alias = std::get<0>(l); signature->params.back().identifier = std::get<1>(l); } result.ok = true; result.result = signature; return result; }