Add AST nodes and actions for paren exprs and simple unary ops.

llvm-svn: 38940
This commit is contained in:
Chris Lattner 2006-08-23 06:42:10 +00:00
parent 9b6d4cb90e
commit 1b92649857
7 changed files with 339 additions and 7 deletions

121
clang/AST/Expr.cpp Normal file
View File

@ -0,0 +1,121 @@
//===--- Expr.cpp - Expression AST Node Implementation --------------------===//
//
// 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 implements the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Expr.h"
#include <iostream>
using namespace llvm;
using namespace clang;
void Expr::dump() const {
if (this == 0)
std::cerr << "<null expr>";
else
dump_impl();
}
void IntegerConstant::dump_impl() const {
std::cerr << "1";
}
void FloatingConstant::dump_impl() const {
std::cerr << "1.0";
}
void ParenExpr::dump_impl() const {
std::cerr << "'('";
Val->dump();
std::cerr << "')'";
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++".
const char *UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
default: assert(0 && "Unknown binary operator");
case PostInc: return "[post]++";
case PostDec: return "[post]--";
case PreInc: return "[pre]++";
case PreDec: return "[pre]--";
case AddrOf: return "&";
case Deref: return "*";
case Plus: return "+";
case Minus: return "-";
case Not: return "~";
case LNot: return "!";
case Real: return "__real";
case Imag: return "__imag";
}
}
void UnaryOperator::dump_impl() const {
std::cerr << "(" << getOpcodeStr(Opc);
Input->dump();
std::cerr << ")";
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
default: assert(0 && "Unknown binary operator");
case Mul: return "*";
case Div: return "/";
case Rem: return "%";
case Add: return "+";
case Sub: return "-";
case Shl: return "<<";
case Shr: return ">>";
case LT: return "<";
case GT: return ">";
case LE: return "<=";
case GE: return ">=";
case EQ: return "==";
case NE: return "!=";
case And: return "&";
case Xor: return "^";
case Or: return "|";
case LAnd: return "&&";
case LOr: return "||";
case Assign: return "=";
case MulAssign: return "*=";
case DivAssign: return "/=";
case RemAssign: return "%=";
case AddAssign: return "+=";
case SubAssign: return "-=";
case ShlAssign: return "<<=";
case ShrAssign: return ">>=";
case AndAssign: return "&=";
case XorAssign: return "^=";
case OrAssign: return "|=";
case Comma: return ",";
}
}
void BinaryOperator::dump_impl() const {
std::cerr << "(";
LHS->dump();
std::cerr << " " << getOpcodeStr(Opc) << " ";
RHS->dump();
std::cerr << ")";
}
void ConditionalOperator::dump_impl() const {
std::cerr << "(";
Cond->dump();
std::cerr << " ? ";
LHS->dump();
std::cerr << " : ";
RHS->dump();
std::cerr << ")";
}

View File

@ -40,10 +40,17 @@ public:
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
// Primary Expressions.
virtual ExprTy *ParseIntegerConstant(const LexerToken &Tok);
virtual ExprTy *ParseFloatingConstant(const LexerToken &Tok);
virtual ExprTy *ParseParenExpr(SourceLocation L, SourceLocation R,
ExprTy *Val);
// Binary/Unary Operators. 'Tok' is the token for the operator.
virtual ExprTy *ParseUnaryOp(const LexerToken &Tok, ExprTy *Input);
virtual ExprTy *ParsePostfixUnaryOp(const LexerToken &Tok, ExprTy *Input);
// Binary Operators. 'Tok' is the token
virtual ExprTy *ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS);
/// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
@ -106,6 +113,55 @@ ASTBuilder::ExprTy *ASTBuilder::ParseFloatingConstant(const LexerToken &Tok) {
return new FloatingConstant();
}
ASTBuilder::ExprTy *ASTBuilder::ParseParenExpr(SourceLocation L,
SourceLocation R,
ExprTy *Val) {
// FIXME: This is obviously just for testing.
((Expr*)Val)->dump();
if (!FullLocInfo) return Val;
return new ParenExpr(L, R, (Expr*)Val);
}
// Unary Operators. 'Tok' is the token for the operator.
ASTBuilder::ExprTy *ASTBuilder::ParseUnaryOp(const LexerToken &Tok,
ExprTy *Input) {
UnaryOperator::Opcode Opc;
switch (Tok.getKind()) {
default: assert(0 && "Unknown unary op!");
case tok::plusplus: Opc = UnaryOperator::PreInc; break;
case tok::minusminus: Opc = UnaryOperator::PreDec; break;
case tok::amp: Opc = UnaryOperator::AddrOf; break;
case tok::star: Opc = UnaryOperator::Deref; break;
case tok::plus: Opc = UnaryOperator::Plus; break;
case tok::minus: Opc = UnaryOperator::Minus; break;
case tok::tilde: Opc = UnaryOperator::Not; break;
case tok::exclaim: Opc = UnaryOperator::LNot; break;
case tok::kw___real: Opc = UnaryOperator::Real; break;
case tok::kw___imag: Opc = UnaryOperator::Imag; break;
}
if (!FullLocInfo)
return new UnaryOperator((Expr*)Input, Opc);
else
return new UnaryOperatorLOC(Tok.getLocation(), (Expr*)Input, Opc);
}
ASTBuilder::ExprTy *ASTBuilder::ParsePostfixUnaryOp(const LexerToken &Tok,
ExprTy *Input) {
UnaryOperator::Opcode Opc;
switch (Tok.getKind()) {
default: assert(0 && "Unknown unary op!");
case tok::plusplus: Opc = UnaryOperator::PostInc; break;
case tok::minusminus: Opc = UnaryOperator::PostDec; break;
}
if (!FullLocInfo)
return new UnaryOperator((Expr*)Input, Opc);
else
return new UnaryOperatorLOC(Tok.getLocation(), (Expr*)Input, Opc);
}
// Binary Operators. 'Tok' is the token for the operator.
ASTBuilder::ExprTy *ASTBuilder::ParseBinOp(const LexerToken &Tok, ExprTy *LHS,
ExprTy *RHS) {

View File

@ -416,6 +416,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
///
Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
ExprResult Res;
LexerToken SavedTok;
// This handles all of cast-expression, unary-expression, postfix-expression,
// and primary-expression. We handle them together like this for efficiency
@ -491,8 +492,12 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
return ParseBuiltinPrimaryExpression();
case tok::plusplus: // unary-expression: '++' unary-expression
case tok::minusminus: // unary-expression: '--' unary-expression
SavedTok = Tok;
ConsumeToken();
return ParseCastExpression(true);
Res = ParseCastExpression(true);
if (!Res.isInvalid)
Res = Actions.ParseUnaryOp(SavedTok, Res.Val);
return Res;
case tok::amp: // unary-expression: '&' cast-expression
case tok::star: // unary-expression: '*' cast-expression
case tok::plus: // unary-expression: '+' cast-expression
@ -500,10 +505,14 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
case tok::tilde: // unary-expression: '~' cast-expression
case tok::exclaim: // unary-expression: '!' cast-expression
case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
case tok::kw___imag: // unary-expression: '__imag' cast-expression [GNU]
//case tok::kw__extension__: [TODO]
SavedTok = Tok;
ConsumeToken();
return ParseCastExpression(false);
Res = ParseCastExpression(false);
if (!Res.isInvalid)
Res = Actions.ParseUnaryOp(SavedTok, Res.Val);
return Res;
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
// unary-expression: 'sizeof' '(' type-name ')'
@ -594,6 +603,8 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
case tok::plusplus: // postfix-expression: postfix-expression '++'
case tok::minusminus: // postfix-expression: postfix-expression '--'
if (!LHS.isInvalid)
LHS = Actions.ParsePostfixUnaryOp(Tok, LHS.Val);
ConsumeToken();
break;
}
@ -749,6 +760,7 @@ Parser::ExprResult Parser::ParseStringLiteralExpression() {
// considered to be strings.
while (isTokenStringLiteral())
ConsumeStringToken();
// TODO: Build AST for string literals.
return ExprResult(false);
}
@ -777,6 +789,7 @@ Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType) {
Diag(Tok, diag::ext_gnu_statement_expr);
ParseCompoundStatement();
ExprType = CompoundStmt;
// TODO: Build AST for GNU compound stmt.
} else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
// Otherwise, this is a compound literal expression or cast expression.
ParseTypeName();
@ -789,9 +802,11 @@ Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType) {
Diag(OpenLoc, diag::ext_c99_compound_literal);
Result = ParseInitializer();
ExprType = CompoundLiteral;
// TODO: Build AST for compound literal.
} else if (ExprType == CastExpr) {
// Note that this doesn't parse the subsequence cast-expression.
ExprType = CastExpr;
// TODO: Build AST for cast in caller.
} else {
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
return ExprResult(true);
@ -800,6 +815,8 @@ Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType) {
} else {
Result = ParseExpression();
ExprType = SimpleExpr;
if (!Result.isInvalid && Tok.getKind() == tok::r_paren)
Result = Actions.ParseParenExpr(OpenLoc, Tok.getLocation(), Result.Val);
}
// Match the ')'.
@ -807,5 +824,6 @@ Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType) {
SkipUntil(tok::r_paren);
else
MatchRHSPunctuation(tok::r_paren, OpenLoc);
return Result;
}

View File

@ -40,10 +40,17 @@ public:
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
// Primary Expressions.
virtual ExprTy *ParseIntegerConstant(const LexerToken &Tok);
virtual ExprTy *ParseFloatingConstant(const LexerToken &Tok);
virtual ExprTy *ParseParenExpr(SourceLocation L, SourceLocation R,
ExprTy *Val);
// Binary/Unary Operators. 'Tok' is the token for the operator.
virtual ExprTy *ParseUnaryOp(const LexerToken &Tok, ExprTy *Input);
virtual ExprTy *ParsePostfixUnaryOp(const LexerToken &Tok, ExprTy *Input);
// Binary Operators. 'Tok' is the token
virtual ExprTy *ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS);
/// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
@ -106,6 +113,55 @@ ASTBuilder::ExprTy *ASTBuilder::ParseFloatingConstant(const LexerToken &Tok) {
return new FloatingConstant();
}
ASTBuilder::ExprTy *ASTBuilder::ParseParenExpr(SourceLocation L,
SourceLocation R,
ExprTy *Val) {
// FIXME: This is obviously just for testing.
((Expr*)Val)->dump();
if (!FullLocInfo) return Val;
return new ParenExpr(L, R, (Expr*)Val);
}
// Unary Operators. 'Tok' is the token for the operator.
ASTBuilder::ExprTy *ASTBuilder::ParseUnaryOp(const LexerToken &Tok,
ExprTy *Input) {
UnaryOperator::Opcode Opc;
switch (Tok.getKind()) {
default: assert(0 && "Unknown unary op!");
case tok::plusplus: Opc = UnaryOperator::PreInc; break;
case tok::minusminus: Opc = UnaryOperator::PreDec; break;
case tok::amp: Opc = UnaryOperator::AddrOf; break;
case tok::star: Opc = UnaryOperator::Deref; break;
case tok::plus: Opc = UnaryOperator::Plus; break;
case tok::minus: Opc = UnaryOperator::Minus; break;
case tok::tilde: Opc = UnaryOperator::Not; break;
case tok::exclaim: Opc = UnaryOperator::LNot; break;
case tok::kw___real: Opc = UnaryOperator::Real; break;
case tok::kw___imag: Opc = UnaryOperator::Imag; break;
}
if (!FullLocInfo)
return new UnaryOperator((Expr*)Input, Opc);
else
return new UnaryOperatorLOC(Tok.getLocation(), (Expr*)Input, Opc);
}
ASTBuilder::ExprTy *ASTBuilder::ParsePostfixUnaryOp(const LexerToken &Tok,
ExprTy *Input) {
UnaryOperator::Opcode Opc;
switch (Tok.getKind()) {
default: assert(0 && "Unknown unary op!");
case tok::plusplus: Opc = UnaryOperator::PostInc; break;
case tok::minusminus: Opc = UnaryOperator::PostDec; break;
}
if (!FullLocInfo)
return new UnaryOperator((Expr*)Input, Opc);
else
return new UnaryOperatorLOC(Tok.getLocation(), (Expr*)Input, Opc);
}
// Binary Operators. 'Tok' is the token for the operator.
ASTBuilder::ExprTy *ASTBuilder::ParseBinOp(const LexerToken &Tok, ExprTy *LHS,
ExprTy *RHS) {

View File

@ -19,6 +19,7 @@
DE06E8140A8FF9330050E87E /* Action.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06E8130A8FF9330050E87E /* Action.h */; };
DE0FCA210A95710600248FD5 /* EmptyAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE0FCA200A95710600248FD5 /* EmptyAction.cpp */; };
DE0FCA630A95859D00248FD5 /* Expr.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE0FCA620A95859D00248FD5 /* Expr.h */; };
DE0FCB340A9C21F100248FD5 /* Expr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE0FCB330A9C21F100248FD5 /* Expr.cpp */; };
DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; };
DE1F24820A7DCD3800FBF588 /* Declarations.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F24810A7DCD3800FBF588 /* Declarations.h */; };
DEAEE98B0A5A2B970045101B /* MultipleIncludeOpt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */; };
@ -119,6 +120,7 @@
DE06E8130A8FF9330050E87E /* Action.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Parse/Action.h; sourceTree = "<group>"; };
DE0FCA200A95710600248FD5 /* EmptyAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = EmptyAction.cpp; path = Parse/EmptyAction.cpp; sourceTree = "<group>"; };
DE0FCA620A95859D00248FD5 /* Expr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Expr.h; path = clang/AST/Expr.h; sourceTree = "<group>"; };
DE0FCB330A9C21F100248FD5 /* Expr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Expr.cpp; path = AST/Expr.cpp; sourceTree = "<group>"; };
DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = "<group>"; };
DE1F24810A7DCD3800FBF588 /* Declarations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Declarations.h; path = clang/Parse/Declarations.h; sourceTree = "<group>"; };
DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = "<group>"; };
@ -268,6 +270,7 @@
children = (
DEC8DAAC0A94400300353FCA /* ASTStreamer.cpp */,
DEC8D9B50A9434FA00353FCA /* Builder.cpp */,
DE0FCB330A9C21F100248FD5 /* Expr.cpp */,
);
name = AST;
sourceTree = "<group>";
@ -411,6 +414,7 @@
DEC8DA1E0A94388B00353FCA /* PrintParserCallbacks.cpp in Sources */,
DEC8DAAD0A94400300353FCA /* ASTStreamer.cpp in Sources */,
DE0FCA210A95710600248FD5 /* EmptyAction.cpp in Sources */,
DE0FCB340A9C21F100248FD5 /* Expr.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -26,16 +26,75 @@ class Expr {
public:
Expr() {}
virtual ~Expr() {}
// FIXME: Change to non-virtual method that uses visitor pattern to do this.
void dump() const;
private:
virtual void dump_impl() const = 0;
};
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
class IntegerConstant : public Expr {
public:
IntegerConstant() {}
virtual void dump_impl() const;
};
class FloatingConstant : public Expr {
public:
FloatingConstant() {}
virtual void dump_impl() const;
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
/// AST node is only formed if full location information is requested.
class ParenExpr : public Expr {
SourceLocation L, R;
Expr *Val;
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: L(l), R(r), Val(val) {}
virtual void dump_impl() const;
};
/// UnaryOperator - This represents the unary-expression's (except sizeof), the
/// postinc/postdec operators from postfix-expression, and various extensions.
class UnaryOperator : public Expr {
public:
enum Opcode {
PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators
PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators.
AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators.
Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators.
Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
Real, Imag // "__real expr"/"__imag expr" Extension.
};
UnaryOperator(Expr *input, Opcode opc)
: Input(input), Opc(opc) {}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
static const char *getOpcodeStr(Opcode Op);
virtual void dump_impl() const;
private:
Expr *Input;
Opcode Opc;
};
class UnaryOperatorLOC : public UnaryOperator {
SourceLocation Loc;
public:
UnaryOperatorLOC(SourceLocation loc, Expr *Input, Opcode Opc)
: UnaryOperator(Input, Opc), Loc(loc) {}
};
class BinaryOperator : public Expr {
@ -64,6 +123,12 @@ public:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc)
: LHS(lhs), RHS(rhs), Opc(opc) {}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
static const char *getOpcodeStr(Opcode Op);
virtual void dump_impl() const;
private:
Expr *LHS, *RHS;
Opcode Opc;
@ -85,6 +150,7 @@ class ConditionalOperator : public Expr {
public:
ConditionalOperator(Expr *cond, Expr *lhs, Expr *rhs)
: Cond(cond), LHS(lhs), RHS(rhs) {}
virtual void dump_impl() const;
};
/// ConditionalOperatorLOC - ConditionalOperator with full location info.

View File

@ -73,8 +73,19 @@ public:
// Primary Expressions.
virtual ExprTy *ParseIntegerConstant(const LexerToken &Tok) { return 0; }
virtual ExprTy *ParseFloatingConstant(const LexerToken &Tok) { return 0; }
// Binary Operators. 'Tok' is the token
virtual ExprTy *ParseParenExpr(SourceLocation L, SourceLocation R,
ExprTy *Val) {
return Val;
}
// Binary/Unary Operators. 'Tok' is the token for the operator.
virtual ExprTy *ParseUnaryOp(const LexerToken &Tok, ExprTy *Input) {
return 0;
}
virtual ExprTy *ParsePostfixUnaryOp(const LexerToken &Tok, ExprTy *Input) {
return 0;
}
virtual ExprTy *ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS) {
return 0;
}