-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.cpp
More file actions
144 lines (115 loc) · 3.48 KB
/
Copy pathparser.cpp
File metadata and controls
144 lines (115 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// convert Hack Assembly Language into an abstract syntax tree
#include "iobuffer.h"
#include "tokeniser.h"
#include "abstract-syntax-tree.h"
// to make out programs a bit neater
using namespace std ;
using namespace CS_IO_Buffers ;
using namespace Hack_Assembler ;
// grammer to be parsed:
// a_program ::= line* eoi
// line ::= instruction? eol
// instruction ::= a_label | a_instr | c_instr
// a_label ::= label
// a_instr ::= a_instr_name | a_instr_number
// a_instr_name ::= name
// a_instr_number ::= number
// c_instr ::= dest? alu_op jump?
// Tokens: label, name, number, dest, alu_op, jump, eol, eoi
// forward declare parsing functions - one per rule
ast parse_program() ;
ast parse_instruction() ;
ast parse_a_label() ;
ast parse_a_instr() ;
ast parse_a_instr_name() ;
ast parse_a_instr_number() ;
ast parse_c_instr() ;
// Note: always read one token after the one recognised
// a_program ::= line* tk_eoi
// line ::= instruction? tk_eol
ast parse_program()
{
vector<ast> instructions ;
// we stop when we see the EOI token
// this may be end of input or an error
// we cannot tell so treat both as end of input
// every new assembler instruction we find is appended to the_program
while ( have(tk_line) )
{
if ( have(tk_instruction) ) instructions.push_back(parse_instruction()) ;
mustbe(tk_eol) ;
}
mustbe(tk_eoi) ;
return create_program(instructions) ;
}
/***************** REPLACE THE FOLLOWING CODE ******************/
// instruction ::= tk_label | A-instr | C-instr
ast parse_instruction()
{
// inspect the token to see what it might start
if ( have(tk_label) ) return parse_a_label() ;
if ( have(tk_a_instr) ) return parse_a_instr() ;
if ( have(tk_c_instr) ) return parse_c_instr() ;
mustbe(tk_instruction) ;
return -1 ;
}
// tk_label is the token for '(' label ')'
ast parse_a_label()
{
string label = token_spelling() ;
next_token() ; // replace this with code to parse a label
return create_label(label) ;
}
// A-instr ::= tk_name | tk_number
ast parse_a_instr()
{
// inspect the token to see what it might start
if ( have(tk_name) ) return parse_a_instr_name() ;
if ( have(tk_number) ) return parse_a_instr_number() ;
mustbe(tk_a_instr) ;
return -1 ;
}
// tk_name is the token for '@' name
ast parse_a_instr_name()
{
string name = token_spelling() ;
next_token() ; // replace this with code to parse '@'name
return create_a_name(name) ;
}
// tk_number is the token for '@' number
ast parse_a_instr_number()
{
int ivalue = token_ivalue();
next_token() ; // replace this with code to parse '@'number
return create_a_instruction(ivalue) ;
}
// C-instr ::= dest? alu_op jump?
ast parse_c_instr()
{
string dest = "NULL" ;
if (have(tk_dest)){
dest = token_spelling() ;
next_token() ;
}
string alu_op = token_spelling() ;
next_token() ;
// if (have())
string jump = "NULL" ;
if (have(tk_jump)){
jump = token_spelling() ;
next_token() ;
}
return create_c_instruction(dest,alu_op,jump) ;
}
/***************** DOWN TO HERE ******************/
// main program
int main(int argc,char **argv)
{
// initialise the tokeniser by reading the first token
next_token() ;
// parse a class and print the abstract syntax tree as XML
ast_print_as_xml(parse_program(),4) ;
// flush the output and any errors
print_output() ;
print_errors() ;
}