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
|
use crate::Word;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Token {
Label(String),
Operator(String),
Symbol(String),
SymbolDef(String),
Number(Word),
Address(Word),
String(String),
}
pub fn split(mut line: String) -> Vec<Token> {
line.push('\n');
let mut res = Vec::new();
let mut buffer = String::new();
let mut has_label = false;
let mut string_started = false;
let mut skip_next = false;
let mut address = false;
for c in line.chars() {
buffer.push(c);
if skip_next || (string_started && c != '"') {
skip_next = false;
continue;
}
match c {
':' => if ! has_label {
buffer.pop();
res.push(Token::Label(buffer.clone()));
buffer.clear();
has_label = true;
}
else {
panic!("Found double labels!");
},
' ' | '\t' => {
buffer.pop();
if buffer.is_empty() { continue; }
if (has_label && (res.len() == 1)) ||
(!has_label && (res.is_empty())) {
res.push(Token::Operator(buffer.clone()));
buffer.clear();
}
},
'"' => {
buffer.pop();
if string_started {
res.push(Token::String(buffer.clone()));
buffer.clear();
}
string_started = !string_started;
},
',' | '\n' | ';' => {
buffer.pop();
if buffer.is_empty() {
if c == ';' { break; } else { continue; }
}
if let Some(num) = buffer.parse::<Word>().ok() {
if address {
address = false;
res.push(Token::Address(num));
}
else {
res.push(Token::Number(num));
}
}
else if res.len() == has_label as usize {
res.push(Token::Operator(buffer.clone()));
}
else {
res.push(Token::Symbol(buffer.clone()));
}
buffer.clear();
if c == ';' { break; }
},
'=' => if buffer.is_empty() {
panic!("Cannot begin the line with an =")
}
else if let Token::Operator(name) = &res[0] {
res[0] = Token::SymbolDef(name.clone());
buffer.clear();
}
else {
panic!("Before an = you may only have a symbol name!");
},
'\\' => skip_next = true,
'%' => { buffer.pop(); address = true; },
'-' => if address {
panic!("Addresses cannot be negative!");
},
'A'..='Z' | 'a'..='z' | '0'..='9' | '_' | '.' | '$' | '?'
=> {},
_ => panic!("Found invalid character '{}'", c),
}
}
res
}
|