Example #1
0
BlockNode* Parser::parseBlock(bool needBraces, const bool scoped/* = true */) {
    if (needBraces) {
        ensureToken(tLBRACE);
    }

    if (scoped) {
      pushScope();
    }

    BlockNode* block = new BlockNode(_currentTokenIndex,
                                     _currentScope);
    TokenKind sentinel = needBraces ? tRBRACE : tEOF;

     while (currentToken() != sentinel) {
         if (currentToken() == tSEMICOLON) {
             consumeToken();
             continue;
         }
         AstNode* statement = parseStatement();
         // Ignore statements that doesn't result in AST nodes, such
         // as variable or function declaration.
         if (statement != 0) {
             block->add(statement);
         }
     }

    if (scoped) {
      popScope();
    }

     if (needBraces) {
         ensureToken(tRBRACE);
     }

     return block;
}
Example #2
0
FunctionNode* Parser::parseFunction() {
    uint32_t tokenIndex = _currentTokenIndex;
    ensureKeyword("function");

    if (currentToken() != tIDENT) {
        error("identifier expected");
    }
    const string& returnTypeName = currentTokenValue();
    VarType returnType = nameToType(returnTypeName);
    if (returnType == VT_INVALID) {
      error("wrong return type");
    }
    consumeToken();

    if (currentToken() != tIDENT) {
        error("name expected");
    }
    const string& name = currentTokenValue();
    consumeToken();

    Signature signature;
    signature.push_back(SignatureElement(returnType, "return"));

    ensureToken(tLPAREN);
    while (currentToken() != tRPAREN) {
        const string& parameterTypeName = currentTokenValue();
        VarType parameterType = nameToType(parameterTypeName);
        if (parameterType == VT_INVALID) {
            error("wrong parameter type");
        }
        consumeToken();
        const string& parameterName = currentTokenValue();
        if (currentToken() != tIDENT) {
            error("identifier expected");
        }
        consumeToken();
        signature.push_back(SignatureElement(parameterType, parameterName));

        if (currentToken() == tCOMMA) {
            consumeToken();
        }
    }
    ensureToken(tRPAREN);

    BlockNode* body = 0;
    pushScope();
    for (uint32_t i = 1; i < signature.size(); i++) {
      const string& name = signature[i].second;
      VarType type = signature[i].first;
      if (!_currentScope->declareVariable(name, type)) {
          error("Formal \"%s\" already declared", name.c_str());
      }
    }
    if ((currentToken() == tIDENT) && currentTokenValue() == "native") {
      consumeToken();
      if (currentToken() != tSTRING) {
          error("Native name expected, got %s", tokenStr(currentToken()));
      }
      pushScope();
      body = new BlockNode(_currentTokenIndex, _currentScope);
      body->add(new NativeCallNode(tokenIndex, currentTokenValue(), signature));
      consumeToken();
      ensureToken(tSEMICOLON);
      body->add(new ReturnNode(0, 0));
      popScope();
    } else {
      body = parseBlock(true, false);
      if (body->nodes() == 0 ||
          !(body->nodeAt(body->nodes() - 1)->isReturnNode())) {
        body->add(new ReturnNode(0, defaultReturnExpr(returnType)));
      }
    }
    popScope();

    if (_currentScope->lookupFunction(name) != 0) {
        error("Function %s already defined", name.c_str());
    }
    FunctionNode* result = new FunctionNode(tokenIndex, name, signature, body);
    _currentScope->declareFunction(result);

    // We don't add function node into AST.
    return 0;
}