Commit 5b307fe7379cb1e47d4df1f735b8c8a5fc5263f3

Authored by Austin Sun
1 parent 2531734375
Exists in master

ummm not sure

Showing 2 changed files with 67 additions and 1 deletions 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
Node::Node(yyltype loc) { 12 13 Node::Node(yyltype loc) {
location = new yyltype(loc); 13 14 location = new yyltype(loc);
parent = NULL; 14 15 parent = NULL;
} 15 16 }
16 17
Node::Node() { 17 18 Node::Node() {
location = NULL; 18 19 location = NULL;
parent = NULL; 19 20 parent = NULL;
} 20 21 }
21 22
/* The Print method is used to print the parse tree nodes. 22 23 /* The Print method is used to print the parse tree nodes.
* If this node has a location (most nodes do, but some do not), it 23 24 * If this node has a location (most nodes do, but some do not), it
* will first print the line number to help you match the parse tree 24 25 * will first print the line number to help you match the parse tree
* back to the source text. It then indents the proper number of levels 25 26 * back to the source text. It then indents the proper number of levels
* and prints the "print name" of the node. It then will invoke the 26 27 * and prints the "print name" of the node. It then will invoke the
* virtual function PrintChildren which is expected to print the 27 28 * virtual function PrintChildren which is expected to print the
* internals of the node (itself & children) as appropriate. 28 29 * internals of the node (itself & children) as appropriate.
*/ 29 30 */
void Node::Print(int indentLevel, const char *label) { 30 31 void Node::Print(int indentLevel, const char *label) {
const int numSpaces = 3; 31 32 const int numSpaces = 3;
printf("\n"); 32 33 printf("\n");
if (GetLocation()) 33 34 if (GetLocation())
printf("%*d", numSpaces, GetLocation()->first_line); 34 35 printf("%*d", numSpaces, GetLocation()->first_line);
else 35 36 else
printf("%*s", numSpaces, ""); 36 37 printf("%*s", numSpaces, "");
printf("%*s%s%s: ", indentLevel*numSpaces, "", 37 38 printf("%*s%s%s: ", indentLevel*numSpaces, "",
label? label : "", GetPrintNameForNode()); 38 39 label? label : "", GetPrintNameForNode());
PrintChildren(indentLevel); 39 40 PrintChildren(indentLevel);
} 40 41 }
41 42
Identifier::Identifier(yyltype loc, const char *n) : Node(loc) { 42 43 Identifier::Identifier(yyltype loc, const char *n) : Node(loc) {
name = strdup(n); 43 44 name = strdup(n);
} 44 45 }
45 46
void Identifier::PrintChildren(int indentLevel) { 46 47 void Identifier::PrintChildren(int indentLevel) {
printf("%s", name); 47 48 printf("%s", name);
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() {
/** 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>
44 47
using namespace std; 45 48 using namespace std;
46 49
class SymbolTable; 47 50 class SymbolTable;
class MyStack; 48 51 class MyStack;
class FnDecl; 49 52 class FnDecl;
53 class Decl;
50 54
class Node { 51 55 class Node {
protected: 52 56 protected:
yyltype *location; 53 57 yyltype *location;
Node *parent; 54 58 Node *parent;
55 59
public: 56 60 public:
Node(yyltype loc); 57 61 Node(yyltype loc);
Node(); 58 62 Node();
virtual ~Node() {} 59 63 virtual ~Node() {}
60 64
yyltype *GetLocation() { return location; } 61 65 yyltype *GetLocation() { return location; }
void SetParent(Node *p) { parent = p; } 62 66 void SetParent(Node *p) { parent = p; }
Node *GetParent() { return parent; } 63 67 Node *GetParent() { return parent; }
64 68
virtual const char *GetPrintNameForNode() = 0; 65 69 virtual const char *GetPrintNameForNode() = 0;
66 70
// Print() is deliberately _not_ virtual 67 71 // Print() is deliberately _not_ virtual
// subclasses should override PrintChildren() instead 68 72 // subclasses should override PrintChildren() instead
void Print(int indentLevel, const char *label = NULL); 69 73 void Print(int indentLevel, const char *label = NULL);
virtual void PrintChildren(int indentLevel) {} 70 74 virtual void PrintChildren(int indentLevel) {}
71 75
virtual llvm::Value* Emit() { return NULL; } 72 76 virtual llvm::Value* Emit() { return NULL; }
}; 73 77 };
74 78
75 79
class Identifier : public Node 76 80 class Identifier : public Node
{ 77 81 {
protected: 78 82 protected:
char *name; 79 83 char *name;
80 84
public: 81 85 public:
Identifier(yyltype loc, const char *name); 82 86 Identifier(yyltype loc, const char *name);
const char *GetPrintNameForNode() { return "Identifier"; } 83 87 const char *GetPrintNameForNode() { return "Identifier"; }
char *GetName() const { return name; } 84 88 char *GetName() const { return name; }
void PrintChildren(int indentLevel); 85 89 void PrintChildren(int indentLevel);
friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; } 86 90 friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; }
}; 87 91 };
88 92
89 93
// This node class is designed to represent a portion of the tree that 90 94 // This node class is designed to represent a portion of the tree that
// encountered syntax errors during parsing. The partial completed tree 91 95 // encountered syntax errors during parsing. The partial completed tree
// is discarded along with the states being popped, and an instance of 92 96 // is discarded along with the states being popped, and an instance of
// the Error class can stand in as the placeholder in the parse tree 93 97 // the Error class can stand in as the placeholder in the parse tree
// when your parser can continue after an error. 94 98 // when your parser can continue after an error.
class Error : public Node 95 99 class Error : public Node
{ 96 100 {
public: 97 101 public:
Error() : Node() {} 98 102 Error() : Node() {}