Skip to content

Commit

Permalink
Add parser.
Browse files Browse the repository at this point in the history
  • Loading branch information
mzweilin committed Dec 7, 2013
1 parent 5860de4 commit f3e6bd0
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 14 deletions.
11 changes: 9 additions & 2 deletions wx4ed/src/pp5/ast_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,15 @@ CompoundExpr::CompoundExpr(Operator *o, Expr *r)
(op=o)->SetParent(this);
(right=r)->SetParent(this);
}



CompoundExpr::CompoundExpr(Expr *l, Operator *o)
: Expr(Join(l->GetLocation(), o->GetLocation())) {
Assert(o != NULL && l != NULL);
right = NULL;
(op=o)->SetParent(this);
(left=l)->SetParent(this);
}

ArrayAccess::ArrayAccess(yyltype loc, Expr *b, Expr *s) : LValue(loc) {
(base=b)->SetParent(this);
(subscript=s)->SetParent(this);
Expand Down
7 changes: 7 additions & 0 deletions wx4ed/src/pp5/ast_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ class CompoundExpr : public Expr
public:
CompoundExpr(Expr *lhs, Operator *op, Expr *rhs); // for binary
CompoundExpr(Operator *op, Expr *rhs); // for unary
CompoundExpr(Expr *lhs, Operator *op); // for postfix
};

class PostfixExpr : public CompoundExpr
{
public:
PostfixExpr(Expr *lhs, Operator *op) : CompoundExpr(lhs,op) {}
};

class ArithmeticExpr : public CompoundExpr
Expand Down
14 changes: 14 additions & 0 deletions wx4ed/src/pp5/ast_stmt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,18 @@ PrintStmt::PrintStmt(List<Expr*> *a) {
(args=a)->SetParentAll(this);
}

SwitchStmt::SwitchStmt(Expr *e, List<CaseStmt*> *s) {
Assert(e != NULL && s != NULL); // DefaultStmt can be NULL
(expr=e)->SetParent(this);
(caseStmts=s)->SetParentAll(this);
}

SwitchStmt::CaseStmt::CaseStmt(Expr *e, List<Stmt*> *s) {
Assert(s != NULL);

intConst=e;
if (intConst != NULL)
intConst->SetParent(this);

(caseBody=s)->SetParentAll(this);
}
20 changes: 20 additions & 0 deletions wx4ed/src/pp5/ast_stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,25 @@ class PrintStmt : public Stmt
PrintStmt(List<Expr*> *arguments);
};

class SwitchStmt : public Stmt
{
public:
class CaseStmt : public Stmt
{
protected:
Expr *intConst;
List<Stmt*> *caseBody;

public:
CaseStmt(Expr *intConst, List<Stmt*> *caseBody);
};

protected:
Expr *expr;
List<CaseStmt*> *caseStmts;

public:
SwitchStmt(Expr *expr, List<CaseStmt*> *caseStmts);
};

#endif
257 changes: 245 additions & 12 deletions wx4ed/src/pp5/parser.y
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
/* File: parser.y
* --------------
* Yacc input file to generate the parser for the compiler.
*
* pp5: add parser rules and tree construction from your past projects.
* You should not need to make any significant changes in the parser itself.
* After parsing completes, if no errors were found, the parser calls
* program->Emit() to kick off the code generation pass. The
* interesting work happens during the tree traversal.
*/

%{
Expand All @@ -31,6 +25,21 @@ void yyerror(const char *msg); // standard error-handling routine
char identifier[MaxIdentLen+1]; // +1 for terminating null
Decl *decl;
List<Decl*> *declList;
Type *type;
NamedType *cType;
List<NamedType*> *cTypeList;
FnDecl *fDecl;
VarDecl *var;
List<VarDecl*> *varList;
Expr *expr;
List<Expr*> *exprList;
Stmt *stmt;
List<Stmt*> *stmtList;
LValue *lvalue;

SwitchStmt *switchStmt;
SwitchStmt::CaseStmt *caseStmt;
List<SwitchStmt::CaseStmt*> *caseStmtList;
}


Expand All @@ -42,18 +51,52 @@ void yyerror(const char *msg); // standard error-handling routine
%token T_And T_Or T_Null T_Extends T_This T_Interface T_Implements
%token T_While T_For T_If T_Else T_Return T_Break
%token T_New T_NewArray T_Print T_ReadInteger T_ReadLine
%token T_Incr T_Decr T_Switch T_Case T_Default T_Colon

%token <identifier> T_Identifier
%token <stringConstant> T_StringConstant
%token <integerConstant> T_IntConstant
%token <doubleConstant> T_DoubleConstant
%token <boolConstant> T_BoolConstant


/* Non-terminal types
* ------------------
*/
%type <declList> DeclList
%type <expr> Constant Expr Call OptExpr
%type <lvalue> LValue
%type <type> Type
%type <cType> OptExt
%type <cTypeList> OptImpl ImpList
%type <decl> ClassDecl Decl Field IntfDecl
%type <fDecl> FnDecl FnHeader
%type <declList> FieldList DeclList IntfList
%type <var> Variable VarDecl
%type <varList> Formals FormalList VarDecls
%type <exprList> Actuals ExprList
%type <stmt> Stmt StmtBlock OptElse
%type <stmtList> StmtList

%type <switchStmt> SwitchStmt
%type <caseStmt> CaseStmt DefaultStmt
%type <caseStmtList> CaseStmts


/* Precedence and associativity
* ----------------------------
* Here we establish the precedence and associativity of the
* tokens as needed to resolve conflicts and remove ambiguity.
*/
%left '='
%left T_Or
%left T_And
%nonassoc T_Equal T_NotEqual
%nonassoc '<' '>' T_LessEqual T_GreaterEqual
%left '+' '-'
%left '*' '/' '%'
%nonassoc T_UnaryMinus '!' T_Incr T_Decr
%nonassoc '.' '['
%nonassoc T_Lower_Than_Else
%nonassoc T_Else

%%
/* Rules
Expand All @@ -65,16 +108,206 @@ Program : DeclList {
Program *program = new Program($1);
// if no errors, advance to next phase
if (ReportError::NumErrors() == 0)
program->Check();
if (ReportError::NumErrors() == 0)
program->Emit();
program->Emit();
}
;

DeclList : { /* replace with your parser */ }

DeclList : DeclList Decl { ($$=$1)->Append($2); }
| Decl { ($$ = new List<Decl*>)->Append($1); }
;

Decl : ClassDecl
| FnDecl { $$=$1; }
| VarDecl { $$=$1; }
| IntfDecl
;

VarDecl : Variable ';'
;

Variable : Type T_Identifier { $$ = new VarDecl(new Identifier(@2, $2), $1); }
;

Type : T_Int { $$ = Type::intType; }
| T_Bool { $$ = Type::boolType; }
| T_String { $$ = Type::stringType; }
| T_Double { $$ = Type::doubleType; }
| T_Identifier { $$ = new NamedType(new Identifier(@1,$1)); }
| Type T_Dims { $$ = new ArrayType(Join(@1, @2), $1); }
;

IntfDecl : T_Interface T_Identifier '{' IntfList '}'
{ $$ = new InterfaceDecl(new Identifier(@2, $2), $4); }
;

IntfList : IntfList FnHeader ';'
{ ($$=$1)->Append($2); }
| /* empty */ { $$ = new List<Decl*>(); }
;

ClassDecl : T_Class T_Identifier OptExt OptImpl '{' FieldList '}'
{ $$ = new ClassDecl(new Identifier(@2, $2), $3, $4, $6); }
;

OptExt : T_Extends T_Identifier
{ $$ = new NamedType(new Identifier(@2, $2)); }
| /* empty */ { $$ = NULL; }
;

OptImpl : T_Implements ImpList
{ $$ = $2; }
| /* empty */ { $$ = new List<NamedType*>; }
;

ImpList : ImpList ',' T_Identifier
{ ($$=$1)->Append(new NamedType(new Identifier(@3, $3))); }
| T_Identifier { ($$=new List<NamedType*>)->Append(new NamedType(new Identifier(@1, $1))); }
;

FieldList : FieldList Field { ($$=$1)->Append($2); }
| /* empty */ { $$ = new List<Decl*>(); }
;

Field : VarDecl { $$ = $1; }
| FnDecl { $$ = $1; }
;


FnHeader : Type T_Identifier '(' Formals ')'
{ $$ = new FnDecl(new Identifier(@2, $2), $1, $4); }
| T_Void T_Identifier '(' Formals ')'
{ $$ = new FnDecl(new Identifier(@2, $2), Type::voidType, $4); }
;

Formals : FormalList { $$ = $1; }
| /* empty */ { $$ = new List<VarDecl*>; }
;

FormalList: FormalList ',' Variable
{ ($$=$1)->Append($3); }
| Variable { ($$ = new List<VarDecl*>)->Append($1); }
;

FnDecl : FnHeader StmtBlock { ($$=$1)->SetFunctionBody($2); }
;

StmtBlock : '{' VarDecls StmtList '}'
{ $$ = new StmtBlock($2, $3); }
;

VarDecls : VarDecls VarDecl { ($$=$1)->Append($2); }
| /* empty */ { $$ = new List<VarDecl*>; }
;

StmtList : Stmt StmtList { $$ = $2; $$->InsertAt($1, 0); }
| /* empty */ { $$ = new List<Stmt*>; }
;

Stmt : OptExpr ';' { $$ = $1; }
| StmtBlock
| T_If '(' Expr ')' Stmt OptElse
{ $$ = new IfStmt($3, $5, $6); }
| T_While '(' Expr ')' Stmt
{ $$ = new WhileStmt($3, $5); }
| T_For '(' OptExpr ';' Expr ';' OptExpr ')' Stmt
{ $$ = new ForStmt($3, $5, $7, $9); }
| T_Return Expr ';'
{ $$ = new ReturnStmt(@2, $2); }
| T_Return ';'
{ $$ = new ReturnStmt(@1, new EmptyExpr()); }
| T_Print '(' ExprList ')' ';'
{ $$ = new PrintStmt($3); }
| T_Break ';' { $$ = new BreakStmt(@1); }
| SwitchStmt { $$ = $1; }
;

SwitchStmt: T_Switch '(' Expr ')' '{' CaseStmts DefaultStmt '}' { if ($7) $6->Append($7);
$$ = new SwitchStmt($3, $6);}
;

CaseStmts : CaseStmts CaseStmt { ($$ = $1)->Append($2); }
| CaseStmt { ($$ = new List<SwitchStmt::CaseStmt*>)->Append($1);}
;
// why colon could not be recognized? but comma did!!!
CaseStmt : T_Case T_IntConstant T_Colon StmtList { $$ = new SwitchStmt::CaseStmt((new IntConstant(@2, $2)), $4); }
;
// why colon could not be recognized? but comma did!!!
DefaultStmt : T_Default T_Colon StmtList { $$ = new SwitchStmt::CaseStmt(NULL, $3); }
| /* empty */ { $$ = NULL;}
;

LValue : T_Identifier { $$ = new FieldAccess(NULL, new Identifier(@1, $1)); }
| Expr '.' T_Identifier { $$ = new FieldAccess($1, new Identifier(@3, $3)); }
| Expr '[' Expr ']' { $$ = new ArrayAccess(Join(@1, @4), $1, $3); }
;

Call : T_Identifier '(' Actuals ')'
{ $$ = new Call(Join(@1,@4), NULL, new Identifier(@1,$1), $3); }
| Expr '.' T_Identifier '(' Actuals ')'
{ $$ = new Call(Join(@1,@6), $1, new Identifier(@3,$3), $5); }
;

OptExpr : Expr { $$ = $1; }
| /* empty */ { $$ = new EmptyExpr(); }
;

Expr : LValue { $$ = $1; }
| LValue T_Incr { $$ = new PostfixExpr($1,(new Operator(@2, "++"))); }
//{ $$ = new AssignExpr($1, new Operator(@2,"="), new ArithmeticExpr($1, new Operator(@2, "+"), new IntConstant(@2,1))); }
| LValue T_Decr { $$ = new PostfixExpr($1,(new Operator(@2, "--"))); }
//{ $$ = new AssignExpr($1, new Operator(@2,"="), new ArithmeticExpr($1, new Operator(@2, "-"), new IntConstant(@2,1))); }
| Call
| Constant
| LValue '=' Expr { $$ = new AssignExpr($1, new Operator(@2,"="), $3); }
| Expr '+' Expr { $$ = new ArithmeticExpr($1, new Operator(@2, "+"), $3); }
| Expr '-' Expr { $$ = new ArithmeticExpr($1, new Operator(@2, "-"), $3); }
| Expr '/' Expr { $$ = new ArithmeticExpr($1, new Operator(@2,"/"), $3); }
| Expr '*' Expr { $$ = new ArithmeticExpr($1, new Operator(@2,"*"), $3); }
| Expr '%' Expr { $$ = new ArithmeticExpr($1, new Operator(@2,"%"), $3); }
| Expr T_Equal Expr { $$ = new EqualityExpr($1, new Operator(@2,"=="), $3); }
| Expr T_NotEqual Expr { $$ = new EqualityExpr($1, new Operator(@2,"!="), $3); }
| Expr '<' Expr { $$ = new RelationalExpr($1, new Operator(@2,"<"), $3); }
| Expr '>' Expr { $$ = new RelationalExpr($1, new Operator(@2,">"), $3); }
| Expr T_LessEqual Expr
{ $$ = new RelationalExpr($1, new Operator(@2,"<="), $3); }
| Expr T_GreaterEqual Expr
{ $$ = new RelationalExpr($1, new Operator(@2,">="), $3); }
| Expr T_And Expr { $$ = new LogicalExpr($1, new Operator(@2,"&&"), $3); }
| Expr T_Or Expr { $$ = new LogicalExpr($1, new Operator(@2,"||"), $3); }
| '(' Expr ')' { $$ = $2; }
| '-' Expr %prec T_UnaryMinus
{ $$ = new ArithmeticExpr(new Operator(@1,"-"), $2); }
| '!' Expr { $$ = new LogicalExpr(new Operator(@1,"!"), $2); }
| T_ReadInteger '(' ')'
{ $$ = new ReadIntegerExpr(Join(@1,@3)); }
| T_ReadLine '(' ')' { $$ = new ReadLineExpr(Join(@1,@3)); }
| T_New '(' T_Identifier ')'
{ $$ = new NewExpr(Join(@1,@4),new NamedType(new Identifier(@3,$3))); }
| T_NewArray '(' Expr ',' Type ')'
{ $$ = new NewArrayExpr(Join(@1,@6),$3, $5); }
| T_This { $$ = new This(@1); }
;

Constant : T_IntConstant { $$ = new IntConstant(@1,$1); }
| T_BoolConstant { $$ = new BoolConstant(@1,$1); }
| T_DoubleConstant { $$ = new DoubleConstant(@1,$1); }
| T_StringConstant { $$ = new StringConstant(@1,$1); }
| T_Null { $$ = new NullConstant(@1); }
;

Actuals : ExprList { $$ = $1; }
| /* empty */ { $$ = new List<Expr*>; }
;

ExprList : ExprList ',' Expr { ($$=$1)->Append($3); }
| Expr { ($$ = new List<Expr*>)->Append($1); }
;

OptElse : T_Else Stmt { $$ = $2; }
| /* empty */ %prec T_Lower_Than_Else
{ $$ = NULL; }
;

%%

Expand Down

0 comments on commit f3e6bd0

Please sign in to comment.