bool Parser::TryParseType(std::string& aOutType) { if (m_lexer.NextToken().id != Lexer::TOK_IDENTIFIER) return false; aOutType = m_lexer.currTok.strId; if (!IsTypeName(aOutType)) return false; if (aOutType == "const" || aOutType == "unsigned" || aOutType == "signed") { std::string properType = ""; if (!TryParseType(properType)) return false; aOutType += " " + properType; return true; } if (m_lexer.PeekToken().id == '<') { m_lexer.NextToken(); // we have a complicated type to deal with. (like std::map<std::string, std::vector<T>>) aOutType += '<'; do { std::string innerType = ""; bool gotInnerType = TryParseType(innerType); // a syntax error occured if (!gotInnerType) return false; aOutType += innerType; m_lexer.NextToken(); if (m_lexer.currTok.id == ',' || m_lexer.currTok.id == '>') aOutType += m_lexer.currTok.id; else return false; // a syntax error ocurred } while (m_lexer.currTok.id == ',' && m_lexer.currTok.id != '>' && m_lexer.currTok.id != Lexer::TOK_EOF); if (m_lexer.currTok.id == Lexer::TOK_EOF) return false; // syntax error if (m_lexer.PeekToken().id == ':') { m_lexer.NextToken(); if (m_lexer.PeekToken().id == ':') { m_lexer.NextToken(); std::string additionalType = ""; if (TryParseType(additionalType)) aOutType += "::" + additionalType; else return false; } else { return false; // syntax error } } } Lexer::Token peekToken = m_lexer.PeekToken(); while (peekToken.id == '&' || peekToken.id == '*') { m_lexer.NextToken(); aOutType += m_lexer.currTok.id; peekToken = m_lexer.PeekToken(); } return true; }
/** * unary-expression: * postfix-expression * unary-operator unary-expression * ( type-name ) unary-expression * sizeof unary-expression * sizeof ( type-name ) * * unary-operator: * ++ -- & * + - ! ~ */ static AstExpression ParseUnaryExpression() { AstExpression expr; int t; switch (CurrentToken) { case TK_INC: case TK_DEC: case TK_BITAND: case TK_MUL: case TK_ADD: case TK_SUB: case TK_NOT: case TK_COMP: CREATE_AST_NODE(expr, Expression); expr->op = UNARY_OP; NEXT_TOKEN; expr->kids[0] = ParseUnaryExpression(); return expr; case TK_LPAREN: /// When current token is (, it may be a type cast expression /// or a primary expression, we need to look ahead one token, /// if next token is type name, the expression is treated as /// a type cast expression; otherwise a primary expresion BeginPeekToken(); t = GetNextToken(); if (IsTypeName(t)) { EndPeekToken(); CREATE_AST_NODE(expr, Expression); expr->op = OP_CAST; NEXT_TOKEN; expr->kids[0] = (AstExpression)ParseTypeName(); Expect(TK_RPAREN); expr->kids[1] = ParseUnaryExpression(); return expr; } else { EndPeekToken(); return ParsePostfixExpression(); } break; case TK_SIZEOF: /// this case hase the same issue with TK_LPAREN case CREATE_AST_NODE(expr, Expression); expr->op = OP_SIZEOF; NEXT_TOKEN; if (CurrentToken == TK_LPAREN) { BeginPeekToken(); t = GetNextToken(); if (IsTypeName(t)) { EndPeekToken(); NEXT_TOKEN; /// In this case, the first kid is not an expression, /// but thanks to both type name and expression have a /// kind member to discriminate them. expr->kids[0] = (AstExpression)ParseTypeName(); Expect(TK_RPAREN); } else { EndPeekToken(); expr->kids[0] = ParseUnaryExpression(); } } else { expr->kids[0] = ParseUnaryExpression(); } return expr; default: return ParsePostfixExpression(); } }