Beispiel #1
0
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()));
}
Beispiel #2
0
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);

}
Beispiel #3
0
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;
}
Beispiel #4
0
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()
    ));
}
Beispiel #5
0
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;
}