Compare View

switch
from
...
to
 
Commits (2)

Diff

Showing 2 changed files Inline Diff

/* File: ast.cc 1 1 /* File: ast.cc
* ------------ 2 2 * ------------
*/ 3 3 */
4 4
#include "ast.h" 5 5 #include "ast.h"
#include "ast_type.h" 6 6 #include "ast_type.h"
#include "ast_decl.h" 7 7 #include "ast_decl.h"
#include "symtable.h" 8 8 #include "symtable.h"
#include <string.h> // strdup 9 9 #include <string.h> // strdup
#include <stdio.h> // printf 10 10 #include <stdio.h> // printf
11 11
12
12 13 Node::Node(yyltype loc) {
Node::Node(yyltype loc) { 13 14 location = new yyltype(loc);
location = new yyltype(loc); 14 15 parent = NULL;
parent = NULL; 15 16 }
} 16 17
17 18 Node::Node() {
Node::Node() { 18 19 location = NULL;
location = NULL; 19 20 parent = NULL;
parent = NULL; 20 21 }
} 21 22
22 23 /* The Print method is used to print the parse tree nodes.
/* The Print method is used to print the parse tree nodes. 23 24 * If this node has a location (most nodes do, but some do not), it
* If this node has a location (most nodes do, but some do not), it 24 25 * will first print the line number to help you match the parse tree
* will first print the line number to help you match the parse tree 25 26 * back to the source text. It then indents the proper number of levels
* back to the source text. It then indents the proper number of levels 26 27 * and prints the "print name" of the node. It then will invoke the
* and prints the "print name" of the node. It then will invoke the 27 28 * virtual function PrintChildren which is expected to print the
* virtual function PrintChildren which is expected to print the 28 29 * internals of the node (itself & children) as appropriate.
* internals of the node (itself & children) as appropriate. 29 30 */
*/ 30 31 void Node::Print(int indentLevel, const char *label) {
void Node::Print(int indentLevel, const char *label) { 31 32 const int numSpaces = 3;
const int numSpaces = 3; 32 33 printf("\n");
printf("\n"); 33 34 if (GetLocation())
if (GetLocation()) 34 35 printf("%*d", numSpaces, GetLocation()->first_line);
printf("%*d", numSpaces, GetLocation()->first_line); 35 36 else
else 36 37 printf("%*s", numSpaces, "");
printf("%*s", numSpaces, ""); 37 38 printf("%*s%s%s: ", indentLevel*numSpaces, "",
printf("%*s%s%s: ", indentLevel*numSpaces, "", 38 39 label? label : "", GetPrintNameForNode());
label? label : "", GetPrintNameForNode()); 39 40 PrintChildren(indentLevel);
PrintChildren(indentLevel); 40 41 }
} 41 42
42 43 Identifier::Identifier(yyltype loc, const char *n) : Node(loc) {
Identifier::Identifier(yyltype loc, const char *n) : Node(loc) { 43 44 name = strdup(n);
name = strdup(n); 44 45 }
} 45 46
46 47 void Identifier::PrintChildren(int indentLevel) {
void Identifier::PrintChildren(int indentLevel) { 47 48 printf("%s", name);
printf("%s", name); 48 49 }
50
51 /*------------------------------------------------------------------------------------
52 * Symbol Table Information
53 *----------------------------------------------------------------------------------*/
54 SymbolTable symbols;
55
56 pair<Decl*,llvm::Value *> findSymbol(string s) {
57 for(int i = symbols.size() - 1; i >= 0; i--) {
58 if(symbols[i].count(s) > 0) return symbols[i][s];
59 }
60 return make_pair<Decl*,llvm::Value *>(NULL,NULL);
61 }
62
63 pair<Decl*,llvm::Value *> findSymbol(Decl* d) {
64 string s(d->GetIdentifier()->GetName());
65 return findSymbol(s);
66 }
67
68 bool isInCurrentScope(string s) {
69 if(symbols.size() == 0) return false;
70 return symbols[symbols.size()-1].count(s);
71 }
72
73 bool isInCurrentScope(Decl* d) {
74 string s(d->GetIdentifier()->GetName());
75 return isInCurrentScope(s);
76 }
77
78 bool isInScope(string s) {
79 pair<Decl*,llvm::Value *> tmp = findSymbol(s);
80 return tmp.first != NULL;
81 }
82
83 bool isInScope(Decl* d) {
84 string s(d->GetIdentifier()->GetName());
85 return isInScope(s);
86 }
87
88 void pushScope() {
89 symbols.push_back(map<string,pair<Decl*,llvm::Value *> >());
90 }
91 void popScope() {
92 symbols.pop_back();
93 }
94
95 void addToScope(string s, Decl* d, Type* t) {
96 symbols[symbols.size()-1][s] = make_pair(d, t);
97 }
} 49 98
50
/*------------------------------------------------------------------------------------ 51
* Symbol Table Information 52
*----------------------------------------------------------------------------------*/ 53
SymbolTable symbols; 54
55
pair<Decl*,llvm::Value *> findSymbol(string s) { 56
for(int i = symbols.size() - 1; i >= 0; i--) { 57
if(symbols[i].count(s) > 0) return symbols[i][s]; 58
} 59
return make_pair<Decl*,llvm::Value *>(NULL,NULL); 60
} 61
62
pair<Decl*,llvm::Value *> findSymbol(Decl* d) { 63
string s(d->GetIdentifier()->GetName()); 64
return findSymbol(s); 65
} 66
67
bool isInCurrentScope(string s) { 68
if(symbols.size() == 0) return false; 69
return symbols[symbols.size()-1].count(s); 70
} 71
72
bool isInCurrentScope(Decl* d) { 73
string s(d->GetIdentifier()->GetName()); 74
return isInCurrentScope(s); 75
} 76
77
bool isInScope(string s) { 78
pair<Decl*,llvm::Value *> tmp = findSymbol(s); 79
return tmp.first != NULL; 80
} 81
/** 1 1 /**
* File: ast.h 2 2 * File: ast.h
* ----------- 3 3 * -----------
* This file defines the abstract base class Node and the concrete 4 4 * This file defines the abstract base class Node and the concrete
* Identifier and Error node subclasses that are used through the tree as 5 5 * Identifier and Error node subclasses that are used through the tree as
* leaf nodes. A parse tree is a hierarchical collection of ast nodes (or, 6 6 * leaf nodes. A parse tree is a hierarchical collection of ast nodes (or,
* more correctly, of instances of concrete subclassses such as VarDecl, 7 7 * more correctly, of instances of concrete subclassses such as VarDecl,
* ForStmt, and AssignExpr). 8 8 * ForStmt, and AssignExpr).
* 9 9 *
* Location: Each node maintains its lexical location (line and columns in 10 10 * Location: Each node maintains its lexical location (line and columns in
* file), that location can be NULL for those nodes that don't care/use 11 11 * file), that location can be NULL for those nodes that don't care/use
* locations. The location is typcially set by the node constructor. The 12 12 * locations. The location is typcially set by the node constructor. The
* location is used to provide the context when reporting semantic errors. 13 13 * location is used to provide the context when reporting semantic errors.
* 14 14 *
* Parent: Each node has a pointer to its parent. For a Program node, the 15 15 * Parent: Each node has a pointer to its parent. For a Program node, the
* parent is NULL, for all other nodes it is the pointer to the node one level 16 16 * parent is NULL, for all other nodes it is the pointer to the node one level
* up in the parse tree. The parent is not set in the constructor (during a 17 17 * up in the parse tree. The parent is not set in the constructor (during a
* bottom-up parse we don't know the parent at the time of construction) but 18 18 * bottom-up parse we don't know the parent at the time of construction) but
* instead we wait until assigning the children into the parent node and then 19 19 * instead we wait until assigning the children into the parent node and then
* set up links in both directions. The parent link is typically not used 20 20 * set up links in both directions. The parent link is typically not used
* during parsing, but is more important in later phases. 21 21 * during parsing, but is more important in later phases.
* 22 22 *
* Printing: This functionaility is saved from pp2 of the node classes to 23 23 * Printing: This functionaility is saved from pp2 of the node classes to
* print out the AST tree for debugging purpose. Each node class is 24 24 * print out the AST tree for debugging purpose. Each node class is
* responsible for printing itself/children by overriding the virtual 25 25 * responsible for printing itself/children by overriding the virtual
* PrintChildren() and GetPrintNameForNode() methods. All the classes we 26 26 * PrintChildren() and GetPrintNameForNode() methods. All the classes we
* provide already implement these methods, so your job is to construct the 27 27 * provide already implement these methods, so your job is to construct the
* nodes and wire them up during parsing. Once that's done, printing is a snap! 28 28 * nodes and wire them up during parsing. Once that's done, printing is a snap!
29 29
* Semantic analysis: For pp3 you are adding "Check" behavior to the ast 30 30 * Semantic analysis: For pp3 you are adding "Check" behavior to the ast
* node classes. Your semantic analyzer should do an inorder walk on the 31 31 * node classes. Your semantic analyzer should do an inorder walk on the
* parse tree, and when visiting each node, verify the particular 32 32 * parse tree, and when visiting each node, verify the particular
* semantic rules that apply to that construct. 33 33 * semantic rules that apply to that construct.
34 34
*/ 35 35 */
36 36
#ifndef _H_ast 37 37 #ifndef _H_ast
#define _H_ast 38 38 #define _H_ast
39 39
#include <stdlib.h> // for NULL 40 40 #include <stdlib.h> // for NULL
#include "irgen.h" 41 41 #include "irgen.h"
#include "location.h" 42 42 #include "location.h"
#include <iostream> 43 43 #include <iostream>
44 #include <vector>
45 #include <map>
46 #include <algorithm>
#include <vector> 44 47
#include <map> 45 48 using namespace std;
#include <algorithm> 46 49
47 50 class SymbolTable;
using namespace std; 48 51 class MyStack;
49 52 class FnDecl;
53 class Decl;
class SymbolTable; 50 54
class MyStack; 51 55 class Node {
class FnDecl; 52 56 protected:
class Decl; 53 57 yyltype *location;
54 58 Node *parent;
class Node { 55 59
protected: 56 60 public:
yyltype *location; 57 61 Node(yyltype loc);
Node *parent; 58 62 Node();
59 63 virtual ~Node() {}
public: 60 64
Node(yyltype loc); 61 65 yyltype *GetLocation() { return location; }
Node(); 62 66 void SetParent(Node *p) { parent = p; }
virtual ~Node() {} 63 67 Node *GetParent() { return parent; }
64 68
yyltype *GetLocation() { return location; } 65 69 virtual const char *GetPrintNameForNode() = 0;
void SetParent(Node *p) { parent = p; } 66 70
Node *GetParent() { return parent; } 67 71 // Print() is deliberately _not_ virtual
68 72 // subclasses should override PrintChildren() instead
virtual const char *GetPrintNameForNode() = 0; 69 73 void Print(int indentLevel, const char *label = NULL);
70 74 virtual void PrintChildren(int indentLevel) {}
// Print() is deliberately _not_ virtual 71 75
// subclasses should override PrintChildren() instead 72 76 virtual llvm::Value* Emit() { return NULL; }
void Print(int indentLevel, const char *label = NULL); 73 77 };
virtual void PrintChildren(int indentLevel) {} 74 78
75 79
virtual llvm::Value* Emit() { return NULL; } 76 80 class Identifier : public Node
}; 77 81 {
78 82 protected:
79 83 char *name;
class Identifier : public Node 80 84
{ 81 85 public:
protected: 82 86 Identifier(yyltype loc, const char *name);
char *name; 83 87 const char *GetPrintNameForNode() { return "Identifier"; }
84 88 char *GetName() const { return name; }
public: 85 89 void PrintChildren(int indentLevel);
Identifier(yyltype loc, const char *name); 86 90 friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; }
const char *GetPrintNameForNode() { return "Identifier"; } 87 91 };
char *GetName() const { return name; } 88 92
void PrintChildren(int indentLevel); 89 93
friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; } 90 94 // This node class is designed to represent a portion of the tree that
}; 91 95 // encountered syntax errors during parsing. The partial completed tree
92 96 // is discarded along with the states being popped, and an instance of
93 97 // the Error class can stand in as the placeholder in the parse tree
// This node class is designed to represent a portion of the tree that 94 98 // when your parser can continue after an error.
// encountered syntax errors during parsing. The partial completed tree 95 99 class Error : public Node
// is discarded along with the states being popped, and an instance of 96 100 {
// the Error class can stand in as the placeholder in the parse tree 97 101 public:
// when your parser can continue after an error. 98 102 Error() : Node() {}
class Error : public Node 99 103 const char *GetPrintNameForNode() { return "Error"; }
{ 100 104 };
public: 101 105 /*------------------------------------------------------------------------------------
106 * Symbol Table Information
107 *----------------------------------------------------------------------------------*/
108 typedef vector<map<string,pair<Decl*,llvm::Value *> > > SymbolTable;
109 pair<Decl*,llvm::Value * v> findSymbol(string s);
110 pair<Decl*,llvm::Value * v> findSymbol(Decl* d);
111 bool isInCurrentScope(string s);
112 bool isInCurrentScope(Decl* d);
113 bool isInScope(string s);
114 bool isInScope(Decl* d);
115 void pushScope();
116 void popScope();
117 void addToScope(string s, Decl* d, llvm::Value * v t);
118 extern SymbolTable symbols;
Error() : Node() {} 102 119
const char *GetPrintNameForNode() { return "Error"; } 103 120