blob: 19bee276a4ccbbe51c97d246ef49edad5d35d69d [file] [log] [blame]
//===--- Parser.h - C Language Parser ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Parser interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Action.h"
namespace clang {
class DeclSpec;
class Declarator;
class AttributeList;
class Scope;
/// Parser - This implements a parser for the C family of languages. After
/// parsing units of the grammar, productions are invoked to handle whatever has
/// been read.
///
class Parser {
Preprocessor &PP;
/// Tok - The current token we are peeking head. All parsing methods assume
/// that this is valid.
LexerToken Tok;
unsigned short ParenCount, BracketCount, BraceCount;
/// Actions - These are the callbacks we invoke as we parse various constructs
/// in the file. This refers to the common base class between MinimalActions
/// and SemaActions for those uses that don't matter.
Action &Actions;
Scope *CurScope;
Diagnostic &Diags;
public:
Parser(Preprocessor &PP, Action &Actions);
~Parser();
const LangOptions &getLang() const { return PP.getLangOptions(); }
TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
Action &getActions() const { return Actions; }
// Type forwarding. All of these are statically 'void*', but they may all be
// different actual classes based on the actions in place.
typedef Action::ExprTy ExprTy;
typedef Action::StmtTy StmtTy;
typedef Action::DeclTy DeclTy;
typedef Action::TypeTy TypeTy;
// Parsing methods.
/// ParseTranslationUnit - All in one method that initializes parses, and
/// shuts down the parser.
void ParseTranslationUnit();
/// Initialize - Warm up the parser.
///
void Initialize();
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
bool ParseTopLevelDecl(DeclTy*& Result);
/// Finalize - Shut down the parser.
///
void Finalize();
private:
//===--------------------------------------------------------------------===//
// Low-Level token peeking and consumption methods.
//
/// isTokenParen - Return true if the cur token is '(' or ')'.
bool isTokenParen() const {
return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren;
}
/// isTokenBracket - Return true if the cur token is '[' or ']'.
bool isTokenBracket() const {
return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square;
}
/// isTokenBrace - Return true if the cur token is '{' or '}'.
bool isTokenBrace() const {
return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace;
}
/// isTokenStringLiteral - True if this token is a string-literal.
///
bool isTokenStringLiteral() const {
return Tok.getKind() == tok::string_literal ||
Tok.getKind() == tok::wide_string_literal;
}
/// ConsumeToken - Consume the current 'peek token' and lex the next one.
/// This does not work will all kinds of tokens: strings and specific other
/// tokens must be consumed with custom methods below. This returns the
/// location of the consumed token.
SourceLocation ConsumeToken() {
assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
!isTokenBrace() &&
"Should consume special tokens with Consume*Token");
SourceLocation L = Tok.getLocation();
PP.Lex(Tok);
return L;
}
/// ConsumeAnyToken - Dispatch to the right Consume* method based on the
/// current token type. This should only be used in cases where the type of
/// the token really isn't known, e.g. in error recovery.
SourceLocation ConsumeAnyToken() {
if (isTokenParen())
return ConsumeParen();
else if (isTokenBracket())
return ConsumeBracket();
else if (isTokenBrace())
return ConsumeBrace();
else
return ConsumeToken();
}
/// ConsumeParen - This consume method keeps the paren count up-to-date.
///
SourceLocation ConsumeParen() {
assert(isTokenParen() && "wrong consume method");
if (Tok.getKind() == tok::l_paren)
++ParenCount;
else if (ParenCount)
--ParenCount; // Don't let unbalanced )'s drive the count negative.
SourceLocation L = Tok.getLocation();
PP.Lex(Tok);
return L;
}
/// ConsumeBracket - This consume method keeps the bracket count up-to-date.
///
SourceLocation ConsumeBracket() {
assert(isTokenBracket() && "wrong consume method");
if (Tok.getKind() == tok::l_square)
++BracketCount;
else if (BracketCount)
--BracketCount; // Don't let unbalanced ]'s drive the count negative.
SourceLocation L = Tok.getLocation();
PP.Lex(Tok);
return L;
}
/// ConsumeBrace - This consume method keeps the brace count up-to-date.
///
SourceLocation ConsumeBrace() {
assert(isTokenBrace() && "wrong consume method");
if (Tok.getKind() == tok::l_brace)
++BraceCount;
else if (BraceCount)
--BraceCount; // Don't let unbalanced }'s drive the count negative.
SourceLocation L = Tok.getLocation();
PP.Lex(Tok);
return L;
}
/// ConsumeStringToken - Consume the current 'peek token', lexing a new one
/// and returning the token kind. This method is specific to strings, as it
/// handles string literal concatenation, as per C99 5.1.1.2, translation
/// phase #6.
SourceLocation ConsumeStringToken() {
assert(isTokenStringLiteral() &&
"Should only consume string literals with this method");
SourceLocation L = Tok.getLocation();
PP.Lex(Tok);
return L;
}
/// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
/// this helper function matches and consumes the specified RHS token if
/// present. If not present, it emits the specified diagnostic indicating
/// that the parser failed to match the RHS of the token at LHSLoc. LHSName
/// should be the name of the unmatched LHS token. This returns the location
/// of the consumed token.
SourceLocation MatchRHSPunctuation(tok::TokenKind RHSTok,
SourceLocation LHSLoc);
/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
/// input. If so, it is consumed and false is returned.
///
/// If the input is malformed, this emits the specified diagnostic. Next, if
/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
/// returned.
bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag,
const char *DiagMsg = "",
tok::TokenKind SkipToTok = tok::unknown);
//===--------------------------------------------------------------------===//
// Scope manipulation
/// EnterScope - Start a new scope.
void EnterScope(unsigned ScopeFlags);
/// ExitScope - Pop a scope off the scope stack.
void ExitScope();
//===--------------------------------------------------------------------===//
// Diagnostic Emission and Error recovery.
void Diag(SourceLocation Loc, unsigned DiagID,
const std::string &Msg = std::string());
void Diag(const LexerToken &Tok, unsigned DiagID,
const std::string &M = std::string()) {
Diag(Tok.getLocation(), DiagID, M);
}
/// SkipUntil - Read tokens until we get to the specified token, then consume
/// it (unless DontConsume is false). Because we cannot guarantee that the
/// token will ever occur, this skips to the next token, or to some likely
/// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
/// character.
///
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
bool DontConsume = false) {
return SkipUntil(&T, 1, StopAtSemi, DontConsume);
}
bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
bool DontConsume = false) {
tok::TokenKind TokArray[] = {T1, T2};
return SkipUntil(TokArray, 2, StopAtSemi, DontConsume);
}
bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
bool StopAtSemi = true, bool DontConsume = false);
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
DeclTy *ParseExternalDeclaration();
DeclTy *ParseDeclarationOrFunctionDefinition();
DeclTy *ParseFunctionDefinition(Declarator &D);
void ParseKNRParamDeclarations(Declarator &D);
void ParseSimpleAsm();
void ParseAsmStringLiteral();
// Objective-C External Declarations
void ParseObjCAtDirectives();
void ParseObjCAtClassDeclaration(SourceLocation atLoc);
void ParseObjCAtInterfaceDeclaration();
void ParseObjCAtProtocolDeclaration();
void ParseObjCAtImplementationDeclaration();
void ParseObjCAtEndDeclaration();
void ParseObjCAtAliasDeclaration();
void ParseObjCInstanceMethodDeclaration();
void ParseObjCClassMethodDeclaration();
//===--------------------------------------------------------------------===//
// C99 6.5: Expressions.
typedef Action::ExprResult ExprResult;
typedef Action::StmtResult StmtResult;
ExprResult ParseExpression();
ExprResult ParseConstantExpression();
ExprResult ParseAssignmentExpression(); // Expr that doesn't include commas.
ExprResult ParseExpressionWithLeadingIdentifier(const LexerToken &Tok);
ExprResult ParseAssignmentExprWithLeadingIdentifier(const LexerToken &Tok);
ExprResult ParseAssignmentExpressionWithLeadingStar(const LexerToken &Tok);
ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec);
ExprResult ParseCastExpression(bool isUnaryExpression);
ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
ExprResult ParseSizeofAlignofExpression();
ExprResult ParseBuiltinPrimaryExpression();
/// ParenParseOption - Control what ParseParenExpression will parse.
enum ParenParseOption {
SimpleExpr, // Only parse '(' expression ')'
CompoundStmt, // Also allow '(' compound-statement ')'
CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
CastExpr // Also allow '(' type-name ')' <anything>
};
ExprResult ParseParenExpression(ParenParseOption &ExprType, TypeTy *&CastTy,
SourceLocation &RParenLoc);
ExprResult ParseSimpleParenExpression() { // Parse SimpleExpr only.
SourceLocation RParenLoc;
return ParseSimpleParenExpression(RParenLoc);
}
ExprResult ParseSimpleParenExpression(SourceLocation &RParenLoc) {
ParenParseOption Op = SimpleExpr;
TypeTy *CastTy;
return ParseParenExpression(Op, CastTy, RParenLoc);
}
ExprResult ParseStringLiteralExpression();
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
ExprResult ParseCXXCasts();
//===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
ExprResult ParseCXXBoolLiteral();
//===--------------------------------------------------------------------===//
// C99 6.7.8: Initialization.
ExprResult ParseInitializer();
ExprResult ParseInitializerWithPotentialDesignator();
//===--------------------------------------------------------------------===//
// C99 6.8: Statements and Blocks.
StmtResult ParseStatement() { return ParseStatementOrDeclaration(true); }
StmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
StmtResult ParseIdentifierStatement(bool OnlyStatement);
StmtResult ParseCaseStatement();
StmtResult ParseDefaultStatement();
StmtResult ParseCompoundStatement();
StmtResult ParseCompoundStatementBody();
StmtResult ParseIfStatement();
StmtResult ParseSwitchStatement();
StmtResult ParseWhileStatement();
StmtResult ParseDoStatement();
StmtResult ParseForStatement();
StmtResult ParseGotoStatement();
StmtResult ParseContinueStatement();
StmtResult ParseBreakStatement();
StmtResult ParseReturnStatement();
StmtResult ParseAsmStatement();
void ParseAsmOperandsOpt();
//===--------------------------------------------------------------------===//
// C99 6.7: Declarations.
DeclTy *ParseDeclaration(unsigned Context);
DeclTy *ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
void ParseDeclarationSpecifiers(DeclSpec &DS);
void ParseSpecifierQualifierList(DeclSpec &DS);
bool ParseTag(DeclTy *&Decl, unsigned TagType, SourceLocation StartLoc);
void ParseEnumSpecifier(DeclSpec &DS);
void ParseEnumBody(SourceLocation StartLoc, DeclTy *TagDecl);
void ParseStructUnionSpecifier(DeclSpec &DS);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
DeclTy *TagDecl);
bool isDeclarationSpecifier() const;
bool isTypeSpecifierQualifier() const;
TypeTy *ParseTypeName();
AttributeList *ParseAttributes();
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
void ParseDeclarator(Declarator &D);
void ParseDeclaratorInternal(Declarator &D);
void ParseTypeQualifierListOpt(DeclSpec &DS);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseBracketDeclarator(Declarator &D);
};
} // end namespace clang
#endif