Commit c30bbd12c19674ba2f4945fe4fec04457ef33406

Authored by Austin Sun
0 parents
Exists in master

well

Showing 37 changed files with 3036 additions and 0 deletions Side-by-side Diff

... ... @@ -0,0 +1,87 @@
  1 +##
  2 +## Simple makefile for CS131 programming projects
  3 +##
  4 +
  5 +
  6 +.PHONY: clean strip
  7 +
  8 +# Set the default target. When you make with no arguments,
  9 +# this will be the target built.
  10 +COMPILER = glc
  11 +PRODUCTS = $(COMPILER)
  12 +default: $(PRODUCTS)
  13 +
  14 +# Set up the list of source and object files
  15 +SRCS = ast.cc ast_decl.cc ast_expr.cc ast_stmt.cc ast_type.cc errors.cc utility.cc main.cc symtable.cc irgen.cc
  16 +
  17 +# OBJS can deal with either .cc or .c files listed in SRCS
  18 +OBJS = y.tab.o lex.yy.o $(patsubst %.cc, %.o, $(filter %.cc,$(SRCS))) $(patsubst %.c, %.o, $(filter %.c, $(SRCS)))
  19 +
  20 +JUNK = *.o lex.yy.c dpp.yy.c y.tab.c y.tab.h *.core core *~
  21 +
  22 +# Define the tools we are going to use
  23 +CC= g++
  24 +LD = g++
  25 +LEX = flex
  26 +YACC = bison
  27 +
  28 +# Set up the necessary flags for the tools
  29 +
  30 +# We want debugging and most warnings, but lex/yacc generate some
  31 +# static symbols we don't use, so turn off unused warnings to avoid clutter
  32 +# Also STL has some signed/unsigned comparisons we want to suppress
  33 +CFLAGS = -g -Wall -Wno-unused -Wno-sign-compare `llvm-config --cxxflags`
  34 +
  35 +# The -d flag tells lex to set up for debugging. Can turn on/off by
  36 +# setting value of global yy_flex_debug inside the scanner itself
  37 +LEXFLAGS = -d
  38 +
  39 +# The -d flag tells yacc to generate header with token types
  40 +# The -v flag writes out a verbose description of the states and conflicts
  41 +# The -t flag turns on debugging capability
  42 +# The -y flag means imitate yacc's output file naming conventions
  43 +YACCFLAGS = -dvty
  44 +# YACCFLAGS = -dvty --report=all --report-file=y.debug
  45 +
  46 +# Link with standard C library, math library, and lex library
  47 +LIBS = -lc -lm -ll `llvm-config --ldflags --libs`
  48 +
  49 +# Rules for various parts of the target
  50 +
  51 +.yy.o: $*.yy.c
  52 + $(CC) $(CFLAGS) -c -o $@ $*.cc
  53 +
  54 +lex.yy.c: scanner.l parser.y y.tab.h
  55 + $(LEX) $(LEXFLAGS) scanner.l
  56 +
  57 +y.tab.o: y.tab.c
  58 + $(CC) $(CFLAGS) -c -o y.tab.o y.tab.c
  59 +
  60 +y.tab.h y.tab.c: parser.y
  61 + $(YACC) $(YACCFLAGS) parser.y
  62 +.cc.o: $*.cc
  63 + $(CC) $(CFLAGS) -c -o $@ $*.cc
  64 +
  65 +# rules to build compiler (dcc)
  66 +
  67 +$(COMPILER) : $(OBJS)
  68 + $(LD) -o $@ $(OBJS) $(LIBS)
  69 +
  70 +
  71 +# This target is to build small for testing (no debugging info), removes
  72 +# all intermediate products, too
  73 +strip : $(PRODUCTS)
  74 + strip $(PRODUCTS)
  75 + rm -rf $(JUNK)
  76 +
  77 +
  78 +# make depend will set up the header file dependencies for the
  79 +# assignment. You should make depend whenever you add a new header
  80 +# file to the project or move the project between machines
  81 +#
  82 +depend:
  83 + makedepend -- $(CFLAGS) -- $(SRCS)
  84 +
  85 +clean:
  86 + rm -f $(JUNK) y.output $(PRODUCTS)
  87 +
... ... @@ -0,0 +1,16 @@
  1 +# CSE131
  2 +
  3 +Describe briefly how you approached the project in Project_Description.txt
  4 +
  5 +Fill in the name email and pid in the script submission.sh
  6 +Execute the script like
  7 +
  8 +$ ./submission.sh
  9 +
  10 +if it fails to execute then try changing the permissions like
  11 +$ chmod +x submission.sh
  12 +
  13 +if it fails for other reasons, then fix the name,email, pid etc whatever the error message says.
  14 +
  15 +
  16 +After it executes, you would get a zip file which you need to submit on the link given in piazza submission guildelines.
... ... @@ -0,0 +1,48 @@
  1 +/* File: ast.cc
  2 + * ------------
  3 + */
  4 +
  5 +#include "ast.h"
  6 +#include "ast_type.h"
  7 +#include "ast_decl.h"
  8 +#include "symtable.h"
  9 +#include <string.h> // strdup
  10 +#include <stdio.h> // printf
  11 +
  12 +Node::Node(yyltype loc) {
  13 + location = new yyltype(loc);
  14 + parent = NULL;
  15 +}
  16 +
  17 +Node::Node() {
  18 + location = NULL;
  19 + parent = NULL;
  20 +}
  21 +
  22 +/* The Print method is used to print the parse tree nodes.
  23 + * If this node has a location (most nodes do, but some do not), it
  24 + * will first print the line number to help you match the parse tree
  25 + * back to the source text. It then indents the proper number of levels
  26 + * and prints the "print name" of the node. It then will invoke the
  27 + * virtual function PrintChildren which is expected to print the
  28 + * internals of the node (itself & children) as appropriate.
  29 + */
  30 +void Node::Print(int indentLevel, const char *label) {
  31 + const int numSpaces = 3;
  32 + printf("\n");
  33 + if (GetLocation())
  34 + printf("%*d", numSpaces, GetLocation()->first_line);
  35 + else
  36 + printf("%*s", numSpaces, "");
  37 + printf("%*s%s%s: ", indentLevel*numSpaces, "",
  38 + label? label : "", GetPrintNameForNode());
  39 + PrintChildren(indentLevel);
  40 +}
  41 +
  42 +Identifier::Identifier(yyltype loc, const char *n) : Node(loc) {
  43 + name = strdup(n);
  44 +}
  45 +
  46 +void Identifier::PrintChildren(int indentLevel) {
  47 + printf("%s", name);
  48 +}
... ... @@ -0,0 +1,103 @@
  1 +/**
  2 + * File: ast.h
  3 + * -----------
  4 + * This file defines the abstract base class Node and the concrete
  5 + * Identifier and Error node subclasses that are used through the tree as
  6 + * leaf nodes. A parse tree is a hierarchical collection of ast nodes (or,
  7 + * more correctly, of instances of concrete subclassses such as VarDecl,
  8 + * ForStmt, and AssignExpr).
  9 + *
  10 + * Location: Each node maintains its lexical location (line and columns in
  11 + * file), that location can be NULL for those nodes that don't care/use
  12 + * locations. The location is typcially set by the node constructor. The
  13 + * location is used to provide the context when reporting semantic errors.
  14 + *
  15 + * Parent: Each node has a pointer to its parent. For a Program node, the
  16 + * parent is NULL, for all other nodes it is the pointer to the node one level
  17 + * up in the parse tree. The parent is not set in the constructor (during a
  18 + * bottom-up parse we don't know the parent at the time of construction) but
  19 + * instead we wait until assigning the children into the parent node and then
  20 + * set up links in both directions. The parent link is typically not used
  21 + * during parsing, but is more important in later phases.
  22 + *
  23 + * Printing: This functionaility is saved from pp2 of the node classes to
  24 + * print out the AST tree for debugging purpose. Each node class is
  25 + * responsible for printing itself/children by overriding the virtual
  26 + * PrintChildren() and GetPrintNameForNode() methods. All the classes we
  27 + * provide already implement these methods, so your job is to construct the
  28 + * nodes and wire them up during parsing. Once that's done, printing is a snap!
  29 +
  30 + * Semantic analysis: For pp3 you are adding "Check" behavior to the ast
  31 + * node classes. Your semantic analyzer should do an inorder walk on the
  32 + * parse tree, and when visiting each node, verify the particular
  33 + * semantic rules that apply to that construct.
  34 +
  35 + */
  36 +
  37 +#ifndef _H_ast
  38 +#define _H_ast
  39 +
  40 +#include <stdlib.h> // for NULL
  41 +#include "location.h"
  42 +#include <iostream>
  43 +
  44 +using namespace std;
  45 +
  46 +class SymbolTable;
  47 +class MyStack;
  48 +class FnDecl;
  49 +
  50 +class Node {
  51 + protected:
  52 + yyltype *location;
  53 + Node *parent;
  54 +
  55 + public:
  56 + Node(yyltype loc);
  57 + Node();
  58 + virtual ~Node() {}
  59 +
  60 + yyltype *GetLocation() { return location; }
  61 + void SetParent(Node *p) { parent = p; }
  62 + Node *GetParent() { return parent; }
  63 +
  64 + virtual const char *GetPrintNameForNode() = 0;
  65 +
  66 + // Print() is deliberately _not_ virtual
  67 + // subclasses should override PrintChildren() instead
  68 + void Print(int indentLevel, const char *label = NULL);
  69 + virtual void PrintChildren(int indentLevel) {}
  70 +
  71 + virtual void Emit() {}
  72 +};
  73 +
  74 +
  75 +class Identifier : public Node
  76 +{
  77 + protected:
  78 + char *name;
  79 +
  80 + public:
  81 + Identifier(yyltype loc, const char *name);
  82 + const char *GetPrintNameForNode() { return "Identifier"; }
  83 + char *GetName() const { return name; }
  84 + void PrintChildren(int indentLevel);
  85 + friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; }
  86 +};
  87 +
  88 +
  89 +// This node class is designed to represent a portion of the tree that
  90 +// encountered syntax errors during parsing. The partial completed tree
  91 +// is discarded along with the states being popped, and an instance of
  92 +// the Error class can stand in as the placeholder in the parse tree
  93 +// when your parser can continue after an error.
  94 +class Error : public Node
  95 +{
  96 + public:
  97 + Error() : Node() {}
  98 + const char *GetPrintNameForNode() { return "Error"; }
  99 +};
  100 +
  101 +
  102 +
  103 +#endif
... ... @@ -0,0 +1,69 @@
  1 +/* File: ast_decl.cc
  2 + * -----------------
  3 + * Implementation of Decl node classes.
  4 + */
  5 +#include "ast_decl.h"
  6 +#include "ast_type.h"
  7 +#include "ast_stmt.h"
  8 +#include "symtable.h"
  9 +
  10 +Decl::Decl(Identifier *n) : Node(*n->GetLocation()) {
  11 + Assert(n != NULL);
  12 + (id=n)->SetParent(this);
  13 +}
  14 +
  15 +VarDecl::VarDecl(Identifier *n, Type *t, Expr *e) : Decl(n) {
  16 + Assert(n != NULL && t != NULL);
  17 + (type=t)->SetParent(this);
  18 + if (e) (assignTo=e)->SetParent(this);
  19 + typeq = NULL;
  20 +}
  21 +
  22 +VarDecl::VarDecl(Identifier *n, TypeQualifier *tq, Expr *e) : Decl(n) {
  23 + Assert(n != NULL && tq != NULL);
  24 + (typeq=tq)->SetParent(this);
  25 + if (e) (assignTo=e)->SetParent(this);
  26 + type = NULL;
  27 +}
  28 +
  29 +VarDecl::VarDecl(Identifier *n, Type *t, TypeQualifier *tq, Expr *e) : Decl(n) {
  30 + Assert(n != NULL && t != NULL && tq != NULL);
  31 + (type=t)->SetParent(this);
  32 + (typeq=tq)->SetParent(this);
  33 + if (e) (assignTo=e)->SetParent(this);
  34 +}
  35 +
  36 +void VarDecl::PrintChildren(int indentLevel) {
  37 + if (typeq) typeq->Print(indentLevel+1);
  38 + if (type) type->Print(indentLevel+1);
  39 + if (id) id->Print(indentLevel+1);
  40 + if (assignTo) assignTo->Print(indentLevel+1, "(initializer) ");
  41 +}
  42 +
  43 +FnDecl::FnDecl(Identifier *n, Type *r, List<VarDecl*> *d) : Decl(n) {
  44 + Assert(n != NULL && r!= NULL && d != NULL);
  45 + (returnType=r)->SetParent(this);
  46 + (formals=d)->SetParentAll(this);
  47 + body = NULL;
  48 + returnTypeq = NULL;
  49 +}
  50 +
  51 +FnDecl::FnDecl(Identifier *n, Type *r, TypeQualifier *rq, List<VarDecl*> *d) : Decl(n) {
  52 + Assert(n != NULL && r != NULL && rq != NULL&& d != NULL);
  53 + (returnType=r)->SetParent(this);
  54 + (returnTypeq=rq)->SetParent(this);
  55 + (formals=d)->SetParentAll(this);
  56 + body = NULL;
  57 +}
  58 +
  59 +void FnDecl::SetFunctionBody(Stmt *b) {
  60 + (body=b)->SetParent(this);
  61 +}
  62 +
  63 +void FnDecl::PrintChildren(int indentLevel) {
  64 + if (returnType) returnType->Print(indentLevel+1, "(return type) ");
  65 + if (id) id->Print(indentLevel+1);
  66 + if (formals) formals->PrintAll(indentLevel+1, "(formals) ");
  67 + if (body) body->Print(indentLevel+1, "(body) ");
  68 +}
  69 +
... ... @@ -0,0 +1,92 @@
  1 +/* File: ast_decl.h
  2 + * ----------------
  3 + * In our parse tree, Decl nodes are used to represent and
  4 + * manage declarations. There are 4 subclasses of the base class,
  5 + * specialized for declarations of variables, functions, classes,
  6 + * and interfaces.
  7 + *
  8 + * pp3: You will need to extend the Decl classes to implement
  9 + * semantic processing including detection of declaration conflicts
  10 + * and managing scoping issues.
  11 + */
  12 +
  13 +#ifndef _H_ast_decl
  14 +#define _H_ast_decl
  15 +
  16 +#include "ast.h"
  17 +#include "list.h"
  18 +#include "ast_expr.h"
  19 +
  20 +class Type;
  21 +class TypeQualifier;
  22 +class NamedType;
  23 +class Identifier;
  24 +class Stmt;
  25 +
  26 +void yyerror(const char *msg);
  27 +
  28 +class Decl : public Node
  29 +{
  30 + protected:
  31 + Identifier *id;
  32 +
  33 + public:
  34 + Decl() : id(NULL) {}
  35 + Decl(Identifier *name);
  36 + Identifier *GetIdentifier() const { return id; }
  37 + friend ostream& operator<<(ostream& out, Decl *d) { return out << d->id; }
  38 +
  39 +};
  40 +
  41 +class VarDecl : public Decl
  42 +{
  43 + protected:
  44 + Type *type;
  45 + TypeQualifier *typeq;
  46 + Expr *assignTo;
  47 +
  48 + public:
  49 + VarDecl() : type(NULL), typeq(NULL), assignTo(NULL) {}
  50 + VarDecl(Identifier *name, Type *type, Expr *assignTo = NULL);
  51 + VarDecl(Identifier *name, TypeQualifier *typeq, Expr *assignTo = NULL);
  52 + VarDecl(Identifier *name, Type *type, TypeQualifier *typeq, Expr *assignTo = NULL);
  53 + const char *GetPrintNameForNode() { return "VarDecl"; }
  54 + void PrintChildren(int indentLevel);
  55 + Type *GetType() const { return type; }
  56 +};
  57 +
  58 +class VarDeclError : public VarDecl
  59 +{
  60 + public:
  61 + VarDeclError() : VarDecl() { yyerror(this->GetPrintNameForNode()); };
  62 + const char *GetPrintNameForNode() { return "VarDeclError"; }
  63 +};
  64 +
  65 +class FnDecl : public Decl
  66 +{
  67 + protected:
  68 + List<VarDecl*> *formals;
  69 + Type *returnType;
  70 + TypeQualifier *returnTypeq;
  71 + Stmt *body;
  72 +
  73 + public:
  74 + FnDecl() : Decl(), formals(NULL), returnType(NULL), returnTypeq(NULL), body(NULL) {}
  75 + FnDecl(Identifier *name, Type *returnType, List<VarDecl*> *formals);
  76 + FnDecl(Identifier *name, Type *returnType, TypeQualifier *returnTypeq, List<VarDecl*> *formals);
  77 + void SetFunctionBody(Stmt *b);
  78 + const char *GetPrintNameForNode() { return "FnDecl"; }
  79 + void PrintChildren(int indentLevel);
  80 +
  81 + Type *GetType() const { return returnType; }
  82 + List<VarDecl*> *GetFormals() {return formals;}
  83 +};
  84 +
  85 +class FormalsError : public FnDecl
  86 +{
  87 + public:
  88 + FormalsError() : FnDecl() { yyerror(this->GetPrintNameForNode()); }
  89 + const char *GetPrintNameForNode() { return "FormalsError"; }
  90 +};
  91 +
  92 +#endif
... ... @@ -0,0 +1,134 @@
  1 +/* File: ast_expr.cc
  2 + * -----------------
  3 + * Implementation of expression node classes.
  4 + */
  5 +
  6 +#include <string.h>
  7 +#include "ast_expr.h"
  8 +#include "ast_type.h"
  9 +#include "ast_decl.h"
  10 +#include "symtable.h"
  11 +
  12 +IntConstant::IntConstant(yyltype loc, int val) : Expr(loc) {
  13 + value = val;
  14 +}
  15 +void IntConstant::PrintChildren(int indentLevel) {
  16 + printf("%d", value);
  17 +}
  18 +
  19 +FloatConstant::FloatConstant(yyltype loc, double val) : Expr(loc) {
  20 + value = val;
  21 +}
  22 +void FloatConstant::PrintChildren(int indentLevel) {
  23 + printf("%g", value);
  24 +}
  25 +
  26 +BoolConstant::BoolConstant(yyltype loc, bool val) : Expr(loc) {
  27 + value = val;
  28 +}
  29 +void BoolConstant::PrintChildren(int indentLevel) {
  30 + printf("%s", value ? "true" : "false");
  31 +}
  32 +
  33 +VarExpr::VarExpr(yyltype loc, Identifier *ident) : Expr(loc) {
  34 + Assert(ident != NULL);
  35 + this->id = ident;
  36 +}
  37 +
  38 +void VarExpr::PrintChildren(int indentLevel) {
  39 + id->Print(indentLevel+1);
  40 +}
  41 +
  42 +Operator::Operator(yyltype loc, const char *tok) : Node(loc) {
  43 + Assert(tok != NULL);
  44 + strncpy(tokenString, tok, sizeof(tokenString));
  45 +}
  46 +
  47 +void Operator::PrintChildren(int indentLevel) {
  48 + printf("%s",tokenString);
  49 +}
  50 +
  51 +bool Operator::IsOp(const char *op) const {
  52 + return strcmp(tokenString, op) == 0;
  53 +}
  54 +
  55 +CompoundExpr::CompoundExpr(Expr *l, Operator *o, Expr *r)
  56 + : Expr(Join(l->GetLocation(), r->GetLocation())) {
  57 + Assert(l != NULL && o != NULL && r != NULL);
  58 + (op=o)->SetParent(this);
  59 + (left=l)->SetParent(this);
  60 + (right=r)->SetParent(this);
  61 +}
  62 +
  63 +CompoundExpr::CompoundExpr(Operator *o, Expr *r)
  64 + : Expr(Join(o->GetLocation(), r->GetLocation())) {
  65 + Assert(o != NULL && r != NULL);
  66 + left = NULL;
  67 + (op=o)->SetParent(this);
  68 + (right=r)->SetParent(this);
  69 +}
  70 +
  71 +CompoundExpr::CompoundExpr(Expr *l, Operator *o)
  72 + : Expr(Join(l->GetLocation(), o->GetLocation())) {
  73 + Assert(l != NULL && o != NULL);
  74 + (left=l)->SetParent(this);
  75 + (op=o)->SetParent(this);
  76 +}
  77 +
  78 +void CompoundExpr::PrintChildren(int indentLevel) {
  79 + if (left) left->Print(indentLevel+1);
  80 + op->Print(indentLevel+1);
  81 + if (right) right->Print(indentLevel+1);
  82 +}
  83 +
  84 +ConditionalExpr::ConditionalExpr(Expr *c, Expr *t, Expr *f)
  85 + : Expr(Join(c->GetLocation(), f->GetLocation())) {
  86 + Assert(c != NULL && t != NULL && f != NULL);
  87 + (cond=c)->SetParent(this);
  88 + (trueExpr=t)->SetParent(this);
  89 + (falseExpr=f)->SetParent(this);
  90 +}
  91 +
  92 +void ConditionalExpr::PrintChildren(int indentLevel) {
  93 + cond->Print(indentLevel+1, "(cond) ");
  94 + trueExpr->Print(indentLevel+1, "(true) ");
  95 + falseExpr->Print(indentLevel+1, "(false) ");
  96 +}
  97 +ArrayAccess::ArrayAccess(yyltype loc, Expr *b, Expr *s) : LValue(loc) {
  98 + (base=b)->SetParent(this);
  99 + (subscript=s)->SetParent(this);
  100 +}
  101 +
  102 +void ArrayAccess::PrintChildren(int indentLevel) {
  103 + base->Print(indentLevel+1);
  104 + subscript->Print(indentLevel+1, "(subscript) ");
  105 +}
  106 +
  107 +FieldAccess::FieldAccess(Expr *b, Identifier *f)
  108 + : LValue(b? Join(b->GetLocation(), f->GetLocation()) : *f->GetLocation()) {
  109 + Assert(f != NULL); // b can be be NULL (just means no explicit base)
  110 + base = b;
  111 + if (base) base->SetParent(this);
  112 + (field=f)->SetParent(this);
  113 +}
  114 +
  115 +
  116 +void FieldAccess::PrintChildren(int indentLevel) {
  117 + if (base) base->Print(indentLevel+1);
  118 + field->Print(indentLevel+1);
  119 +}
  120 +
  121 +Call::Call(yyltype loc, Expr *b, Identifier *f, List<Expr*> *a) : Expr(loc) {
  122 + Assert(f != NULL && a != NULL); // b can be be NULL (just means no explicit base)
  123 + base = b;
  124 + if (base) base->SetParent(this);
  125 + (field=f)->SetParent(this);
  126 + (actuals=a)->SetParentAll(this);
  127 +}
  128 +
  129 +void Call::PrintChildren(int indentLevel) {
  130 + if (base) base->Print(indentLevel+1);
  131 + if (field) field->Print(indentLevel+1);
  132 + if (actuals) actuals->PrintAll(indentLevel+1, "(actuals) ");
  133 +}
  134 +
... ... @@ -0,0 +1,235 @@
  1 +/* File: ast_expr.h
  2 + * ----------------
  3 + * The Expr class and its subclasses are used to represent
  4 + * expressions in the parse tree. For each expression in the
  5 + * language (add, call, New, etc.) there is a corresponding
  6 + * node class for that construct.
  7 + *
  8 + * pp3: You will need to extend the Expr classes to implement
  9 + * semantic analysis for rules pertaining to expressions.
  10 + */
  11 +
  12 +
  13 +#ifndef _H_ast_expr
  14 +#define _H_ast_expr
  15 +
  16 +#include "ast.h"
  17 +#include "ast_stmt.h"
  18 +#include "list.h"
  19 +#include "ast_type.h"
  20 +
  21 +void yyerror(const char *msg);
  22 +
  23 +class Expr : public Stmt
  24 +{
  25 + public:
  26 + Expr(yyltype loc) : Stmt(loc) {}
  27 + Expr() : Stmt() {}
  28 +
  29 + friend std::ostream& operator<< (std::ostream& stream, Expr * expr) {
  30 + return stream << expr->GetPrintNameForNode();
  31 + }
  32 +};
  33 +
  34 +class ExprError : public Expr
  35 +{
  36 + public:
  37 + ExprError() : Expr() { yyerror(this->GetPrintNameForNode()); }
  38 + const char *GetPrintNameForNode() { return "ExprError"; }
  39 +};
  40 +
  41 +/* This node type is used for those places where an expression is optional.
  42 + * We could use a NULL pointer, but then it adds a lot of checking for
  43 + * NULL. By using a valid, but no-op, node, we save that trouble */
  44 +class EmptyExpr : public Expr
  45 +{
  46 + public:
  47 + const char *GetPrintNameForNode() { return "Empty"; }
  48 +};
  49 +
  50 +class IntConstant : public Expr
  51 +{
  52 + protected:
  53 + int value;
  54 +
  55 + public:
  56 + IntConstant(yyltype loc, int val);
  57 + const char *GetPrintNameForNode() { return "IntConstant"; }
  58 + void PrintChildren(int indentLevel);
  59 +};
  60 +
  61 +class FloatConstant: public Expr
  62 +{
  63 + protected:
  64 + double value;
  65 +
  66 + public:
  67 + FloatConstant(yyltype loc, double val);
  68 + const char *GetPrintNameForNode() { return "FloatConstant"; }
  69 + void PrintChildren(int indentLevel);
  70 +};
  71 +
  72 +class BoolConstant : public Expr
  73 +{
  74 + protected:
  75 + bool value;
  76 +
  77 + public:
  78 + BoolConstant(yyltype loc, bool val);
  79 + const char *GetPrintNameForNode() { return "BoolConstant"; }
  80 + void PrintChildren(int indentLevel);
  81 +};
  82 +
  83 +class VarExpr : public Expr
  84 +{
  85 + protected:
  86 + Identifier *id;
  87 +
  88 + public:
  89 + VarExpr(yyltype loc, Identifier *id);
  90 + const char *GetPrintNameForNode() { return "VarExpr"; }
  91 + void PrintChildren(int indentLevel);
  92 + Identifier *GetIdentifier() {return id;}
  93 +};
  94 +
  95 +class Operator : public Node
  96 +{
  97 + protected:
  98 + char tokenString[4];
  99 +
  100 + public:
  101 + Operator(yyltype loc, const char *tok);
  102 + const char *GetPrintNameForNode() { return "Operator"; }
  103 + void PrintChildren(int indentLevel);
  104 + friend ostream& operator<<(ostream& out, Operator *o) { return out << o->tokenString; }
  105 + bool IsOp(const char *op) const;
  106 + };
  107 +
  108 +class CompoundExpr : public Expr
  109 +{
  110 + protected:
  111 + Operator *op;
  112 + Expr *left, *right; // left will be NULL if unary
  113 +
  114 + public:
  115 + CompoundExpr(Expr *lhs, Operator *op, Expr *rhs); // for binary
  116 + CompoundExpr(Operator *op, Expr *rhs); // for unary
  117 + CompoundExpr(Expr *lhs, Operator *op); // for unary
  118 + void PrintChildren(int indentLevel);
  119 +};
  120 +
  121 +class ArithmeticExpr : public CompoundExpr
  122 +{
  123 + public:
  124 + ArithmeticExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {}
  125 + ArithmeticExpr(Operator *op, Expr *rhs) : CompoundExpr(op,rhs) {}
  126 + const char *GetPrintNameForNode() { return "ArithmeticExpr"; }
  127 +};
  128 +
  129 +class RelationalExpr : public CompoundExpr
  130 +{
  131 + public:
  132 + RelationalExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {}
  133 + const char *GetPrintNameForNode() { return "RelationalExpr"; }
  134 +};
  135 +
  136 +class EqualityExpr : public CompoundExpr
  137 +{
  138 + public:
  139 + EqualityExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {}
  140 + const char *GetPrintNameForNode() { return "EqualityExpr"; }
  141 +};
  142 +
  143 +class LogicalExpr : public CompoundExpr
  144 +{
  145 + public:
  146 + LogicalExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {}
  147 + LogicalExpr(Operator *op, Expr *rhs) : CompoundExpr(op,rhs) {}
  148 + const char *GetPrintNameForNode() { return "LogicalExpr"; }
  149 +};
  150 +
  151 +class AssignExpr : public CompoundExpr
  152 +{
  153 + public:
  154 + AssignExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {}
  155 + const char *GetPrintNameForNode() { return "AssignExpr"; }
  156 +};
  157 +
  158 +class PostfixExpr : public CompoundExpr
  159 +{
  160 + public:
  161 + PostfixExpr(Expr *lhs, Operator *op) : CompoundExpr(lhs,op) {}
  162 + const char *GetPrintNameForNode() { return "PostfixExpr"; }
  163 +
  164 +};
  165 +
  166 +class ConditionalExpr : public Expr
  167 +{
  168 + protected:
  169 + Expr *cond, *trueExpr, *falseExpr;
  170 + public:
  171 + ConditionalExpr(Expr *c, Expr *t, Expr *f);
  172 + void PrintChildren(int indentLevel);
  173 + const char *GetPrintNameForNode() { return "ConditionalExpr"; }
  174 +};
  175 +
  176 +class LValue : public Expr
  177 +{
  178 + public:
  179 + LValue(yyltype loc) : Expr(loc) {}
  180 +};
  181 +
  182 +class ArrayAccess : public LValue
  183 +{
  184 + protected:
  185 + Expr *base, *subscript;
  186 +
  187 + public:
  188 + ArrayAccess(yyltype loc, Expr *base, Expr *subscript);
  189 + const char *GetPrintNameForNode() { return "ArrayAccess"; }
  190 + void PrintChildren(int indentLevel);
  191 +};
  192 +
  193 +/* Note that field access is used both for qualified names
  194 + * base.field and just field without qualification. We don't
  195 + * know for sure whether there is an implicit "this." in
  196 + * front until later on, so we use one node type for either
  197 + * and sort it out later. */
  198 +class FieldAccess : public LValue
  199 +{
  200 + protected:
  201 + Expr *base; // will be NULL if no explicit base
  202 + Identifier *field;
  203 +
  204 + public:
  205 + FieldAccess(Expr *base, Identifier *field); //ok to pass NULL base
  206 + const char *GetPrintNameForNode() { return "FieldAccess"; }
  207 + void PrintChildren(int indentLevel);
  208 +};
  209 +
  210 +/* Like field access, call is used both for qualified base.field()
  211 + * and unqualified field(). We won't figure out until later
  212 + * whether we need implicit "this." so we use one node type for either
  213 + * and sort it out later. */
  214 +class Call : public Expr
  215 +{
  216 + protected:
  217 + Expr *base; // will be NULL if no explicit base
  218 + Identifier *field;
  219 + List<Expr*> *actuals;
  220 +
  221 + public:
  222 + Call() : Expr(), base(NULL), field(NULL), actuals(NULL) {}
  223 + Call(yyltype loc, Expr *base, Identifier *field, List<Expr*> *args);
  224 + const char *GetPrintNameForNode() { return "Call"; }
  225 + void PrintChildren(int indentLevel);
  226 +};
  227 +
  228 +class ActualsError : public Call
  229 +{
  230 + public:
  231 + ActualsError() : Call() { yyerror(this->GetPrintNameForNode()); }
  232 + const char *GetPrintNameForNode() { return "ActualsError"; }
  233 +};
  234 +
  235 +#endif
... ... @@ -0,0 +1,161 @@
  1 +/* File: ast_stmt.cc
  2 + * -----------------
  3 + * Implementation of statement node classes.
  4 + */
  5 +#include "ast_stmt.h"
  6 +#include "ast_type.h"
  7 +#include "ast_decl.h"
  8 +#include "ast_expr.h"
  9 +#include "symtable.h"
  10 +
  11 +#include "irgen.h"
  12 +#include "llvm/Bitcode/ReaderWriter.h"
  13 +#include "llvm/Support/raw_ostream.h"
  14 +
  15 +
  16 +Program::Program(List<Decl*> *d) {
  17 + Assert(d != NULL);
  18 + (decls=d)->SetParentAll(this);
  19 +}
  20 +
  21 +void Program::PrintChildren(int indentLevel) {
  22 + decls->PrintAll(indentLevel+1);
  23 + printf("\n");
  24 +}
  25 +
  26 +void Program::Emit() {
  27 + // TODO:
  28 + // This is just a reference for you to get started
  29 + //
  30 + // You can use this as a template and create Emit() function
  31 + // for individual node to fill in the module structure and instructions.
  32 + //
  33 + IRGenerator irgen;
  34 + llvm::Module *mod = irgen.GetOrCreateModule("Name_the_Module.bc");
  35 +
  36 + // create a function signature
  37 + std::vector<llvm::Type *> argTypes;
  38 + llvm::Type *intTy = irgen.GetIntType();
  39 + argTypes.push_back(intTy);
  40 + llvm::ArrayRef<llvm::Type *> argArray(argTypes);
  41 + llvm::FunctionType *funcTy = llvm::FunctionType::get(intTy, argArray, false);
  42 +
  43 + // llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("foo", intTy, intTy, (Type *)0));
  44 + llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("Name_the_function", funcTy));
  45 + llvm::Argument *arg = f->arg_begin();
  46 + arg->setName("x");
  47 +
  48 + // insert a block into the runction
  49 + llvm::LLVMContext *context = irgen.GetContext();
  50 + llvm::BasicBlock *bb = llvm::BasicBlock::Create(*context, "entry", f);
  51 +
  52 + // create a return instruction
  53 + llvm::Value *val = llvm::ConstantInt::get(intTy, 1);
  54 + llvm::Value *sum = llvm::BinaryOperator::CreateAdd(arg, val, "", bb);
  55 + llvm::ReturnInst::Create(*context, sum, bb);
  56 +
  57 + // write the BC into standard output
  58 + llvm::WriteBitcodeToFile(mod, llvm::outs());
  59 +}
  60 +
  61 +StmtBlock::StmtBlock(List<VarDecl*> *d, List<Stmt*> *s) {
  62 + Assert(d != NULL && s != NULL);
  63 + (decls=d)->SetParentAll(this);
  64 + (stmts=s)->SetParentAll(this);
  65 +}
  66 +
  67 +void StmtBlock::PrintChildren(int indentLevel) {
  68 + decls->PrintAll(indentLevel+1);
  69 + stmts->PrintAll(indentLevel+1);
  70 +}
  71 +
  72 +DeclStmt::DeclStmt(Decl *d) {
  73 + Assert(d != NULL);
  74 + (decl=d)->SetParent(this);
  75 +}
  76 +
  77 +void DeclStmt::PrintChildren(int indentLevel) {
  78 + decl->Print(indentLevel+1);
  79 +}
  80 +
  81 +ConditionalStmt::ConditionalStmt(Expr *t, Stmt *b) {
  82 + Assert(t != NULL && b != NULL);
  83 + (test=t)->SetParent(this);
  84 + (body=b)->SetParent(this);
  85 +}
  86 +
  87 +ForStmt::ForStmt(Expr *i, Expr *t, Expr *s, Stmt *b): LoopStmt(t, b) {
  88 + Assert(i != NULL && t != NULL && b != NULL);
  89 + (init=i)->SetParent(this);
  90 + step = s;
  91 + if ( s )
  92 + (step=s)->SetParent(this);
  93 +}
  94 +
  95 +void ForStmt::PrintChildren(int indentLevel) {
  96 + init->Print(indentLevel+1, "(init) ");
  97 + test->Print(indentLevel+1, "(test) ");
  98 + if ( step )
  99 + step->Print(indentLevel+1, "(step) ");
  100 + body->Print(indentLevel+1, "(body) ");
  101 +}
  102 +
  103 +void WhileStmt::PrintChildren(int indentLevel) {
  104 + test->Print(indentLevel+1, "(test) ");
  105 + body->Print(indentLevel+1, "(body) ");
  106 +}
  107 +
  108 +IfStmt::IfStmt(Expr *t, Stmt *tb, Stmt *eb): ConditionalStmt(t, tb) {
  109 + Assert(t != NULL && tb != NULL); // else can be NULL
  110 + elseBody = eb;
  111 + if (elseBody) elseBody->SetParent(this);
  112 +}
  113 +
  114 +void IfStmt::PrintChildren(int indentLevel) {
  115 + if (test) test->Print(indentLevel+1, "(test) ");
  116 + if (body) body->Print(indentLevel+1, "(then) ");
  117 + if (elseBody) elseBody->Print(indentLevel+1, "(else) ");
  118 +}
  119 +
  120 +
  121 +ReturnStmt::ReturnStmt(yyltype loc, Expr *e) : Stmt(loc) {
  122 + expr = e;
  123 + if (e != NULL) expr->SetParent(this);
  124 +}
  125 +
  126 +void ReturnStmt::PrintChildren(int indentLevel) {
  127 + if ( expr )
  128 + expr->Print(indentLevel+1);
  129 +}
  130 +
  131 +SwitchLabel::SwitchLabel(Expr *l, Stmt *s) {
  132 + Assert(l != NULL && s != NULL);
  133 + (label=l)->SetParent(this);
  134 + (stmt=s)->SetParent(this);
  135 +}
  136 +
  137 +SwitchLabel::SwitchLabel(Stmt *s) {
  138 + Assert(s != NULL);
  139 + label = NULL;
  140 + (stmt=s)->SetParent(this);
  141 +}
  142 +
  143 +void SwitchLabel::PrintChildren(int indentLevel) {
  144 + if (label) label->Print(indentLevel+1);
  145 + if (stmt) stmt->Print(indentLevel+1);
  146 +}
  147 +
  148 +SwitchStmt::SwitchStmt(Expr *e, List<Stmt *> *c, Default *d) {
  149 + Assert(e != NULL && c != NULL && c->NumElements() != 0 );
  150 + (expr=e)->SetParent(this);
  151 + (cases=c)->SetParentAll(this);
  152 + def = d;
  153 + if (def) def->SetParent(this);
  154 +}
  155 +
  156 +void SwitchStmt::PrintChildren(int indentLevel) {
  157 + if (expr) expr->Print(indentLevel+1);
  158 + if (cases) cases->PrintAll(indentLevel+1);
  159 + if (def) def->Print(indentLevel+1);
  160 +}
  161 +
... ... @@ -0,0 +1,208 @@
  1 +/* File: ast_stmt.h
  2 + * ----------------
  3 + * The Stmt class and its subclasses are used to represent
  4 + * statements in the parse tree. For each statment in the
  5 + * language (for, if, return, etc.) there is a corresponding
  6 + * node class for that construct.
  7 + *
  8 + * pp3: You will need to extend the Stmt classes to generate
  9 + * LLVM IR instructions.
  10 + */
  11 +
  12 +
  13 +#ifndef _H_ast_stmt
  14 +#define _H_ast_stmt
  15 +
  16 +#include "list.h"
  17 +#include "ast.h"
  18 +
  19 +class Decl;
  20 +class VarDecl;
  21 +class Expr;
  22 +class IntConstant;
  23 +
  24 +void yyerror(const char *msg);
  25 +
  26 +class Program : public Node
  27 +{
  28 + protected:
  29 + List<Decl*> *decls;
  30 +
  31 + public:
  32 + Program(List<Decl*> *declList);
  33 + const char *GetPrintNameForNode() { return "Program"; }
  34 + void PrintChildren(int indentLevel);
  35 + virtual void Emit();
  36 +};
  37 +
  38 +class Stmt : public Node
  39 +{
  40 + public:
  41 + Stmt() : Node() {}
  42 + Stmt(yyltype loc) : Node(loc) {}
  43 +};
  44 +
  45 +class StmtBlock : public Stmt
  46 +{
  47 + protected:
  48 + List<VarDecl*> *decls;
  49 + List<Stmt*> *stmts;
  50 +
  51 + public:
  52 + StmtBlock(List<VarDecl*> *variableDeclarations, List<Stmt*> *statements);
  53 + const char *GetPrintNameForNode() { return "StmtBlock"; }
  54 + void PrintChildren(int indentLevel);
  55 +};
  56 +
  57 +class DeclStmt: public Stmt
  58 +{
  59 + protected:
  60 + Decl* decl;
  61 +
  62 + public:
  63 + DeclStmt(Decl *d);
  64 + const char *GetPrintNameForNode() { return "DeclStmt"; }
  65 + void PrintChildren(int indentLevel);
  66 +
  67 +};
  68 +
  69 +class ConditionalStmt : public Stmt
  70 +{
  71 + protected:
  72 + Expr *test;
  73 + Stmt *body;
  74 +
  75 + public:
  76 + ConditionalStmt() : Stmt(), test(NULL), body(NULL) {}
  77 + ConditionalStmt(Expr *testExpr, Stmt *body);
  78 +
  79 +};
  80 +
  81 +class LoopStmt : public ConditionalStmt
  82 +{
  83 + public:
  84 + LoopStmt(Expr *testExpr, Stmt *body)
  85 + : ConditionalStmt(testExpr, body) {}
  86 +};
  87 +
  88 +class ForStmt : public LoopStmt
  89 +{
  90 + protected:
  91 + Expr *init, *step;
  92 +
  93 + public:
  94 + ForStmt(Expr *init, Expr *test, Expr *step, Stmt *body);
  95 + const char *GetPrintNameForNode() { return "ForStmt"; }
  96 + void PrintChildren(int indentLevel);
  97 +
  98 +};
  99 +
  100 +class WhileStmt : public LoopStmt
  101 +{
  102 + public:
  103 + WhileStmt(Expr *test, Stmt *body) : LoopStmt(test, body) {}
  104 + const char *GetPrintNameForNode() { return "WhileStmt"; }
  105 + void PrintChildren(int indentLevel);
  106 +
  107 +};
  108 +
  109 +class IfStmt : public ConditionalStmt
  110 +{
  111 + protected:
  112 + Stmt *elseBody;
  113 +
  114 + public:
  115 + IfStmt() : ConditionalStmt(), elseBody(NULL) {}
  116 + IfStmt(Expr *test, Stmt *thenBody, Stmt *elseBody);
  117 + const char *GetPrintNameForNode() { return "IfStmt"; }
  118 + void PrintChildren(int indentLevel);
  119 +
  120 +};
  121 +
  122 +class IfStmtExprError : public IfStmt
  123 +{
  124 + public:
  125 + IfStmtExprError() : IfStmt() { yyerror(this->GetPrintNameForNode()); }
  126 + const char *GetPrintNameForNode() { return "IfStmtExprError"; }
  127 +};
  128 +
  129 +class BreakStmt : public Stmt
  130 +{
  131 + public:
  132 + BreakStmt(yyltype loc) : Stmt(loc) {}
  133 + const char *GetPrintNameForNode() { return "BreakStmt"; }
  134 +
  135 +};
  136 +
  137 +class ContinueStmt : public Stmt
  138 +{
  139 + public:
  140 + ContinueStmt(yyltype loc) : Stmt(loc) {}
  141 + const char *GetPrintNameForNode() { return "ContinueStmt"; }
  142 +
  143 +};
  144 +
  145 +class ReturnStmt : public Stmt
  146 +{
  147 + protected:
  148 + Expr *expr;
  149 +
  150 + public:
  151 + ReturnStmt(yyltype loc, Expr *expr = NULL);
  152 + const char *GetPrintNameForNode() { return "ReturnStmt"; }
  153 + void PrintChildren(int indentLevel);
  154 +
  155 +};
  156 +
  157 +class SwitchLabel : public Stmt
  158 +{
  159 + protected:
  160 + Expr *label;
  161 + Stmt *stmt;
  162 +
  163 + public:
  164 + SwitchLabel() { label = NULL; stmt = NULL; }
  165 + SwitchLabel(Expr *label, Stmt *stmt);
  166 + SwitchLabel(Stmt *stmt);
  167 + void PrintChildren(int indentLevel);
  168 +
  169 +};
  170 +
  171 +class Case : public SwitchLabel
  172 +{
  173 + public:
  174 + Case() : SwitchLabel() {}
  175 + Case(Expr *label, Stmt *stmt) : SwitchLabel(label, stmt) {}
  176 + const char *GetPrintNameForNode() { return "Case"; }
  177 +};
  178 +
  179 +class Default : public SwitchLabel
  180 +{
  181 + public:
  182 + Default(Stmt *stmt) : SwitchLabel(stmt) {}
  183 + const char *GetPrintNameForNode() { return "Default"; }
  184 +};
  185 +
  186 +class SwitchStmt : public Stmt
  187 +{
  188 + protected:
  189 + Expr *expr;
  190 + List<Stmt*> *cases;
  191 + Default *def;
  192 +
  193 + public:
  194 + SwitchStmt() : expr(NULL), cases(NULL), def(NULL) {}
  195 + SwitchStmt(Expr *expr, List<Stmt*> *cases, Default *def);
  196 + virtual const char *GetPrintNameForNode() { return "SwitchStmt"; }
  197 + void PrintChildren(int indentLevel);
  198 +
  199 +};
  200 +
  201 +class SwitchStmtError : public SwitchStmt
  202 +{
  203 + public:
  204 + SwitchStmtError(const char * msg) { yyerror(msg); }
  205 + const char *GetPrintNameForNode() { return "SwitchStmtError"; }
  206 +};
  207 +
  208 +#endif
... ... @@ -0,0 +1,101 @@
  1 +/* File: ast_type.cc
  2 + * -----------------
  3 + * Implementation of type node classes.
  4 + */
  5 +
  6 +#include <string.h>
  7 +#include "ast_type.h"
  8 +#include "ast_decl.h"
  9 +
  10 +/* Class constants
  11 + * ---------------
  12 + * These are public constants for the built-in base types (int, double, etc.)
  13 + * They can be accessed with the syntax Type::intType. This allows you to
  14 + * directly access them and share the built-in types where needed rather that
  15 + * creates lots of copies.
  16 + */
  17 +
  18 +Type *Type::intType = new Type("int");
  19 +Type *Type::floatType = new Type("float");
  20 +Type *Type::voidType = new Type("void");
  21 +Type *Type::boolType = new Type("bool");
  22 +Type *Type::mat2Type = new Type("mat2");
  23 +Type *Type::mat3Type = new Type("mat3");
  24 +Type *Type::mat4Type = new Type("mat4");
  25 +Type *Type::vec2Type = new Type("vec2");
  26 +Type *Type::vec3Type = new Type("vec3");
  27 +Type *Type::vec4Type = new Type("vec4");
  28 +Type *Type::ivec2Type = new Type("ivec2");
  29 +Type *Type::ivec3Type = new Type("ivec3");
  30 +Type *Type::ivec4Type = new Type("ivec4");
  31 +Type *Type::bvec2Type = new Type("bvec2");
  32 +Type *Type::bvec3Type = new Type("bvec3");
  33 +Type *Type::bvec4Type = new Type("bvec4");
  34 +Type *Type::uintType = new Type("uint");
  35 +Type *Type::uvec2Type = new Type("uvec2");
  36 +Type *Type::uvec3Type = new Type("uvec3");
  37 +Type *Type::uvec4Type = new Type("uvec4");
  38 +Type *Type::errorType = new Type("error");
  39 +
  40 +TypeQualifier *TypeQualifier::inTypeQualifier = new TypeQualifier("in");
  41 +TypeQualifier *TypeQualifier::outTypeQualifier = new TypeQualifier("out");
  42 +TypeQualifier *TypeQualifier::constTypeQualifier = new TypeQualifier("const");
  43 +TypeQualifier *TypeQualifier::uniformTypeQualifier = new TypeQualifier("uniform");
  44 +
  45 +Type::Type(const char *n) {
  46 + Assert(n);
  47 + typeName = strdup(n);
  48 +}
  49 +
  50 +void Type::PrintChildren(int indentLevel) {
  51 + printf("%s", typeName);
  52 +}
  53 +
  54 +TypeQualifier::TypeQualifier(const char *n) {
  55 + Assert(n);
  56 + typeQualifierName = strdup(n);
  57 +}
  58 +
  59 +void TypeQualifier::PrintChildren(int indentLevel) {
  60 + printf("%s", typeQualifierName);
  61 +}
  62 +
  63 +bool Type::IsNumeric() {
  64 + return this->IsEquivalentTo(Type::intType) || this->IsEquivalentTo(Type::floatType);
  65 +}
  66 +
  67 +bool Type::IsVector() {
  68 + return this->IsEquivalentTo(Type::vec2Type) ||
  69 + this->IsEquivalentTo(Type::vec3Type) ||
  70 + this->IsEquivalentTo(Type::vec4Type);
  71 +}
  72 +
  73 +bool Type::IsMatrix() {
  74 + return this->IsEquivalentTo(Type::mat2Type) ||
  75 + this->IsEquivalentTo(Type::mat3Type) ||
  76 + this->IsEquivalentTo(Type::mat4Type);
  77 +}
  78 +
  79 +bool Type::IsError() {
  80 + return this->IsEquivalentTo(Type::errorType);
  81 +}
  82 +
  83 +NamedType::NamedType(Identifier *i) : Type(*i->GetLocation()) {
  84 + Assert(i != NULL);
  85 + (id=i)->SetParent(this);
  86 +}
  87 +
  88 +void NamedType::PrintChildren(int indentLevel) {
  89 + id->Print(indentLevel+1);
  90 +}
  91 +
  92 +ArrayType::ArrayType(yyltype loc, Type *et, int ec) : Type(loc) {
  93 + Assert(et != NULL);
  94 + (elemType=et)->SetParent(this);
  95 + elemCount=ec;
  96 +}
  97 +void ArrayType::PrintChildren(int indentLevel) {
  98 + elemType->Print(indentLevel+1);
  99 +}
  100 +
  101 +
... ... @@ -0,0 +1,96 @@
  1 +/* File: ast_type.h
  2 + * ----------------
  3 + * In our parse tree, Type nodes are used to represent and
  4 + * store type information. The base Type class is used
  5 + * for built-in types, the NamedType for classes and interfaces,
  6 + * and the ArrayType for arrays of other types.
  7 + *
  8 + * pp3: You will need to extend the Type classes to implement
  9 + * the type system and rules for type equivalency and compatibility.
  10 + */
  11 +
  12 +#ifndef _H_ast_type
  13 +#define _H_ast_type
  14 +
  15 +#include "ast.h"
  16 +#include "list.h"
  17 +#include <iostream>
  18 +
  19 +using namespace std;
  20 +
  21 +class TypeQualifier : public Node
  22 +{
  23 + protected:
  24 + char *typeQualifierName;
  25 +
  26 + public :
  27 + static TypeQualifier *inTypeQualifier, *outTypeQualifier, *constTypeQualifier, *uniformTypeQualifier;
  28 +
  29 + TypeQualifier(yyltype loc) : Node(loc) {}
  30 + TypeQualifier(const char *str);
  31 +
  32 + const char *GetPrintNameForNode() { return "TypeQualifier"; }
  33 + void PrintChildren(int indentLevel);
  34 +};
  35 +
  36 +class Type : public Node
  37 +{
  38 + protected:
  39 + char *typeName;
  40 +
  41 + public :
  42 + static Type *intType, *uintType,*floatType, *boolType, *voidType,
  43 + *vec2Type, *vec3Type, *vec4Type,
  44 + *mat2Type, *mat3Type, *mat4Type,
  45 + *ivec2Type, *ivec3Type, *ivec4Type,
  46 + *bvec2Type, *bvec3Type, *bvec4Type,
  47 + *uvec2Type, *uvec3Type,*uvec4Type,
  48 + *errorType;
  49 +
  50 + Type(yyltype loc) : Node(loc) {}
  51 + Type(const char *str);
  52 +
  53 + const char *GetPrintNameForNode() { return "Type"; }
  54 + void PrintChildren(int indentLevel);
  55 +
  56 + virtual void PrintToStream(ostream& out) { out << typeName; }
  57 + friend ostream& operator<<(ostream& out, Type *t) { t->PrintToStream(out); return out; }
  58 + virtual bool IsEquivalentTo(Type *other) { return (this == other); }
  59 + virtual bool IsConvertibleTo(Type *other) { return (this == other || this == errorType); }
  60 + bool IsNumeric();
  61 + bool IsVector();
  62 + bool IsMatrix();
  63 + bool IsError();
  64 +};
  65 +
  66 +
  67 +class NamedType : public Type
  68 +{
  69 + protected:
  70 + Identifier *id;
  71 +
  72 + public:
  73 + NamedType(Identifier *i);
  74 +
  75 + const char *GetPrintNameForNode() { return "NamedType"; }
  76 + void PrintChildren(int indentLevel);
  77 + void PrintToStream(ostream& out) { out << id; }
  78 +};
  79 +
  80 +class ArrayType : public Type
  81 +{
  82 + protected:
  83 + Type *elemType;
  84 + int elemCount;
  85 +
  86 + public:
  87 + ArrayType(yyltype loc, Type *elemType, int elemCount);
  88 +
  89 + const char *GetPrintNameForNode() { return "ArrayType"; }
  90 + void PrintChildren(int indentLevel);
  91 + void PrintToStream(ostream& out) { out << elemType << "[]"; }
  92 + Type *GetElemType() {return elemType;}
  93 +};
  94 +
  95 +
  96 +#endif
... ... @@ -0,0 +1,208 @@
  1 +/**
  2 + * File: errors.cc
  3 + * ---------------
  4 + * Implementation for error-reporting class.
  5 + */
  6 +
  7 +#include "errors.h"
  8 +#include <sstream>
  9 +#include <stdarg.h>
  10 +#include <stdio.h>
  11 +
  12 +using namespace std;
  13 +
  14 +#include "scanner.h" // for GetLineNumbered
  15 +#include "ast_type.h"
  16 +#include "ast_expr.h"
  17 +#include "ast_stmt.h"
  18 +#include "ast_decl.h"
  19 +
  20 +int ReportError::numErrors = 0;
  21 +
  22 +void ReportError::UnderlineErrorInLine(const char *line, yyltype *pos) {
  23 + if (!line) return;
  24 + cerr << line << endl;
  25 + for (int i = 1; i <= pos->last_column; i++)
  26 + cerr << (i >= pos->first_column ? '^' : ' ');
  27 + cerr << endl;
  28 +}
  29 +
  30 +
  31 +
  32 +void ReportError::OutputError(yyltype *loc, string msg) {
  33 + numErrors++;
  34 + fflush(stdout); // make sure any buffered text has been output
  35 + if (loc) {
  36 + cerr << endl << "*** Error line " << loc->first_line << "." << endl;
  37 + UnderlineErrorInLine(GetLineNumbered(loc->first_line), loc);
  38 + } else
  39 + cerr << endl << "*** Error." << endl;
  40 + cerr << "*** " << msg << endl << endl;
  41 +}
  42 +
  43 +
  44 +void ReportError::Formatted(yyltype *loc, const char *format, ...) {
  45 + va_list args;
  46 + char errbuf[2048];
  47 +
  48 + va_start(args, format);
  49 + vsprintf(errbuf,format, args);
  50 + va_end(args);
  51 + OutputError(loc, errbuf);
  52 +}
  53 +
  54 +void ReportError::UntermComment() {
  55 + OutputError(NULL, "Input ends with unterminated comment");
  56 +}
  57 +
  58 +
  59 +void ReportError::LongIdentifier(yyltype *loc, const char *ident) {
  60 + ostringstream s;
  61 + s << "Identifier too long: \"" << ident << "\"";
  62 + OutputError(loc, s.str());
  63 +}
  64 +
  65 +void ReportError::UntermString(yyltype *loc, const char *str) {
  66 + ostringstream s;
  67 + s << "Unterminated string constant: " << str;
  68 + OutputError(loc, s.str());
  69 +}
  70 +
  71 +void ReportError::UnrecogChar(yyltype *loc, char ch) {
  72 + ostringstream s;
  73 + s << "Unrecognized char: '" << ch << "'";
  74 + OutputError(loc, s.str());
  75 +}
  76 +
  77 +void ReportError::DeclConflict(Decl *decl, Decl *prevDecl) {
  78 + ostringstream s;
  79 + s << "Declaration of '" << decl << "' here conflicts with declaration on line "
  80 + << prevDecl->GetLocation()->first_line;
  81 + OutputError(decl->GetLocation(), s.str());
  82 +}
  83 +
  84 +void ReportError::InvalidInitialization(Identifier *id, Type *lType, Type *rType) {
  85 + ostringstream s;
  86 + s << "Wrong initialization of identifier '" << id << "': idType '"
  87 + << lType << "' exprType '" << rType << "'" ;
  88 + OutputError(id->GetLocation(), s.str());
  89 +}
  90 +
  91 +void ReportError::IdentifierNotDeclared(Identifier *ident, reasonT whyNeeded) {
  92 + ostringstream s;
  93 + static const char *names[] = {"type", "variable", "function"};
  94 + Assert(whyNeeded >= 0 && whyNeeded <= sizeof(names)/sizeof(names[0]));
  95 + s << "No declaration found for "<< names[whyNeeded] << " '" << ident << "'";
  96 + OutputError(ident->GetLocation(), s.str());
  97 +}
  98 +
  99 +void ReportError::ExtraFormals(Identifier *id, int expCount, int actualCount) {
  100 + ostringstream s;
  101 + s << "Extra arguments given to function '" << id << "': expected "
  102 + << expCount << ", given " << actualCount ;
  103 + OutputError(id->GetLocation(), s.str());
  104 +}
  105 +
  106 +void ReportError::LessFormals(Identifier *id, int expCount, int actualCount) {
  107 + ostringstream s;
  108 + s << "Less arguments given to function '" << id << "': expected "
  109 + << expCount << ", given " << actualCount ;
  110 + OutputError(id->GetLocation(), s.str());
  111 +}
  112 +
  113 +void ReportError::FormalsTypeMismatch(Identifier *id, int pos, Type *expType, Type *actualType)
  114 +{
  115 + ostringstream s;
  116 + s << "Formal type mismatch in function '" << id << "' at pos " << pos
  117 + << ": expected '" << expType << "', given '" << actualType <<"'";
  118 + OutputError(id->GetLocation(), s.str());
  119 +}
  120 +
  121 +void ReportError::NotAFunction(Identifier *id) {
  122 + ostringstream s;
  123 + s << "'" << id << "' is not a function.";
  124 + OutputError(id->GetLocation(), s.str());
  125 +}
  126 +
  127 +void ReportError::NotAnArray(Identifier *id) {
  128 + ostringstream s;
  129 + s << "'" << id << "' is not an array.";
  130 + OutputError(id->GetLocation(), s.str());
  131 +}
  132 +
  133 +void ReportError::IncompatibleOperands(Operator *op, Type *lhs, Type *rhs) {
  134 + ostringstream s;
  135 + s << "Incompatible operands: " << lhs << " " << op << " " << rhs;
  136 + OutputError(op->GetLocation(), s.str());
  137 +}
  138 +
  139 +void ReportError::IncompatibleOperand(Operator *op, Type *rhs) {
  140 + ostringstream s;
  141 + s << "Incompatible operand: " << op << " " << rhs;
  142 + OutputError(op->GetLocation(), s.str());
  143 +}
  144 +
  145 +void ReportError::ReturnMismatch(ReturnStmt *rStmt, Type *given, Type *expected) {
  146 + ostringstream s;
  147 + s << "Incompatible return: " << given << " given, " << expected << " expected";
  148 + OutputError(rStmt->GetLocation(), s.str());
  149 +}
  150 +
  151 +void ReportError::ReturnMissing(FnDecl *fnDecl) {
  152 + ostringstream s;
  153 + s << "Declaration of '" << fnDecl << "' on line "
  154 + << fnDecl->GetLocation()->first_line
  155 + << " doesn't have a return";
  156 + OutputError(fnDecl->GetLocation(), s.str());
  157 +}
  158 +
  159 +void ReportError::InaccessibleSwizzle(Identifier *field, Expr *base) {
  160 + ostringstream s;
  161 + s << base << " non-vector type can't have swizzle '" << field <<"'";
  162 + OutputError(field->GetLocation(), s.str());
  163 +}
  164 +
  165 +void ReportError::InvalidSwizzle(Identifier *field, Expr *base) {
  166 + ostringstream s;
  167 + s << base << " swizzle '" << field <<"' is not proper subset of [xyzw]";
  168 + OutputError(field->GetLocation(), s.str());
  169 +}
  170 +
  171 +void ReportError::SwizzleOutOfBound(Identifier *field, Expr *base) {
  172 + ostringstream s;
  173 + s << base << " swizzle '" << field <<"' exceeds its vector component";
  174 + OutputError(field->GetLocation(), s.str());
  175 +}
  176 +
  177 +void ReportError::OversizedVector(Identifier *field, Expr *base) {
  178 + ostringstream s;
  179 + s << base << " swizzle '" << field <<"' generates a vector longer than vec4";
  180 + OutputError(field->GetLocation(), s.str());
  181 +}
  182 +
  183 +void ReportError::TestNotBoolean(Expr *expr) {
  184 + OutputError(expr->GetLocation(), "Test expression must have boolean type");
  185 +}
  186 +
  187 +void ReportError::BreakOutsideLoop(BreakStmt *bStmt) {
  188 + OutputError(bStmt->GetLocation(), "break is only allowed inside a loop");
  189 +}
  190 +
  191 +void ReportError::ContinueOutsideLoop(ContinueStmt *cStmt) {
  192 + OutputError(cStmt->GetLocation(), "continue is only allowed inside a loop");
  193 +}
  194 +
  195 +/**
  196 + * Function: yyerror()
  197 + * -------------------
  198 + * Standard error-reporting function expected by yacc. Our version merely
  199 + * just calls into the error reporter above, passing the location of
  200 + * the last token read. If you want to suppress the ordinary "parse error"
  201 + * message from yacc, you can implement yyerror to do nothing and
  202 + * then call ReportError::Formatted yourself with a more descriptive
  203 + * message.
  204 + */
  205 +
  206 +void yyerror(const char *msg) {
  207 + ReportError::Formatted(&yylloc, "%s", msg);
  208 +}
... ... @@ -0,0 +1,114 @@
  1 +/**
  2 + * File: errors.h
  3 + * --------------
  4 + * This file defines an error-reporting class with a set of already
  5 + * implemented static methods for reporting the standard Decaf errors.
  6 + * You should report all errors via this class so that your error
  7 + * messages will have the same wording/spelling as ours and thus
  8 + * diff can easily compare the two. If needed, you can add new
  9 + * methods if you have some fancy error-reporting, but for the most
  10 + * part, you will just use the class as given.
  11 + */
  12 +
  13 +#ifndef _errors_h_
  14 +#define _errors_h_
  15 +
  16 +#include <string>
  17 +#include "location.h"
  18 +#include "ast_decl.h"
  19 +
  20 +using namespace std;
  21 +
  22 +/**
  23 + * General notes on using this class
  24 + * ----------------------------------
  25 + * Each of the methods in thie class matches one of the standard Decaf
  26 + * errors and reports a specific problem such as an unterminated string,
  27 + * type mismatch, declaration conflict, etc. You will call these methods
  28 + * to report problems encountered during the analysis phases. All methods
  29 + * on this class are static, thus you can invoke methods directly via
  30 + * the class name, e.g.
  31 + *
  32 + * if (missingEnd) {
  33 + * ReportError::UntermString(&yylloc, str);
  34 + * }
  35 + *
  36 + * For some methods, the first argument is the pointer to the location
  37 + * structure that identifies where the problem is (usually this is the
  38 + * location of the offending token). You can pass NULL for the argument
  39 + * if there is no appropriate position to point out. For other methods,
  40 + * location is accessed by messaging the node in error which is passed
  41 + * as an argument. You cannot pass NULL for these arguments.
  42 + */
  43 +
  44 +class Type;
  45 +class Identifier;
  46 +class Expr;
  47 +class BreakStmt;
  48 +class ContinueStmt;
  49 +class ReturnStmt;
  50 +class Decl;
  51 +class Operator;
  52 +
  53 +typedef enum {
  54 + LookingForType,
  55 + LookingForVariable,
  56 + LookingForFunction
  57 +} reasonT;
  58 +
  59 +class ReportError {
  60 + public:
  61 +
  62 + // Errors used by scanner
  63 + static void UntermComment();
  64 + static void LongIdentifier(yyltype *loc, const char *ident);
  65 + static void UntermString(yyltype *loc, const char *str);
  66 + static void UnrecogChar(yyltype *loc, char ch);
  67 +
  68 + // Errors used by semantic analyzer for declarations
  69 + static void DeclConflict(Decl *newDecl, Decl *prevDecl);
  70 + static void InvalidInitialization(Identifier *id, Type *lType, Type *rType);
  71 +
  72 +
  73 + // Errors used by semantic analyzer for identifiers
  74 + static void IdentifierNotDeclared(Identifier *ident, reasonT whyNeeded);
  75 +
  76 + // Errors used by semantic analyzer for arrays
  77 + static void NotAnArray(Identifier *id);
  78 +
  79 + // Errors used by semantic analyzer for expressions
  80 + static void IncompatibleOperand(Operator *op, Type *rhs); // unary
  81 + static void IncompatibleOperands(Operator *op, Type *lhs, Type *rhs); // binary
  82 +
  83 + // Errors used by semantic analyzer for function calls
  84 + static void ExtraFormals(Identifier *id, int expCount, int actualCount);
  85 + static void LessFormals(Identifier *id, int expCount, int actualCount);
  86 + static void FormalsTypeMismatch(Identifier *id, int pos, Type *expType, Type *actualType);
  87 + static void NotAFunction(Identifier *id);
  88 +
  89 + // Errors used by semantic analyzer for vector access
  90 + static void InaccessibleSwizzle(Identifier *swizzle, Expr *base);
  91 + static void InvalidSwizzle(Identifier *swizzle, Expr *base);
  92 + static void SwizzleOutOfBound(Identifier *swizzle, Expr *base);
  93 + static void OversizedVector(Identifier *swizzle, Expr *base);
  94 +
  95 + // Errors used by semantic analyzer for control structures
  96 + static void TestNotBoolean(Expr *testExpr);
  97 + static void ReturnMismatch(ReturnStmt *rStmt, Type *given, Type *expected);
  98 + static void ReturnMissing(FnDecl *fnDecl);
  99 + static void BreakOutsideLoop(BreakStmt *bStmt);
  100 + static void ContinueOutsideLoop(ContinueStmt *cStmt);
  101 +
  102 + // Generic method to report a printf-style error message
  103 + static void Formatted(yyltype *loc, const char *format, ...);
  104 +
  105 +
  106 + // Returns number of error messages printed
  107 + static int NumErrors() { return numErrors; }
  108 +
  109 + private:
  110 + static void UnderlineErrorInLine(const char *line, yyltype *pos);
  111 + static void OutputError(yyltype *loc, string msg);
  112 + static int numErrors;
  113 +};
  114 +#endif

No preview for this file type

... ... @@ -0,0 +1,64 @@
  1 +/* irgen.cc - LLVM IR generator
  2 + *
  3 + * You can implement any LLVM related functions here.
  4 + */
  5 +
  6 +#include "irgen.h"
  7 +
  8 +IRGenerator::IRGenerator() :
  9 + context(NULL),
  10 + module(NULL),
  11 + currentFunc(NULL),
  12 + currentBB(NULL)
  13 +{
  14 +}
  15 +
  16 +IRGenerator::~IRGenerator() {
  17 +}
  18 +
  19 +llvm::Module *IRGenerator::GetOrCreateModule(const char *moduleID)
  20 +{
  21 + if ( module == NULL ) {
  22 + context = new llvm::LLVMContext();
  23 + module = new llvm::Module(moduleID, *context);
  24 + module->setTargetTriple(TargetTriple);
  25 + module->setDataLayout(TargetLayout);
  26 + }
  27 + return module;
  28 +}
  29 +
  30 +void IRGenerator::SetFunction(llvm::Function *func) {
  31 + currentFunc = func;
  32 +}
  33 +
  34 +llvm::Function *IRGenerator::GetFunction() const {
  35 + return currentFunc;
  36 +}
  37 +
  38 +void IRGenerator::SetBasicBlock(llvm::BasicBlock *bb) {
  39 + currentBB = bb;
  40 +}
  41 +
  42 +llvm::BasicBlock *IRGenerator::GetBasicBlock() const {
  43 + return currentBB;
  44 +}
  45 +
  46 +llvm::Type *IRGenerator::GetIntType() const {
  47 + llvm::Type *ty = llvm::Type::getInt32Ty(*context);
  48 + return ty;
  49 +}
  50 +
  51 +llvm::Type *IRGenerator::GetBoolType() const {
  52 + llvm::Type *ty = llvm::Type::getInt1Ty(*context);
  53 + return ty;
  54 +}
  55 +
  56 +llvm::Type *IRGenerator::GetFloatType() const {
  57 + llvm::Type *ty = llvm::Type::getFloatTy(*context);
  58 + return ty;
  59 +}
  60 +
  61 +const char *IRGenerator::TargetLayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128";
  62 +
  63 +const char *IRGenerator::TargetTriple = "x86_64-redhat-linux-gnu";
  64 +
... ... @@ -0,0 +1,52 @@
  1 +/**
  2 + * File: irgen.h
  3 + * -----------
  4 + * This file defines a class for LLVM IR Generation.
  5 + *
  6 + * All LLVM instruction related functions or utilities can be implemented
  7 + * here. You'll need to customize this class heavily to provide any helpers
  8 + * or untility as you need.
  9 + */
  10 +
  11 +#ifndef _H_IRGen
  12 +#define _H_IRGen
  13 +
  14 +// LLVM headers
  15 +#include "llvm/IR/Module.h"
  16 +#include "llvm/IR/LLVMContext.h"
  17 +#include "llvm/IR/Instructions.h"
  18 +#include "llvm/IR/Constants.h"
  19 +
  20 +class IRGenerator {
  21 + public:
  22 + IRGenerator();
  23 + ~IRGenerator();
  24 +
  25 + llvm::Module *GetOrCreateModule(const char *moduleID);
  26 + llvm::LLVMContext *GetContext() const { return context; }
  27 +
  28 + // Add your helper functions here
  29 + llvm::Function *GetFunction() const;
  30 + void SetFunction(llvm::Function *func);
  31 +
  32 + llvm::BasicBlock *GetBasicBlock() const;
  33 + void SetBasicBlock(llvm::BasicBlock *bb);
  34 +
  35 + llvm::Type *GetIntType() const;
  36 + llvm::Type *GetBoolType() const;
  37 + llvm::Type *GetFloatType() const;
  38 +
  39 + private:
  40 + llvm::LLVMContext *context;
  41 + llvm::Module *module;
  42 +
  43 + // track which function or basic block is active
  44 + llvm::Function *currentFunc;
  45 + llvm::BasicBlock *currentBB;
  46 +
  47 + static const char *TargetTriple;
  48 + static const char *TargetLayout;
  49 +};
  50 +
  51 +#endif
  52 +
... ... @@ -0,0 +1,88 @@
  1 +/**
  2 + * File: list.h
  3 + * ------------
  4 + * Simple list class for storing a linear collection of elements. It
  5 + * supports operations similar in name to the CS107 CVector -- nth, insert,
  6 + * append, remove, etc. This class is nothing more than a very thin
  7 + * cover of a STL deque, with some added range-checking. Given not everyone
  8 + * is familiar with the C++ templates, this class provides a more familiar
  9 + * interface.
  10 + *
  11 + * It can handle elements of any type, the typename for a List includes the
  12 + * element type in angle brackets, e.g. to store elements of type double,
  13 + * you would use the type name List<double>, to store elements of type
  14 + * Decl *, it woud be List<Decl*> and so on.
  15 + *
  16 + * Here is some sample code illustrating the usage of a List of integers
  17 + *
  18 + * int Sum(List<int> *list) {
  19 + * int sum = 0;
  20 + * for (int i = 0; i < list->NumElements(); i++) {
  21 + * int val = list->Nth(i);
  22 + * sum += val;
  23 + * }
  24 + * return sum;
  25 + * }
  26 + */
  27 +
  28 +#ifndef _H_list
  29 +#define _H_list
  30 +
  31 +#include <deque>
  32 +#include "utility.h" // for Assert()
  33 +using namespace std;
  34 +
  35 +class Node;
  36 +
  37 +template<class Element> class List {
  38 +
  39 + private:
  40 + deque<Element> elems;
  41 +
  42 + public:
  43 + // Create a new empty list
  44 + List() {}
  45 +
  46 + // Returns count of elements currently in list
  47 + int NumElements() const
  48 + { return elems.size(); }
  49 +
  50 + // Returns element at index in list. Indexing is 0-based.
  51 + // Raises an assert if index is out of range.
  52 + Element Nth(int index) const
  53 + { Assert(index >= 0 && index < NumElements());
  54 + return elems[index]; }
  55 +
  56 + // Inserts element at index, shuffling over others
  57 + // Raises assert if index out of range
  58 + void InsertAt(const Element &elem, int index)
  59 + { Assert(index >= 0 && index <= NumElements());
  60 + elems.insert(elems.begin() + index, elem); }
  61 +
  62 + // Adds element to list end
  63 + void Append(const Element &elem)
  64 + { elems.push_back(elem); }
  65 +
  66 + // Removes element at index, shuffling down others
  67 + // Raises assert if index out of range
  68 + void RemoveAt(int index)
  69 + { Assert(index >= 0 && index < NumElements());
  70 + elems.erase(elems.begin() + index); }
  71 +
  72 + // These are some specific methods useful for lists of ast nodes
  73 + // They will only work on lists of elements that respond to the
  74 + // messages, but since C++ only instantiates the template if you use
  75 + // you can still have Lists of ints, chars*, as long as you
  76 + // don't try to SetParentAll on that list.
  77 + void SetParentAll(Node *p)
  78 + { for (int i = 0; i < NumElements(); i++)
  79 + Nth(i)->SetParent(p); }
  80 + void PrintAll(int indentLevel, const char *label = NULL)
  81 + { for (int i = 0; i < NumElements(); i++)
  82 + Nth(i)->Print(indentLevel, label); }
  83 +
  84 +
  85 +};
  86 +
  87 +#endif
  88 +
... ... @@ -0,0 +1,59 @@
  1 +/* File: location.h
  2 + * ----------------
  3 + * This file just contains features relative to the location structure
  4 + * used to record the lexical position of a token or symbol. This file
  5 + * establishes the cmoon definition for the yyltype structure, the global
  6 + * variable yylloc, and a utility function to join locations you might
  7 + * find handy at times.
  8 + */
  9 +
  10 +#ifndef YYLTYPE
  11 +
  12 +/* Typedef: yyltype
  13 + * ----------------
  14 + * Defines the struct type that is used by the scanner to store
  15 + * position information about each lexeme scanned.
  16 + */
  17 +typedef struct yyltype
  18 +{
  19 + int timestamp; // you can ignore this field
  20 + int first_line, first_column;
  21 + int last_line, last_column;
  22 + char *text; // you can also ignore this field
  23 +} yyltype;
  24 +
  25 +#define YYLTYPE yyltype
  26 +
  27 +
  28 +/* Global variable: yylloc
  29 + * ------------------------
  30 + * The global variable holding the position information about the
  31 + * lexeme just scanned.
  32 + */
  33 +extern struct yyltype yylloc;
  34 +
  35 +
  36 +/* Function: Join
  37 + * --------------
  38 + * Takes two locations and returns a new location which represents
  39 + * the span from first to last, inclusive.
  40 + */
  41 +inline yyltype Join(yyltype first, yyltype last)
  42 +{
  43 + yyltype combined;
  44 + combined.first_column = first.first_column;
  45 + combined.first_line = first.first_line;
  46 + combined.last_column = last.last_column;
  47 + combined.last_line = last.last_line;
  48 + return combined;
  49 +}
  50 +
  51 +/* Same as above, except operates on pointers as a convenience */
  52 +inline yyltype Join(yyltype *firstPtr, yyltype *lastPtr)
  53 +{
  54 + return Join(*firstPtr, *lastPtr);
  55 +}
  56 +
  57 +
  58 +#endif
  59 +
... ... @@ -0,0 +1,30 @@
  1 +/* File: main.cc
  2 + * -------------
  3 + * This file defines the main() routine for the program and not much else.
  4 + * You should not need to modify this file.
  5 + */
  6 +
  7 +#include <string.h>
  8 +#include <stdio.h>
  9 +#include "utility.h"
  10 +#include "errors.h"
  11 +#include "parser.h"
  12 +
  13 +
  14 +/* Function: main()
  15 + * ----------------
  16 + * Entry point to the entire program. We parse the command line and turn
  17 + * on any debugging flags requested by the user when invoking the program.
  18 + * InitScanner() is used to set up the scanner.
  19 + * InitParser() is used to set up the parser. The call to yyparse() will
  20 + * attempt to parse a complete program from the input.
  21 + */
  22 +int main(int argc, char *argv[])
  23 +{
  24 + ParseCommandLine(argc, argv);
  25 + InitScanner();
  26 + InitParser();
  27 + yyparse();
  28 + return (ReportError::NumErrors() == 0? 0 : -1);
  29 +}
  30 +
... ... @@ -0,0 +1,38 @@
  1 +/* File: parser.h
  2 + * --------------
  3 + * This file provides constants and type definitions that will
  4 + * are used and/or exported by the yacc-generated parser.
  5 + */
  6 +
  7 +#ifndef _H_parser
  8 +#define _H_parser
  9 +
  10 + // here we need to include things needed for the yylval union
  11 + // (types, classes, constants, etc.)
  12 +
  13 +#include "scanner.h" // for MaxIdentLen
  14 +#include "list.h" // because we use all these types
  15 +#include "ast.h" // in the union, we need their declarations
  16 +#include "ast_type.h"
  17 +#include "ast_decl.h"
  18 +#include "ast_expr.h"
  19 +#include "ast_stmt.h"
  20 +
  21 +
  22 +// Next, we want to get the exported defines for the token codes and
  23 +// typedef for YYSTYPE and exported global variable yylval. These
  24 +// definitions are generated and written to the y.tab.h header file. But
  25 +// because that header does not have any protection against being
  26 +// re-included and those definitions are also present in the y.tab.c,
  27 +// we can get into trouble if we don't take precaution to not include if
  28 +// we are compiling y.tab.c, which we use the YYBISON symbol for.
  29 +// Managing C headers can be such a mess!
  30 +
  31 +#ifndef YYBISON
  32 +#include "y.tab.h"
  33 +#endif
  34 +
  35 +int yyparse(); // Defined in the generated y.tab.c file
  36 +void InitParser(); // Defined in parser.y
  37 +
  38 +#endif
... ... @@ -0,0 +1,504 @@
  1 +/* File: parser.y
  2 + * --------------
  3 + * Bison input file to generate the parser for the compiler.
  4 + *
  5 + * pp2: your job is to write a parser that will construct the parse tree
  6 + * and if no parse errors were found, print it. The parser should
  7 + * accept the language as described in specification, and as augmented
  8 + * in the pp2 handout.
  9 + */
  10 +
  11 +%{
  12 +
  13 +/* Just like lex, the text within this first region delimited by %{ and %}
  14 + * is assumed to be C/C++ code and will be copied verbatim to the y.tab.c
  15 + * file ahead of the definitions of the yyparse() function. Add other header
  16 + * file inclusions or C++ variable declarations/prototypes that are needed
  17 + * by your code here.
  18 + */
  19 +#include "scanner.h" // for yylex
  20 +#include "parser.h"
  21 +#include "errors.h"
  22 +
  23 +void yyerror(const char *msg); // standard error-handling routine
  24 +
  25 +%}
  26 +
  27 +/* The section before the first %% is the Definitions section of the yacc
  28 + * input file. Here is where you declare tokens and types, add precedence
  29 + * and associativity options, and so on.
  30 + */
  31 +
  32 +/* yylval
  33 + * ------
  34 + * Here we define the type of the yylval global variable that is used by
  35 + * the scanner to store attibute information about the token just scanned
  36 + * and thus communicate that information to the parser.
  37 + *
  38 + * pp2: You will need to add new fields to this union as you add different
  39 + * attributes to your non-terminal symbols.
  40 + */
  41 +%union {
  42 + int integerConstant;
  43 + bool boolConstant;
  44 + double floatConstant;
  45 + char identifier[MaxIdentLen+1]; // +1 for terminating null
  46 + Decl *decl;
  47 + FnDecl *funcDecl;
  48 + List<Decl*> *declList;
  49 + Type *typeDecl;
  50 + TypeQualifier *typeQualifier;
  51 + Expr *expression;
  52 + VarDecl *varDecl;
  53 + List<VarDecl *> *varDeclList;
  54 + List<Stmt*> *stmtList;
  55 + Stmt *stmt;
  56 + Operator *ops;
  57 + Identifier *funcId;
  58 + List<Expr*> *argList;
  59 +}
  60 +
  61 +
  62 +/* Tokens
  63 + * ------
  64 + * Here we tell yacc about all the token types that we are using.
  65 + * Bison will assign unique numbers to these and export the #define
  66 + * in the generated y.tab.h header file.
  67 + */
  68 +%token T_Void T_Bool T_Int T_Float T_Uint
  69 +%token T_Bvec2 T_Bvec3 T_Bvec4 T_Ivec2 T_Ivec3 T_Ivec4
  70 +%token T_Uvec2 T_Uvec3 T_Uvec4 T_Vec2 T_Vec3 T_Vec4
  71 +%token T_Mat2 T_Mat3 T_Mat4
  72 +%token T_While T_For T_If T_Else T_Return T_Break T_Continue T_Do
  73 +%token T_Switch T_Case T_Default
  74 +%token T_In T_Out T_Const T_Uniform
  75 +%token T_LeftParen T_RightParen T_LeftBracket T_RightBracket T_LeftBrace T_RightBrace
  76 +%token T_Dot T_Comma T_Colon T_Semicolon T_Question
  77 +
  78 +%token <identifier> T_LessEqual T_GreaterEqual T_EQ T_NE
  79 +%token <identifier> T_And T_Or
  80 +%token <identifier> T_Plus T_Star
  81 +%token <identifier> T_MulAssign T_DivAssign T_AddAssign T_SubAssign T_Equal
  82 +%token <identifier> T_LeftAngle T_RightAngle T_Dash T_Slash
  83 +%token <identifier> T_Inc T_Dec
  84 +%token <identifier> T_Identifier
  85 +%token <integerConstant> T_IntConstant
  86 +%token <floatConstant> T_FloatConstant
  87 +%token <boolConstant> T_BoolConstant
  88 +%token <identifier> T_FieldSelection
  89 +
  90 +%nonassoc LOWEST
  91 +%nonassoc LOWER_THAN_ELSE
  92 +%nonassoc T_Else
  93 +%right T_Equal T_MulAssign T_DivAssign T_AddAssign T_SubAssign
  94 +%right T_Question T_Colon
  95 +%left T_EQ T_NE T_LeftAngle T_RightAngle T_And T_Or T_GreaterEqual
  96 +%left T_Plus T_Dash T_Star T_Slash
  97 +
  98 +/* Non-terminal types
  99 + * ------------------
  100 + * In order for yacc to assign/access the correct field of $$, $1, we
  101 + * must to declare which field is appropriate for the non-terminal.
  102 + * As an example, this first type declaration establishes that the DeclList
  103 + * non-terminal uses the field named "declList" in the yylval union. This
  104 + * means that when we are setting $$ for a reduction for DeclList ore reading
  105 + * $n which corresponds to a DeclList nonterminal we are accessing the field
  106 + * of the union named "declList" which is of type List<Decl*>.
  107 + * pp2: You'll need to add many of these of your own.
  108 + */
  109 +%type <declList> DeclList
  110 +%type <decl> Decl
  111 +%type <decl> Declaration
  112 +%type <funcDecl> FuncDecl
  113 +%type <typeDecl> TypeDecl
  114 +%type <typeQualifier> TypeQualify
  115 +%type <expression> PrimaryExpr PostfixExpr UnaryExpr MultiExpr AdditionExpr RelationExpr Initializer FunctionCallExpr FunctionCallHeaderWithParameters FunctionCallHeaderNoParameters
  116 +%type <expression> EqualityExpr LogicAndExpr LogicOrExpr Expression
  117 + /*%type <floatConstant> Initializer*/
  118 +%type <varDecl> SingleDecl
  119 +%type <varDeclList> ParameterList
  120 +%type <stmt> Statement
  121 +%type <stmtList> StatementList
  122 +%type <stmt> SingleStatement SelectionStmt SwitchStmt CaseStmt JumpStmt WhileStmt ForStmt
  123 +%type <stmt> CompoundStatement
  124 +%type <ops> AssignOp
  125 +%type <funcId> FunctionIdentifier
  126 +%type <argList> ArgumentList
  127 +
  128 +%%
  129 +/* Rules
  130 + * -----
  131 + * All productions and actions should be placed between the start and stop
  132 + * %% markers which delimit the Rules section.
  133 +
  134 + */
  135 +Program : DeclList {
  136 + @1;
  137 + /* pp2: The @1 is needed to convince
  138 + * yacc to set up yylloc. You can remove
  139 + * it once you have other uses of @n*/
  140 + Program *program = new Program($1);
  141 + // if no errors, advance to next phase
  142 + if (ReportError::NumErrors() == 0) {
  143 + if ( IsDebugOn("dumpAST") ) {
  144 + program->Print(0);
  145 + }
  146 + program->Emit();
  147 + }
  148 + }
  149 + ;
  150 +
  151 +DeclList : DeclList Decl { ($$=$1)->Append($2); }
  152 + | Decl { ($$ = new List<Decl*>)->Append($1); }
  153 + ;
  154 +
  155 +/* combine external_declaration and function_definition into a single rule
  156 + * external_declaration:
  157 + * function_definition
  158 + * declaration
  159 + * function_definition:
  160 + * function_prototype compound_statement
  161 + */
  162 +
  163 +Decl : Declaration { $$ = $1; }
  164 + | FuncDecl CompoundStatement { $1->SetFunctionBody($2); $$ = $1; }
  165 + ;
  166 +
  167 +/* combine declaration and init_decl_list into a single rule
  168 + * declaration:
  169 + * function_prototype SEMICOLON
  170 + * init_decl_list SEMICOLON
  171 + * init_decl_list:
  172 + * single_declaration
  173 + */
  174 +
  175 +Declaration : FuncDecl T_Semicolon { $$ = $1; }
  176 + | SingleDecl T_Semicolon { $$ = $1; }
  177 + ;
  178 +
  179 +FuncDecl : TypeDecl T_Identifier T_LeftParen T_RightParen
  180 + {
  181 + Identifier *id = new Identifier(yylloc, (const char *)$2);
  182 + List<VarDecl *> *formals = new List<VarDecl *>;
  183 + $$ = new FnDecl(id, $1, formals);
  184 + }
  185 + | TypeDecl T_Identifier T_LeftParen ParameterList T_RightParen
  186 + {
  187 + Identifier *id = new Identifier(yylloc, (const char *)$2);
  188 + $$ = new FnDecl(id, $1, $4);
  189 + }
  190 + ;
  191 +
  192 +ParameterList : SingleDecl { ($$ = new List<VarDecl *>)->Append($1); }
  193 + | ParameterList T_Comma SingleDecl { ($$ = $1)->Append($3); }
  194 + ;
  195 +
  196 +SingleDecl : TypeDecl T_Identifier
  197 + {
  198 + Identifier *id = new Identifier(yylloc, (const char *)$2);
  199 + $$ = new VarDecl(id, $1);
  200 + }
  201 + | TypeQualify TypeDecl T_Identifier
  202 + {
  203 + Identifier *id = new Identifier(yylloc, (const char *)$3);
  204 + $$ = new VarDecl(id, $2, $1);
  205 + }
  206 + | TypeDecl T_Identifier T_Equal Initializer
  207 + {
  208 + // incomplete: drop the initializer here
  209 + Identifier *id = new Identifier(yylloc, (const char *)$2);
  210 + $$ = new VarDecl(id, $1, $4);
  211 + }
  212 + | TypeQualify TypeDecl T_Identifier T_Equal Initializer
  213 + {
  214 + Identifier *id = new Identifier(yylloc, (const char *)$3);
  215 + $$ = new VarDecl(id, $2, $1, $5);
  216 + }
  217 + | TypeDecl T_Identifier T_LeftBracket T_IntConstant T_RightBracket
  218 + {
  219 + Identifier *id = new Identifier(@2, (const char *)$2);
  220 + $$ = new VarDecl(id, new ArrayType(@1, $1, $4));
  221 + }
  222 + | TypeQualify TypeDecl T_Identifier T_LeftBracket T_IntConstant T_RightBracket
  223 + {
  224 + Identifier *id = new Identifier(@3, $3);
  225 + $$ = new VarDecl(id, new ArrayType(@2, $2, $5), $1);
  226 + }
  227 +
  228 + ;
  229 +
  230 +Initializer : Expression { $$ = $1; }
  231 + ;
  232 +
  233 +TypeQualify : T_In {$$ = TypeQualifier::inTypeQualifier;}
  234 + | T_Out {$$ = TypeQualifier::outTypeQualifier;}
  235 + | T_Const {$$ = TypeQualifier::constTypeQualifier;}
  236 + | T_Uniform {$$ = TypeQualifier::uniformTypeQualifier;}
  237 + ;
  238 +
  239 +TypeDecl : T_Int { $$ = Type::intType; }
  240 + | T_Void { $$ = Type::voidType; }
  241 + | T_Float { $$ = Type::floatType; }
  242 + | T_Bool { $$ = Type::boolType; }
  243 + | T_Vec2 { $$ = Type::vec2Type; }
  244 + | T_Vec3 { $$ = Type::vec3Type; }
  245 + | T_Vec4 { $$ = Type::vec4Type; }
  246 + | T_Mat2 { $$ = Type::mat2Type; }
  247 + | T_Mat3 { $$ = Type::mat3Type; }
  248 + | T_Mat4 { $$ = Type::mat4Type; }
  249 + ;
  250 +
  251 +CompoundStatement : T_LeftBrace T_RightBrace { $$ = new StmtBlock(new List<VarDecl*>, new List<Stmt *>); }
  252 + | T_LeftBrace StatementList T_RightBrace { $$ = new StmtBlock(new List<VarDecl*>, $2); }
  253 + ;
  254 +
  255 +StatementList : Statement { ($$ = new List<Stmt*>)->Append($1); }
  256 + | StatementList Statement { ($$ = $1)->Append($2); }
  257 + ;
  258 +
  259 +Statement : CompoundStatement { $$ = $1; }
  260 + | SingleStatement { $$ = $1; }
  261 + ;
  262 +
  263 +SingleStatement : T_Semicolon { $$ = new EmptyExpr(); }
  264 + | SingleDecl T_Semicolon
  265 + {
  266 + $$ = new DeclStmt($1);
  267 + }
  268 + | Expression T_Semicolon { $$ = $1; }
  269 + | SelectionStmt { $$ = $1; }
  270 + | SwitchStmt { $$ = $1; }
  271 + | CaseStmt { $$ = $1; }
  272 + | JumpStmt { $$ = $1; }
  273 + | WhileStmt { $$ = $1; }
  274 + | ForStmt { $$ = $1; }
  275 + ;
  276 +
  277 +SelectionStmt : T_If T_LeftParen Expression T_RightParen Statement T_Else Statement
  278 + {
  279 + $$ = new IfStmt($3, $5, $7);
  280 + }
  281 + | T_If T_LeftParen Expression T_RightParen Statement %prec LOWER_THAN_ELSE
  282 + {
  283 + $$ = new IfStmt($3, $5, NULL);
  284 + }
  285 + ;
  286 +
  287 +SwitchStmt : T_Switch T_LeftParen Expression T_RightParen T_LeftBrace StatementList T_RightBrace
  288 + {
  289 + $$ = new SwitchStmt($3, $6, NULL);
  290 + }
  291 + ;
  292 +CaseStmt : T_Case Expression T_Colon Statement { $$ = new Case($2, $4); }
  293 + | T_Default T_Colon Statement { $$ = new Default($3); }
  294 + ;
  295 +
  296 +JumpStmt : T_Break T_Semicolon { $$ = new BreakStmt(yylloc); }
  297 + | T_Continue T_Semicolon { $$ = new ContinueStmt(yylloc); }
  298 + | T_Return T_Semicolon { $$ = new ReturnStmt(yylloc); }
  299 + | T_Return Expression T_Semicolon { $$ = new ReturnStmt(yyloc, $2); }
  300 + ;
  301 +
  302 +WhileStmt : T_While T_LeftParen Expression T_RightParen Statement { $$ = new WhileStmt($3, $5); }
  303 + ;
  304 +
  305 +ForStmt : T_For T_LeftParen Expression T_Semicolon Expression T_Semicolon Expression T_RightParen Statement
  306 + {
  307 + $$ = new ForStmt($3, $5, $7, $9);
  308 + }
  309 + ;
  310 +
  311 +PrimaryExpr : T_Identifier { Identifier *id = new Identifier(yylloc, (const char*)$1);
  312 + $$ = new VarExpr(yyloc, id);
  313 + }
  314 + | T_IntConstant { $$ = new IntConstant(yylloc, $1); }
  315 + | T_FloatConstant { $$ = new FloatConstant(yylloc, $1); }
  316 + | T_BoolConstant { $$ = new BoolConstant(yylloc, $1); }
  317 + | T_LeftParen Expression T_RightParen { $$ = $2;}
  318 + ;
  319 +
  320 +FunctionCallExpr : FunctionCallHeaderWithParameters T_RightParen { $$ = $1; }
  321 + | FunctionCallHeaderNoParameters T_RightParen { $$ = $1; }
  322 + ;
  323 +
  324 +FunctionCallHeaderNoParameters : FunctionIdentifier T_LeftParen T_Void { $$ = new Call(@1, NULL, $1, new List<Expr*>); }
  325 + | FunctionIdentifier T_LeftParen { $$ = new Call(@1, NULL, $1, new List<Expr*>); }
  326 + ;
  327 +
  328 +FunctionCallHeaderWithParameters : FunctionIdentifier T_LeftParen ArgumentList { $$ = new Call(@1, NULL, $1, $3);}
  329 + ;
  330 +
  331 +ArgumentList : Expression { ($$ = new List<Expr*>)->Append($1);}
  332 + | ArgumentList T_Comma Expression { ($$ = $1)->Append($3);}
  333 + ;
  334 +
  335 +FunctionIdentifier : T_Identifier { $$ = new Identifier(@1, $1); }
  336 + ;
  337 +
  338 +PostfixExpr : PrimaryExpr { $$ = $1; }
  339 + | PostfixExpr T_LeftBracket Expression T_RightBracket { $$ = new ArrayAccess(@1, $1, $3); }
  340 + | FunctionCallExpr
  341 + {
  342 + }
  343 + | PostfixExpr T_Inc
  344 + {
  345 + Operator *op = new Operator(yylloc, (const char *)$2);
  346 + $$ = new PostfixExpr($1, op);
  347 + }
  348 + | PostfixExpr T_Dec
  349 + {
  350 + Operator *op = new Operator(yylloc, (const char *)$2);
  351 + $$ = new PostfixExpr($1, op);
  352 + }
  353 + | PostfixExpr T_Dot T_FieldSelection
  354 + {
  355 + Identifier *id = new Identifier(yylloc, (const char *)$3);
  356 + $$ = new FieldAccess($1, id);
  357 + }
  358 + ;
  359 +
  360 +UnaryExpr : PostfixExpr { $$ = $1; }
  361 + | T_Inc UnaryExpr
  362 + {
  363 + Operator *op = new Operator(yylloc, $1);
  364 + $$ = new ArithmeticExpr(op, $2);
  365 + }
  366 + | T_Dec UnaryExpr
  367 + {
  368 + Operator *op = new Operator(yylloc, $1);
  369 + $$ = new ArithmeticExpr(op, $2);
  370 + }
  371 + | T_Plus UnaryExpr
  372 + {
  373 + Operator *op = new Operator(yylloc, $1);
  374 + $$ = new ArithmeticExpr(op, $2);
  375 + }
  376 + | T_Dash UnaryExpr
  377 + {
  378 + Operator *op = new Operator(yylloc, $1);
  379 + $$ = new ArithmeticExpr(op, $2);
  380 + }
  381 + ;
  382 +
  383 +MultiExpr : UnaryExpr { $$ = $1; }
  384 + | MultiExpr T_Star UnaryExpr
  385 + {
  386 + Operator *op = new Operator(yylloc, $2);
  387 + $$ = new ArithmeticExpr($1, op, $3);
  388 + }
  389 + | MultiExpr T_Slash UnaryExpr
  390 + {
  391 + Operator *op = new Operator(yylloc, $2);
  392 + $$ = new ArithmeticExpr($1, op, $3);
  393 + }
  394 + ;
  395 +
  396 +AdditionExpr : MultiExpr { $$ = $1; }
  397 + | AdditionExpr T_Plus MultiExpr
  398 + {
  399 + Operator *op = new Operator(yylloc, $2);
  400 + $$ = new ArithmeticExpr($1, op, $3);
  401 + }
  402 + | AdditionExpr T_Dash MultiExpr
  403 + {
  404 + Operator *op = new Operator(yylloc, $2);
  405 + $$ = new ArithmeticExpr($1, op, $3);
  406 + }
  407 + ;
  408 +
  409 +RelationExpr : AdditionExpr { $$ = $1; }
  410 + | RelationExpr T_LeftAngle AdditionExpr
  411 + {
  412 + Operator *op = new Operator(yylloc, $2);
  413 + $$ = new RelationalExpr($1, op, $3);
  414 + }
  415 + | RelationExpr T_RightAngle AdditionExpr
  416 + {
  417 + Operator *op = new Operator(yylloc, $2);
  418 + $$ = new RelationalExpr($1, op, $3);
  419 + }
  420 + | RelationExpr T_GreaterEqual AdditionExpr
  421 + {
  422 + Operator *op = new Operator(yylloc, $2);
  423 + $$ = new RelationalExpr($1, op, $3);
  424 + }
  425 + | RelationExpr T_LessEqual AdditionExpr
  426 + {
  427 + Operator *op = new Operator(yylloc, $2);
  428 + $$ = new RelationalExpr($1, op, $3);
  429 + }
  430 + ;
  431 +
  432 +EqualityExpr : RelationExpr { $$ = $1; }
  433 + | EqualityExpr T_EQ RelationExpr
  434 + {
  435 + Operator *op = new Operator(yylloc, $2);
  436 + $$ = new ArithmeticExpr($1, op, $3);
  437 + }
  438 + | EqualityExpr T_NE RelationExpr
  439 + {
  440 + Operator *op = new Operator(yylloc, $2);
  441 + $$ = new ArithmeticExpr($1, op, $3);
  442 + }
  443 + ;
  444 +
  445 +LogicAndExpr : EqualityExpr { $$ = $1; }
  446 + | LogicAndExpr T_And EqualityExpr
  447 + {
  448 + Operator *op = new Operator(yylloc, $2);
  449 + $$ = new ArithmeticExpr($1, op, $3);
  450 + }
  451 + ;
  452 +
  453 +LogicOrExpr : LogicAndExpr { $$ = $1; }
  454 + | LogicOrExpr T_Or LogicAndExpr
  455 + {
  456 + Operator *op = new Operator(yylloc, $2);
  457 + $$ = new ArithmeticExpr($1, op, $3);
  458 + }
  459 + ;
  460 +
  461 +Expression : LogicOrExpr { $$ = $1; }
  462 + | LogicOrExpr T_Question LogicOrExpr T_Colon LogicOrExpr
  463 + {
  464 + $$ = new ConditionalExpr($1, $3, $5);
  465 + }
  466 + | UnaryExpr AssignOp Expression
  467 + {
  468 + $$ = new AssignExpr($1, $2, $3);
  469 + }
  470 + ;
  471 +
  472 +AssignOp : T_Equal { $$ = new Operator(yylloc, $1); }
  473 + | T_AddAssign { $$ = new Operator(yylloc, "+="); }
  474 + | T_SubAssign { $$ = new Operator(yylloc, "-="); }
  475 + | T_MulAssign { $$ = new Operator(yylloc, "*="); }
  476 + | T_DivAssign { $$ = new Operator(yylloc, "/="); }
  477 + ;
  478 +
  479 +%%
  480 +
  481 +/* The closing %% above marks the end of the Rules section and the beginning
  482 + * of the User Subroutines section. All text from here to the end of the
  483 + * file is copied verbatim to the end of the generated y.tab.c file.
  484 + * This section is where you put definitions of helper functions.
  485 + */
  486 +
  487 +/* Function: InitParser
  488 + * --------------------
  489 + * This function will be called before any calls to yyparse(). It is designed
  490 + * to give you an opportunity to do anything that must be done to initialize
  491 + * the parser (set global variables, configure starting state, etc.). One
  492 + * thing it already does for you is assign the value of the global variable
  493 + * yydebug that controls whether yacc prints debugging information about
  494 + * parser actions (shift/reduce) and contents of state stack during parser.
  495 + * If set to false, no information is printed. Setting it to true will give
  496 + * you a running trail that might be helpful when debugging your parser.
  497 + * Please be sure the variable is set to false when submitting your final
  498 + * version.
  499 + */
  500 +void InitParser()
  501 +{
  502 + PrintDebug("parser", "Initializing parser");
  503 + yydebug = false;
  504 +}
public_samples/foo.dat View file @ c30bbd1
... ... @@ -0,0 +1,2 @@
  1 +funct: foo
  2 +param: int, 3
public_samples/foo.glsl View file @ c30bbd1
... ... @@ -0,0 +1,4 @@
  1 +int foo(int x)
  2 +{
  3 + return x + 1;
  4 +}
public_samples/foo.out View file @ c30bbd1
... ... @@ -0,0 +1 @@
  1 +Result: 4
public_samples/vec2_test.dat View file @ c30bbd1
... ... @@ -0,0 +1,3 @@
  1 +funct: v2test
  2 +param: float, 3.0
  3 +gin: v, vec2, 1.1, 2.2
public_samples/vec2_test.glsl View file @ c30bbd1
... ... @@ -0,0 +1,11 @@
  1 +vec2 v;
  2 +
  3 +float v2test(float x)
  4 +{
  5 + vec2 v2;
  6 +
  7 + v2 = v * x;
  8 +
  9 + return v2.x + v2.y;
  10 +}
  11 +
public_samples/vec2_test.out View file @ c30bbd1
... ... @@ -0,0 +1 @@
  1 +Result: 9.900001e+00
... ... @@ -0,0 +1,17 @@
  1 +#! /bin/sh
  2 +
  3 +[ -x glc ] || { echo "Error: glc not executable"; exit 1; }
  4 +
  5 +LIST=
  6 +if [ "$#" = "0" ]; then
  7 + LIST=`ls samples/*.glsl`
  8 +else
  9 + for test in "$@"; do
  10 + LIST="$LIST samples/$test.glsl"
  11 + done
  12 +fi
  13 +
  14 +for file in $LIST; do
  15 + echo $file
  16 + ./glc < $file
  17 +done
... ... @@ -0,0 +1,23 @@
  1 +/* File: scanner.h
  2 + * ---------------
  3 + * You should not need to modify this file. It declare a few constants,
  4 + * types, variables,and functions that are used and/or exported by
  5 + * the lex-generated scanner.
  6 + */
  7 +
  8 +#ifndef _H_scanner
  9 +#define _H_scanner
  10 +
  11 +#include <stdio.h>
  12 +
  13 +#define MaxIdentLen 31 // Maximum length for identifiers
  14 +
  15 +extern char *yytext; // Text of lexeme just scanned
  16 +
  17 +
  18 +int yylex(); // Defined in the generated lex.yy.c file
  19 +
  20 +void InitScanner(); // Defined in scanner.l user subroutines
  21 +const char *GetLineNumbered(int n); // ditto
  22 +
  23 +#endif
... ... @@ -0,0 +1,236 @@
  1 +/* File: scanner.l
  2 + * ----------------
  3 + * Lex input file to generate the scanner for the compiler.
  4 + */
  5 +
  6 +%{
  7 +
  8 +#include <string.h>
  9 +#include "scanner.h"
  10 +#include "utility.h" // for PrintDebug()
  11 +#include "errors.h"
  12 +#include "parser.h" // for token codes, yylval
  13 +#include <vector>
  14 +using namespace std;
  15 +
  16 +#define TAB_SIZE 8
  17 +
  18 +/* Global variables
  19 + * ----------------
  20 + * (For shame!) But we need a few to keep track of things that are
  21 + * preserved between calls to yylex or used outside the scanner.
  22 + */
  23 +static int curLineNum, curColNum;
  24 +vector<const char*> savedLines;
  25 +
  26 +static void DoBeforeEachAction();
  27 +#define YY_USER_ACTION DoBeforeEachAction();
  28 +
  29 +%}
  30 +
  31 +/* States
  32 + * ------
  33 + * A little wrinkle on states is the COPY exclusive state which
  34 + * I added to first match each line and copy it ot the list of lines
  35 + * read before re-processing it. This allows us to print the entire
  36 + * line later to provide context on errors.
  37 + */
  38 +%s N
  39 +%x COPY COMM FIELDS
  40 +%option stack
  41 +
  42 +/* Definitions
  43 + * -----------
  44 + * To make our rules more readable, we establish some definitions here.
  45 + */
  46 +DIGIT ([0-9])
  47 +HEX_DIGIT ([0-9a-fA-F])
  48 +HEX_INTEGER (0[Xx]{HEX_DIGIT}+)
  49 +INTEGER ({DIGIT}+)
  50 +EXPONENT ([Ee][-+]?{INTEGER})
  51 +FLOAT ({INTEGER}"."{DIGIT}*[fF]?)
  52 +IDENTIFIER ([a-zA-Z][a-zA-Z_0-9]*)
  53 +OPERATOR ([-+/*%=.,;!<>()[\]{}:])
  54 +BEG_COMMENT ("/*")
  55 +END_COMMENT ("*/")
  56 +SINGLE_COMMENT ("//"[^\n]*)
  57 +
  58 +%% /* BEGIN RULES SECTION */
  59 +
  60 +<COPY>.* { char curLine[512];
  61 + //strncpy(curLine, yytext, sizeof(curLine));
  62 + savedLines.push_back(strdup(yytext));
  63 + curColNum = 1; yy_pop_state(); yyless(0); }
  64 +<COPY><<EOF>> { yy_pop_state(); }
  65 +<*>\n { curLineNum++; curColNum = 1;
  66 + if (YYSTATE == COPY) savedLines.push_back("");
  67 + else yy_push_state(COPY); }
  68 +
  69 +[ ]+ { /* ignore all spaces */ }
  70 +<*>[\t] { curColNum += TAB_SIZE - curColNum%TAB_SIZE + 1; }
  71 +
  72 + /* -------------------- Comments ----------------------------- */
  73 +{BEG_COMMENT} { BEGIN(COMM); }
  74 +<COMM>{END_COMMENT} { BEGIN(N); }
  75 +<COMM><<EOF>> { ReportError::UntermComment();
  76 + return 0; }
  77 +<COMM>. { /* ignore everything else that doesn't match */ }
  78 +{SINGLE_COMMENT} { /* skip to end of line for // comment */ }
  79 +
  80 +
  81 + /* --------------------- Keywords ------------------------------- */
  82 +"void" { return T_Void; }
  83 +"int" { return T_Int; }
  84 +"float" { return T_Float; }
  85 +"bool" { return T_Bool; }
  86 +"while" { return T_While; }
  87 +"for" { return T_For; }
  88 +"if" { return T_If; }
  89 +"else" { return T_Else; }
  90 +"return" { return T_Return; }
  91 +"break" { return T_Break; }
  92 +"switch" { return T_Switch; }
  93 +"case" { return T_Case; }
  94 +"default" { return T_Default; }
  95 +"const" { return T_Const; }
  96 +"uniform" { return T_Uniform; }
  97 +"continue" { return T_Continue; }
  98 +"do" { return T_Do; }
  99 +"in" { return T_In; }
  100 +"out" { return T_Out; }
  101 +"mat2" { return T_Mat2; }
  102 +"mat3" { return T_Mat3; }
  103 +"mat4" { return T_Mat4; }
  104 +"vec2" { return T_Vec2; }
  105 +"vec3" { return T_Vec3; }
  106 +"vec4" { return T_Vec4; }
  107 +"ivec2" { return T_Ivec2; }
  108 +"ivec3" { return T_Ivec3; }
  109 +"ivec4" { return T_Ivec4; }
  110 +"bvec2" { return T_Bvec2; }
  111 +"bvec3" { return T_Bvec3; }
  112 +"bvec4" { return T_Bvec4; }
  113 +"uint" { return T_Uint; }
  114 +"uvec2" { return T_Uvec2; }
  115 +"uvec3" { return T_Uvec3; }
  116 +"uvec4" { return T_Uvec4; }
  117 +
  118 +
  119 + /* -------------------- punctuation --------------------------- */
  120 +"(" { return T_LeftParen; }
  121 +")" { return T_RightParen; }
  122 +":" { return T_Colon; }
  123 +";" { return T_Semicolon; }
  124 +"{" { return T_LeftBrace; }
  125 +"}" { return T_RightBrace; }
  126 +"." { BEGIN(FIELDS); return T_Dot; }
  127 +"[" { return T_LeftBracket; }
  128 +"]" { return T_RightBracket; }
  129 +"," { return T_Comma; }
  130 +
  131 + /* -------------------- Operators ----------------------------- */
  132 +"<=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_LessEqual; }
  133 +">=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_GreaterEqual;}
  134 +"==" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_EQ; }
  135 +"!=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_NE; }
  136 +"&&" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_And; }
  137 +"||" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Or; }
  138 +"++" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Inc; }
  139 +"--" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Dec; }
  140 +"+" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Plus; }
  141 +"-" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Dash; }
  142 +"*" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Star; }
  143 +"/" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Slash; }
  144 +"+=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_AddAssign; }
  145 +"-=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_SubAssign; }
  146 +"*=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_MulAssign; }
  147 +"/=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_DivAssign; }
  148 +"=" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Equal; }
  149 +">" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_RightAngle; }
  150 +"<" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_LeftAngle; }
  151 +"?" { snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext); return T_Question; }
  152 +
  153 + /* -------------------- Constants ------------------------------ */
  154 +"true"|"false" { yylval.boolConstant = (yytext[0] == 't');
  155 + return T_BoolConstant; }
  156 +{INTEGER} { yylval.integerConstant = strtol(yytext, NULL, 10);
  157 + return T_IntConstant; }
  158 +{HEX_INTEGER} { yylval.integerConstant = strtol(yytext, NULL, 16);
  159 + return T_IntConstant; }
  160 +{FLOAT} { yylval.floatConstant = atof(yytext);
  161 + return T_FloatConstant; }
  162 +
  163 +
  164 + /* -------------------- Identifiers --------------------------- */
  165 +{IDENTIFIER} { if (strlen(yytext) > 1023)
  166 + ReportError::LongIdentifier(&yylloc, yytext);
  167 + snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext);
  168 + return T_Identifier; }
  169 +
  170 + /* -------------------- Field Selection ------------------------- */
  171 +<FIELDS>{IDENTIFIER} {
  172 +BEGIN(INITIAL);
  173 + // copy the field selection string
  174 + if (strlen(yytext) > 1023)
  175 + ReportError::LongIdentifier(&yylloc, yytext);
  176 + snprintf(yylval.identifier, MaxIdentLen+1, "%s", yytext);
  177 + return T_FieldSelection; }
  178 +<FIELDS>[ \t\r] {}
  179 +
  180 + /* -------------------- Default rule (error) -------------------- */
  181 +. { ReportError::UnrecogChar(&yylloc, yytext[0]); }
  182 +
  183 +%%
  184 +
  185 +
  186 +/* Function: InitScanner
  187 + * ---------------------
  188 + * This function will be called before any calls to yylex(). It is designed
  189 + * to give you an opportunity to do anything that must be done to initialize
  190 + * the scanner (set global variables, configure starting state, etc.). One
  191 + * thing it already does for you is assign the value of the global variable
  192 + * yy_flex_debug that controls whether flex prints debugging information
  193 + * about each token and what rule was matched. If set to false, no information
  194 + * is printed. Setting it to true will give you a running trail that might
  195 + * be helpful when debugging your scanner. Please be sure the variable is
  196 + * set to false when submitting your final version.
  197 + */
  198 +void InitScanner()
  199 +{
  200 + PrintDebug("lex", "Initializing scanner");
  201 + yy_flex_debug = false;
  202 + BEGIN(N);
  203 + yy_push_state(COPY); // copy first line at start
  204 + curLineNum = 1;
  205 + curColNum = 1;
  206 +}
  207 +
  208 +
  209 +/* Function: DoBeforeEachAction()
  210 + * ------------------------------
  211 + * This function is installed as the YY_USER_ACTION. This is a place
  212 + * to group code common to all actions.
  213 + * On each match, we fill in the fields to record its location and
  214 + * update our column counter.
  215 + */
  216 +static void DoBeforeEachAction()
  217 +{
  218 + yylloc.first_line = curLineNum;
  219 + yylloc.first_column = curColNum;
  220 + yylloc.last_column = curColNum + yyleng - 1;
  221 + curColNum += yyleng;
  222 +}
  223 +
  224 +/* Function: GetLineNumbered()
  225 + * ---------------------------
  226 + * Returns string with contents of line numbered n or NULL if the
  227 + * contents of that line are not available. Our scanner copies
  228 + * each line scanned and appends each to a list so we can later
  229 + * retrieve them to report the context for errors.
  230 + */
  231 +const char *GetLineNumbered(int num) {
  232 + if (num <= 0 || num > savedLines.size()) return NULL;
  233 + return savedLines[num-1];
  234 +}
  235 +
  236 +
submission.sh View file @ c30bbd1
... ... @@ -0,0 +1,58 @@
  1 +#!/bin/bash
  2 +
  3 +name=""
  4 +pid=""
  5 +email=""
  6 +
  7 +if [[ $name == "" ]]
  8 +then
  9 + echo "Edit this script to enter your name and partners name above"
  10 + exit
  11 +fi
  12 +
  13 +if [[ $pid == "" ]]
  14 +then
  15 + echo "Edit this script to enter your PID and partners PID above"
  16 + exit
  17 +fi
  18 +
  19 +if [[ $email == "" ]]
  20 +then
  21 + echo "Edit this script to enter one email where you can be reached easily"
  22 + exit
  23 +fi
  24 +
  25 +
  26 +if [[ $pid == [A][0-9]* || $pid == [A][0-9]*[_][A][0-9]* || $pid == [A][0-9]*[_][A][0-9]*[_][A][0-9]* ]]
  27 +then
  28 + rm -rf $pid.zip
  29 + rm -rf $pid
  30 +
  31 + mkdir $pid
  32 +
  33 + cp Makefile $pid/
  34 + cp README.md $pid/
  35 + cp errors.h $pid/
  36 + cp main.cc $pid/
  37 + cp scanner.h $pid/
  38 + cp utility.h $pid/
  39 + cp Project_Description.txt $pid/
  40 + cp errors.cc $pid/
  41 + cp location.h $pid/
  42 + cp scanner.l $pid/
  43 + cp utility.cc $pid/
  44 + cp ast* $pid/
  45 + cp list.h $pid/
  46 + cp parser.h $pid/
  47 + cp parser.y $pid/
  48 + cp symtable.cc $pid/
  49 + cp symtable.h $pid/
  50 + cp irgen.cc $pid/
  51 + cp irgen.h $pid/
  52 +
  53 + zip -r $pid.zip $pid/*
  54 +else
  55 + echo "The pid provided does not match the criteria on piazza"
  56 + exit
  57 +fi
  58 +
... ... @@ -0,0 +1,5 @@
  1 +/*
  2 + * Symbol table implementation
  3 + *
  4 + */
  5 +
... ... @@ -0,0 +1,6 @@
  1 +/**
  2 + * File: symtable.h
  3 + * -----------
  4 + * Header file for Symbol table implementation.
  5 + */
  6 +
... ... @@ -0,0 +1,76 @@
  1 +/* File: utiliy.cc
  2 + * ---------------
  3 + * Implementation of simple printing functions to report failures or
  4 + * debugging information triggered by keys.
  5 + */
  6 +
  7 +#include "utility.h"
  8 +#include <stdarg.h>
  9 +#include <string.h>
  10 +#include <vector>
  11 +using std::vector;
  12 +
  13 +static vector<const char*> debugKeys;
  14 +static const int BufferSize = 2048;
  15 +
  16 +void Failure(const char *format, ...) {
  17 + va_list args;
  18 + char errbuf[BufferSize];
  19 +
  20 + va_start(args, format);
  21 + vsprintf(errbuf, format, args);
  22 + va_end(args);
  23 + fflush(stdout);
  24 + fprintf(stderr,"\n*** Failure: %s\n\n", errbuf);
  25 + abort();
  26 +}
  27 +
  28 +int IndexOf(const char *key) {
  29 + for (unsigned int i = 0; i < debugKeys.size(); i++)
  30 + if (!strcmp(debugKeys[i], key))
  31 + return i;
  32 +
  33 + return -1;
  34 +}
  35 +
  36 +bool IsDebugOn(const char *key) {
  37 + return (IndexOf(key) != -1);
  38 +}
  39 +
  40 +void SetDebugForKey(const char *key, bool value) {
  41 + int k = IndexOf(key);
  42 + if (!value && k != -1)
  43 + debugKeys.erase(debugKeys.begin() + k);
  44 + else if (value && k == -1)
  45 + debugKeys.push_back(key);
  46 +}
  47 +
  48 +void PrintDebug(const char *key, const char *format, ...) {
  49 + va_list args;
  50 + char buf[BufferSize];
  51 +
  52 + if (!IsDebugOn(key))
  53 + return;
  54 +
  55 + va_start(args, format);
  56 + vsprintf(buf, format, args);
  57 + va_end(args);
  58 + printf("+++ (%s): %s%s", key, buf, buf[strlen(buf)-1] != '\n'? "\n" : "");
  59 +}
  60 +
  61 +void ParseCommandLine(int argc, char *argv[]) {
  62 + if (argc == 1)
  63 + return;
  64 +
  65 + if (strcmp(argv[1], "-d") != 0) { // first arg is not -d
  66 + printf("Incorrect Use: ");
  67 + for (int i = 1; i < argc; i++) printf("%s ", argv[i]);
  68 + printf("\n");
  69 + printf("Correct Usage: -d <debug-key-1> <debug-key-2> ... \n");
  70 + exit(2);
  71 + }
  72 +
  73 + for (int i = 2; i < argc; i++)
  74 + SetDebugForKey(argv[i], true);
  75 +}
  76 +
... ... @@ -0,0 +1,86 @@
  1 +/* File: utility.h
  2 + * ---------------
  3 + * This file just includes a few support functions you might find
  4 + * helpful in writing the projects (error handling, debug printing)
  5 + */
  6 +
  7 +#ifndef _H_utility
  8 +#define _H_utility
  9 +
  10 +#include <stdlib.h>
  11 +#include <stdio.h>
  12 +
  13 +/**
  14 + * Function: Failure()
  15 + * Usage: Failure("Out of memory!");
  16 + * --------------------------------
  17 + * Reports an error and exits the program immediately. You should not
  18 + * need to call this since you should always try to continue parsing,
  19 + * even after an error is encountered. Some of the provided code calls
  20 + * this in unrecoverable error situations (cannot allocate memory, etc.)
  21 + * Failure accepts printf-style arguments in the message to be printed.
  22 + */
  23 +
  24 +void Failure(const char *format, ...);
  25 +
  26 +/**
  27 + * Macro: Assert()
  28 + * Usage: Assert(num > 0);
  29 + * ----------------------
  30 + * This macro is designed to assert the truth of a necessary condition.
  31 + * It tests the given expression, and if it evalutes true, nothing happens.
  32 + * If it is false, it calls Failure to print a message and abort.
  33 + * For example: Assert(ptr != NULL)
  34 + * will print something similar to the following if ptr is NULL:
  35 + * *** Failure: Assertion failed: hashtable.cc, line 55:
  36 + * ptr != NULL
  37 + */
  38 +
  39 +#define Assert(expr) \
  40 + ((expr) ? (void)0 : Failure("Assertion failed: %s, line %d:\n %s", __FILE__, __LINE__, #expr))
  41 +
  42 +/**
  43 + * Function: PrintDebug()
  44 + * Usage: PrintDebug("parser", "found ident %s\n", ident);
  45 + * -------------------------------------------------------
  46 + * Print a message if we have turned debugging messages on for the given
  47 + * key. For example, the usage line shown above will only print a message
  48 + * if the call is preceded by a call to SetDebugForKey("parser",true).
  49 + * The function accepts printf arguments. The provided main.cc parses
  50 + * the command line to turn on debug flags.
  51 + */
  52 +
  53 +void PrintDebug(const char *key, const char *format, ...);
  54 +
  55 +/**
  56 + * Function: SetDebugForKey()
  57 + * Usage: SetDebugForKey("scope", true);
  58 + * -------------------------------------
  59 + * Turn on debugging messages for the given key. See PrintDebug
  60 + * for an example. Can be called manually when desired and will
  61 + * be called from the provided main for flags passed with -d.
  62 + */
  63 +
  64 +void SetDebugForKey(const char *key, bool val);
  65 +
  66 +/**
  67 + * Function: IsDebugOn()
  68 + * Usage: if (IsDebugOn("scope")) ...
  69 + * ----------------------------------
  70 + * Return true/false based on whether this key is currently on
  71 + * for debug printing.
  72 + */
  73 +
  74 +bool IsDebugOn(const char *key);
  75 +
  76 +/**
  77 + * Function: ParseCommandLine
  78 + * --------------------------
  79 + * Turn on the debugging flags from the command line. Verifies that
  80 + * first argument is -d, and then interpret all the arguments that follow
  81 + * as being flags to turn on.
  82 + */
  83 +
  84 +void ParseCommandLine(int argc, char *argv[]);
  85 +
  86 +#endif