Skip to content
This repository was archived by the owner on Nov 25, 2019. It is now read-only.

Commit 177bdd5

Browse files
authored
Merge branch 'master' into rust-rewrite
2 parents eca08ba + 52b9299 commit 177bdd5

File tree

3 files changed

+258
-1
lines changed

3 files changed

+258
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ rust: setup
3131
rustc rust/main.rs -o $(EXE)
3232

3333
clean:
34-
-rm $(EXECUTABLE)
34+
-rm $(EXECUTABLE)

bin/.gitkeep

Whitespace-only changes.

src/qqq.cpp

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
//
2+
// qqq.cpp
3+
// ??? (Programming Language)
4+
//
5+
// Created by Alex A. and BrainSteel
6+
// Based heavily on https://gist.github.com/migimunz/964338
7+
//
8+
9+
#include <iostream>
10+
#include <fstream>
11+
#include <sstream>
12+
#include <stdexcept>
13+
#include <vector>
14+
15+
16+
typedef char CELL;
17+
typedef std::vector<CELL> instruction_t;
18+
typedef instruction_t::iterator instruction_pointer;
19+
20+
typedef std::vector<CELL> memory_t;
21+
typedef memory_t::iterator memory_pointer;
22+
23+
24+
struct environment {
25+
memory_t memory;
26+
instruction_t instructions;
27+
28+
instruction_pointer ip;
29+
memory_pointer mp;
30+
31+
environment() : memory(3000) {
32+
clear();
33+
mp = memory.begin();
34+
}
35+
36+
void clear() {
37+
instructions.clear();
38+
ip = instructions.begin();
39+
}
40+
};
41+
42+
43+
void interpret(environment &env);
44+
int from_line(environment &env, std::string &line, int open_quotes = 0);
45+
int from_stream(environment &env, std::istream &stream, int open_quotes = 0);
46+
void interactive_mode(environment &env);
47+
void print_cell(CELL cell);
48+
49+
50+
int main(int argc, const char* argv[]) {
51+
52+
std::string filename;
53+
54+
if (argc < 2) {
55+
std::cout << "Enter a file:\n";
56+
std::cin >> filename;
57+
} else {
58+
filename = argv[1];
59+
}
60+
61+
std::ifstream infile(filename.c_str());
62+
63+
if (infile.is_open()) {
64+
65+
environment env;
66+
67+
int unmatched_quotes = from_stream(env, infile);
68+
69+
if (unmatched_quotes == 0) {
70+
interpret(env);
71+
} else {
72+
std::cerr << "Um, match up your quotes and try again.\n";
73+
return 1;
74+
}
75+
76+
infile.close();
77+
78+
} else {
79+
std::cerr << "Input file does not exist!\n";
80+
return 1;
81+
}
82+
83+
return 0;
84+
}
85+
86+
87+
/*
88+
* Prints a memory cell, or hex representation if unprintable
89+
*/
90+
void print_cell(CELL cell) {
91+
92+
if (isprint(cell))
93+
std::cout << cell;
94+
else
95+
std::cout << "0x" << std::hex << (int)cell << std::dec;
96+
}
97+
98+
99+
/*
100+
* Reads code from a line, returns number of unmatched quotes
101+
*/
102+
int from_line(environment &env, std::string &line, int open_quotes) {
103+
104+
std::istringstream stream(line);
105+
106+
return from_stream(env, stream, open_quotes);
107+
}
108+
109+
110+
/*
111+
* Reads code from a stream into env.instructions
112+
*/
113+
int from_stream(environment &env, std::istream &stream, int open_quotes) {
114+
115+
if (open_quotes == 0)
116+
env.instructions.push_back('\0');
117+
118+
CELL cell;
119+
120+
bool is_open = true;
121+
122+
while (true) {
123+
stream >> cell;
124+
125+
if (!stream)
126+
break;
127+
128+
switch (cell) {
129+
case '!':
130+
case '?':
131+
case '.':
132+
case ',':
133+
case '-':
134+
case ';':
135+
env.instructions.push_back(cell);
136+
break;
137+
138+
case '\'':
139+
is_open = !is_open;
140+
break;
141+
142+
case '"':
143+
if (is_open) {
144+
open_quotes++;
145+
env.instructions.push_back('[');
146+
} else {
147+
open_quotes--;
148+
env.instructions.push_back(']');
149+
}
150+
break;
151+
152+
default:
153+
break;
154+
}
155+
156+
if (open_quotes < 0)
157+
break;
158+
}
159+
160+
if (open_quotes == 0)
161+
env.instructions.push_back('\0');
162+
163+
return open_quotes;
164+
}
165+
166+
167+
/*
168+
* Finds the closing bracket, moves the ip to it
169+
*/
170+
void find_closing(environment &env) {
171+
int balance = 1;
172+
do {
173+
env.ip++;
174+
if (*env.ip == '[')
175+
balance++;
176+
else if (*env.ip == ']')
177+
balance--;
178+
} while (balance != 0);
179+
}
180+
181+
182+
/*
183+
* Finds the opening bracket, moves the ip to one cell before it
184+
*/
185+
void find_opening(environment &env) {
186+
int balance = 0;
187+
do {
188+
if (*env.ip == '[')
189+
balance++;
190+
else if (*env.ip == ']')
191+
balance--;
192+
env.ip--;
193+
} while (balance != 0);
194+
}
195+
196+
197+
/*
198+
* Interprets code
199+
*/
200+
void interpret(environment &env) {
201+
202+
env.ip = env.instructions.begin();
203+
204+
while (env.ip != env.instructions.end()) {
205+
206+
switch (*env.ip) {
207+
case '.':
208+
(*env.mp)++;
209+
env.ip++;
210+
break;
211+
212+
case ',':
213+
(*env.mp)--;
214+
env.ip++;
215+
break;
216+
217+
case ';':
218+
if (env.mp != (env.memory.end()--))
219+
env.mp++;
220+
env.ip++;
221+
break;
222+
223+
case '-':
224+
if (env.mp != env.memory.begin())
225+
env.mp--;
226+
env.ip++;
227+
break;
228+
229+
case '!':
230+
print_cell(*env.mp);
231+
env.ip++;
232+
break;
233+
234+
case '?':
235+
CELL cell;
236+
std::cin >> cell;
237+
(*env.mp) = cell;
238+
env.ip++;
239+
break;
240+
241+
case '[':
242+
if (!(*env.mp))
243+
find_closing(env);
244+
env.ip++;
245+
break;
246+
247+
case ']':
248+
find_opening(env);
249+
env.ip++;
250+
break;
251+
252+
case '\0':
253+
env.ip++;
254+
break;
255+
}
256+
}
257+
}

0 commit comments

Comments
 (0)