void Parser::handle_setvar() { // Assuming an (optional) article here skipOptional(TokenType::Article); // Expecting an (optional) value now skipOptional(TokenType::ValueOf); // Expecting a name OR an (optional) article skipOptional(TokenType::Article); ++current; if(current->type != TokenType::Identifier) error("expecting a name that contains the value", current->line); const std::string name = current->getValue<std::string>(); // Expecting a to now ++current; if(current->type != TokenType::To) error("expecting to after the name", current->line); // Now we need to read an expression and set the name with it program->attach(new Ast::Assignment(name, &data_handler, expression())); }
void Parser::handle_declaration() { skipOptional(TokenType::Article); // Expecting a type identifier (eg. "variable" or "function") ++current; if(current->type != TokenType::Identifier) error("type identifier required in declaration", current->line); const std::string type = current->getValue<std::string>(); // Skip (optional) KnownAs token (eg. "called" or "labeled") skipOptional(TokenType::KnownAs); // Expecting an identifier now ++current; if(current->type != TokenType::Identifier) return error("expecting a name on declaration", current->line); const std::string name = current->getValue<std::string>(); if(type == "variable") return program->attach(new Ast::VarDeclaration(name, &data_handler)); if(type == "function" || type == "subroutine" || type == "procedure") { // TODO (tim#1#): Fix memory leak (premature return in case of error) Ast::FuncDeclaration* decl = new Ast::FuncDeclaration(name, &data_handler); // Possibly read a On (With) token if((current + 1)->type != TokenType::On) return program->attach(decl); current += 2; // Skip Token::On and move to next token // Read "arguments" if(current->type != TokenType::Argument) return error("expecting \"argument\" after on/with", current->line); // Read the actual arguments now while((++current)->type == TokenType::Identifier) decl->addArg(current->getValue<std::string>()); --current; return program->attach(decl); } return error("incorrect type for object in declaration", current->line); }
ParseStatus Parser::parseTuple() { skipExpected(TT_DELIMITER, DL_LPAREN); while(lex[0].type != TT_DELIMITER || lex[0].value != DL_LPAREN) { parseAtom(); // Every atom should be followed by a delimiter. if (lex[0].type != TT_DELIMITER) { assert(false); return PARSE_ERROR; } skipOptional(TT_DELIMITER, DL_COMMA); } return PARSE_OK; }
void Parser::handleFuncImpl() { ++current; // Skip optional "calling" skipOptional(TokenType::Calling); // Expecting the name (id) ++current; if(current->type != TokenType::Identifier) error("type identifier required in function impl.", current->line); const std::string name = current->getValue<std::string>(); TokenStream tokens; readBlock(tokens); program->attach(new Ast::FuncImpl( name, &data_handler, Parser(tokens, data_handler).run() )); }
Ast::UnaryOp* Parser::primary() { ++current; switch(current->type) { case TokenType::String: return new Ast::UnaryOp(new Ast::Literal(Variable(current->getValue<Variable::StringType>()))); case TokenType::Number: return new Ast::UnaryOp(new Ast::Literal(Variable(current->getValue<Variable::NumberType>()))); case TokenType::Article: // We actually expect another primary now // because we allow an optional article before a primary return primary(); case TokenType::Identifier: return new Ast::UnaryOp(new Ast::VarNode(current->getValue<std::string>(), &data_handler)); case TokenType::FuncResult: skipOptional(TokenType::Of); ++current; if(current->type == TokenType::Identifier && current->getValue<std::string>() == "calling"); ++current; return new Ast::UnaryOp(handleFunctionCall()); case TokenType::Operator: { char op = current->getValue<char>(); if(op == '(') { Ast::UnaryOp* uop = new Ast::UnaryOp(expression()); ++current; if(current->getValue<char>() != ')') error("expected ')' after '('", current->line); return uop; } else if(op == '-') return new Ast::UnaryOp(primary(), op); else error("unexpected operator in primary", current->line); } default: error("primary expected", current->line); } return nullptr; }