Skip to content
This repository was archived by the owner on Dec 30, 2024. It is now read-only.

Commit 3ec1aa4

Browse files
Merge pull request #3 from ThePerfectComputer/backtrace
Backtrace
2 parents fa25bad + e8c215f commit 3ec1aa4

File tree

7 files changed

+203
-83
lines changed

7 files changed

+203
-83
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ name = "fastwave"
33
version = "0.1.0"
44
edition = "2021"
55

6+
[profile.release]
7+
debug = 1
8+
69
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
710

811
[dependencies]
912
num = "0.4"
1013
clap = { version = "3.1.8", features = ["derive"] }
1114
chrono = "0.4"
12-
itertools = "0.10.3"
15+
itertools = "0.10.3"
16+
backtrace = "0.3"

src/vcd/parse/combinator_atoms.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ pub(super) fn ident(
7676
) -> Result<(), String> {
7777
// let keyword = "module";
7878

79-
let err : Result<(), String> = Err(format!("reached end of file without parser leaving ident"));
80-
let word = word_reader.next_word();
81-
let (word, cursor) = word.ok_or(err).unwrap();
79+
let (word, cursor) = word_reader.next_word()?;
8280

8381
if word == keyword {
8482
return Ok(())

src/vcd/parse/events.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ pub(super) fn parse_events<'a>(
8484

8585
loop {
8686
let next_word = word_reader.next_word();
87-
// if we've reached the end of the file, then there is obviously
87+
// The following is the only case where eof is not an error.
88+
// If we've reached the end of the file, then there is obviously
8889
// nothing left to do...
89-
if next_word.is_none() {break};
90+
if next_word.is_err() {break};
9091

9192
let (word, cursor) = next_word.unwrap();
9293
let Cursor(Line(_), Word(word_in_line_idx)) = cursor;

src/vcd/parse/metadata.rs

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ pub(super) fn parse_date(
1717

1818
let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
1919
if !days.contains(&word) {
20-
let msg = format!("Error near {}:{}. Reached end of file without \
21-
terminating parser", file!(), line!());
20+
let msg = format!("Error near {}:{}.", file!(), line!());
2221
let msg2 = format!("{word} is not a valid weekday : expected one of {days:?}\n");
2322
let msg3 = format!("failure location: {cursor:?}");
2423
return Err(format!("{}{}{}", msg, msg2, msg3))
@@ -38,8 +37,7 @@ pub(super) fn parse_date(
3837
];
3938

4039
if !months.contains(&word) {
41-
let msg = format!("Error near {}:{}. Reached end of file without \
42-
terminating parser", file!(), line!());
40+
let msg = format!("Error near {}:{}.", file!(), line!());
4341
let msg2 = format!("{word} is not a valid month : expected one of {months:?}\n");
4442
let msg3 = format!("failure location: {cursor:?}");
4543
return Err(format!("{}{}{}", msg, msg2, msg3))
@@ -54,12 +52,11 @@ pub(super) fn parse_date(
5452

5553
let date : u8 = match word.to_string().parse() {
5654
Ok(date) => date,
57-
Err(_) => {return Err("".to_string())}
55+
Err(e) => {return Err(format!("Error near {}:{}. {e}", file!(), line!()))}
5856
};
5957

6058
if date > 31 {
61-
let msg = format!("Error near {}:{}. Reached end of file without \
62-
terminating parser", file!(), line!());
59+
let msg = format!("Error near {}:{}.", file!(), line!());
6360
let msg2 = format!("{word} is not a valid date : must be between 0 and 31\n");
6461
let msg3 = format!("failure location: {cursor:?}");
6562
return Err(format!("{}{}{}", msg, msg2, msg3))
@@ -77,7 +74,7 @@ pub(super) fn parse_date(
7774
res.assert_match()?;
7875
let hh : u8 = res.matched.to_string()
7976
.parse()
80-
.map_err(|_| "failed to parse".to_string())?;
77+
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;
8178

8279
if hh > 23 {
8380
let msg = format!("Error near {}:{}.", file!(), line!());
@@ -92,7 +89,7 @@ pub(super) fn parse_date(
9289
res.assert_match()?;
9390
let mm : u8 = res.matched.to_string()
9491
.parse()
95-
.map_err(|_| "failed to parse".to_string())?;
92+
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;
9693

9794
if mm > 60 {
9895
let msg = format!("Error near {}:{}.", file!(), line!());
@@ -107,7 +104,7 @@ pub(super) fn parse_date(
107104
let residual = &res.residual[1..]; // chop of colon which is at index 0
108105
let ss : u8 = residual.to_string()
109106
.parse()
110-
.map_err(|_| "failed to parse".to_string())?;
107+
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;
111108

112109
if ss > 60 {
113110
let msg = format!("Error near {}:{}.", file!(), line!());
@@ -132,24 +129,15 @@ pub(super) fn parse_date(
132129
return Ok(full_date.unwrap())
133130
}
134131

135-
Err("failed to parse date".to_string())
132+
Err(format!("Error near {}:{}. Failed to parse date.", file!(), line!()))
136133

137134
}
138135

139136
pub(super) fn parse_version(word_reader : &mut WordReader) -> Result<Version, String> {
140137
let mut version = String::new();
141138

142139
loop {
143-
let word = word_reader.next_word();
144-
145-
// if there isn't another word left in the file, then we exit
146-
if word.is_none() {
147-
let msg = format!("Error near {}:{}. Reached end of file without \
148-
terminating parser", file!(), line!());
149-
return Err(msg)
150-
}
151-
152-
let (word, _) = word.unwrap();
140+
let (word, _) = word_reader.next_word()?;
153141

154142
if word == "$end" {
155143
// truncate trailing whitespace
@@ -165,60 +153,56 @@ pub(super) fn parse_version(word_reader : &mut WordReader) -> Result<Version, St
165153
}
166154

167155
pub(super) fn parse_timescale(word_reader : &mut WordReader) -> Result<(Option<u32>, Timescale), String> {
168-
let err_msg = format!("Error near {}:{}. No more words left in vcd file.",
169-
file!(), line!());
170-
171-
// we might see `scalarunit $end` or `scalar unit $end`
172156

157+
// we might see `1ps $end` or `1 ps $end`
173158
// first get timescale
174-
let (word, _) = word_reader.next_word().ok_or(&err_msg)?;
159+
let (word, _) = word_reader.next_word()?;
175160
let word = word.to_string();
176161
let ParseResult{matched, residual} = take_while(word.as_str(), digit);
177162
let scalar = matched;
178163

179164
let scalar : u32 = scalar.to_string().parse()
180-
.map_err(|_| &err_msg)?;
165+
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;
181166

182167
let timescale = {
183168
if residual == "" {
184-
let (word, _) = word_reader.next_word().ok_or(&err_msg)?;
169+
let (word, _) = word_reader.next_word()?;
185170
let unit = match word {
186171
"fs" => {Ok(Timescale::Fs)}
187172
"ps" => {Ok(Timescale::Ps)}
188173
"ns" => {Ok(Timescale::Ns)}
189174
"us" => {Ok(Timescale::Us)}
190175
"ms" => {Ok(Timescale::Ms)}
191176
"s" => {Ok(Timescale::S)}
192-
_ => {Err(err_msg.to_string())}
177+
_ => {Err(format!("Error near {}:{}. Unknown unit {word}.", file!(), line!()))}
193178
}.unwrap();
194179

195180
(Some(scalar), unit)
196181
}
197182
else {
198183
let unit = match residual {
184+
"fs" => {Ok(Timescale::Fs)}
199185
"ps" => {Ok(Timescale::Ps)}
200186
"ns" => {Ok(Timescale::Ns)}
201187
"us" => {Ok(Timescale::Us)}
202188
"ms" => {Ok(Timescale::Ms)}
203189
"s" => {Ok(Timescale::S)}
204-
_ => {Err(err_msg.to_string())}
190+
_ => {Err(format!("Error near {}:{}. Unknown unit {residual}.", file!(), line!()))}
205191
}.unwrap();
206192

207193
(Some(scalar), unit)
208194
}
209195
};
210196

211197
// then check for the `$end` keyword
212-
let (end, _) = word_reader.next_word().ok_or(&err_msg)?;
198+
let (end, _) = word_reader.next_word()?;
213199
tag(end, "$end").assert_match()?;
214200

215201
return Ok(timescale);
216202

217203
}
218204

219205
pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result<Metadata, String> {
220-
let err_msg = format!("Error near {}:{}. No more words left in vcd file.",
221-
file!(), line!());
222206

223207
let mut metadata = Metadata {
224208
date : None,
@@ -228,7 +212,7 @@ pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result<Metadata,
228212

229213
loop {
230214
// check for another word in the file
231-
let (word, _) = word_reader.next_word().ok_or(&err_msg)?;
215+
let (word, _) = word_reader.next_word()?;
232216

233217
let ParseResult{matched, residual} = tag(word, "$");
234218
match matched {
@@ -254,7 +238,7 @@ pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result<Metadata,
254238
let mut lookahead_5_words : Vec<(String, Cursor)> = Vec::new();
255239

256240
for _ in 0..5 {
257-
let (word, cursor) = word_reader.next_word().expect(err_msg.as_str());
241+
let (word, cursor) = word_reader.next_word()?;
258242
let word = word.to_string();
259243
match word.as_str() {
260244
"$end" => {

src/vcd/parse/scopes.rs

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ pub(super) fn parse_var<'a>(
88
vcd : &'a mut VCD,
99
signal_map : &mut HashMap<String, SignalIdx>
1010
) -> Result<(), String> {
11-
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
12-
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
11+
let (word, cursor) = word_reader.next_word()?;
1312
let expected_types = ["integer", "parameter", "real", "reg", "string", "wire", "tri1", "time"];
1413

1514
// $var parameter 3 a IDLE $end
@@ -24,12 +23,14 @@ pub(super) fn parse_var<'a>(
2423
"tri1" => {Ok(SigType::Tri1)}
2524
"time" => {Ok(SigType::Time)}
2625
_ => {
27-
let err = format!("found keyword `{word}` but expected one of {expected_types:?} on {cursor:?}");
26+
let err = format!("Error near {}:{} \
27+
found keyword `{word}` but expected one of \
28+
{expected_types:?} on {cursor:?}", file!(), line!());
2829
Err(err)
2930
}
3031
}?;
3132

32-
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
33+
let (word, cursor) = word_reader.next_word()?;
3334
let parse_err = format!("failed to parse as usize on {cursor:?}");
3435

3536
// $var parameter 3 a IDLE $end
@@ -48,14 +49,14 @@ pub(super) fn parse_var<'a>(
4849

4950
// $var parameter 3 a IDLE $end
5051
// ^ - signal_alias
51-
let (word, _) = word_reader.next_word().ok_or(&err)?;
52+
let (word, _) = word_reader.next_word()?;
5253
let signal_alias = word.to_string();
5354

5455
// $var parameter 3 a IDLE $end
5556
// ^^^^ - full_signal_name(can extend until $end)
5657
let mut full_signal_name = Vec::<String>::new();
5758
loop {
58-
let (word, _) = word_reader.next_word().ok_or(&err)?;
59+
let (word, _) = word_reader.next_word()?;
5960
match word {
6061
"$end" => {break}
6162
_ => {full_signal_name.push(word.to_string())}
@@ -145,25 +146,17 @@ fn parse_orphaned_vars<'a>(
145146
parse_var(word_reader, scope_idx, vcd, signal_map)?;
146147

147148
loop {
148-
let next_word = word_reader.next_word();
149-
150-
// we shouldn't reach the end of the file here...
151-
if next_word.is_none() {
152-
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
153-
Err(err)?;
154-
};
155-
156-
let (word, cursor) = next_word.unwrap();
149+
let (word, cursor) = word_reader.next_word()?;
157150

158151
match word {
159152
"$var" => {
160153
parse_var(word_reader, scope_idx, vcd, signal_map)?;
161154
}
162155
"$scope" => {break}
163156
_ => {
164-
let (f, l )= (file!(), line!());
165-
let msg = format!("Error near {f}:{l}.\
166-
Expected $scope or $var, found {word} at {cursor:?}");
157+
let msg = format!("Error near {}:{}.\
158+
Expected $scope or $var, found \
159+
{word} at {cursor:?}", file!(), line!());
167160
Err(msg)?;
168161
}
169162
};
@@ -181,20 +174,21 @@ pub(super) fn parse_signal_tree<'a>(
181174

182175
// $scope module reg_mag_i $end
183176
// ^^^^^^ - module keyword
184-
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
185-
let (keyword, cursor) = word_reader.next_word().ok_or(&err)?;
177+
let (keyword, cursor) = word_reader.next_word()?;
186178

187179
let expected = ["module", "begin", "task", "function"];
188180
if expected.contains(&keyword) {
189181
Ok(())
190182
} else {
191-
let err = format!("found keyword `{keyword}` but expected one of `{expected:?}` on {cursor:?}");
183+
let err = format!("Error near {}:{}. \
184+
found keyword `{keyword}` but expected one of \
185+
{expected:?} on {cursor:?}", file!(), line!());
192186
Err(err)
193187
}?;
194188

195189
// $scope module reg_mag_i $end
196190
// ^^^^^^^^^ - scope name
197-
let (scope_name, _) = word_reader.next_word().ok_or(&err)?;
191+
let (scope_name, _) = word_reader.next_word()?;
198192

199193
let curr_scope_idx = ScopeIdx(vcd.all_scopes.len());
200194

@@ -227,7 +221,7 @@ pub(super) fn parse_signal_tree<'a>(
227221
ident(word_reader, "$end")?;
228222

229223
loop {
230-
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
224+
let (word, cursor) = word_reader.next_word()?;
231225
let ParseResult{matched, residual} = tag(word, "$");
232226
match matched {
233227
// we hope that this word starts with a `$`
@@ -251,13 +245,18 @@ pub(super) fn parse_signal_tree<'a>(
251245
}
252246
}
253247
_ => {
254-
let err = format!("found keyword `{residual}` but expected `$scope`, `$var`, `$comment`, or `$upscope` on {cursor:?}");
248+
let err = format!("Error near {}:{}. \
249+
found keyword `{residual}` but expected \
250+
`$scope`, `$var`, `$comment`, or `$upscope` \
251+
on {cursor:?}", file!(), line!());
255252
return Err(err)
256253
}
257254
}
258255
}
259256
_ => {
260-
let err = format!("found keyword `{matched}` but expected `$` on {cursor:?}");
257+
let err = format!("Error near {}:{}. \
258+
found keyword `{matched}` but \
259+
expected `$` on {cursor:?}", file!(), line!());
261260
return Err(err)
262261
}
263262
}
@@ -272,25 +271,24 @@ pub(super) fn parse_scopes<'a>(
272271
signal_map : &mut HashMap<String, SignalIdx>
273272
) -> Result<(), String> {
274273
// get the current word
275-
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
276-
let (word, _) = word_reader.curr_word().ok_or(&err)?;
274+
let (word, _) = word_reader.curr_word()?;
277275

278276
// we may have orphaned vars that occur before the first scope
279277
if word == "$var" {
280278
parse_orphaned_vars(word_reader, vcd, signal_map)?;
281279
}
282280

283281
// get the current word
284-
let (word, cursor) = word_reader.curr_word().ok_or(&err)?;
282+
let (word, cursor) = word_reader.curr_word()?;
285283

286284
// the current word should be "scope", as `parse_orphaned_vars`(if it
287285
// was called), should have terminated upon encountering "$scope".
288286
// If `parse_orphaned_vars` was not called, `parse_scopes` should still
289287
// have only been called if the caller encountered the word "$scope"
290288
if word != "$scope" {
291-
let (f, l )= (file!(), line!());
292-
let msg = format!("Error near {f}:{l}.\
293-
Expected $scope or $var, found {word} at {cursor:?}");
289+
let msg = format!("Error near {}:{}.\
290+
Expected $scope or $var, found \
291+
{word} at {cursor:?}", file!(), line!());
294292
return Err(msg)
295293
}
296294

@@ -305,7 +303,7 @@ pub(super) fn parse_scopes<'a>(
305303
// because this loop gets a word from `next_word` instead of
306304
// `curr_word()`.
307305
loop {
308-
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
306+
let (word, cursor) = word_reader.next_word()?;
309307
match word {
310308
"$scope" => {
311309
parse_signal_tree(word_reader, None, vcd, signal_map)?;
@@ -322,8 +320,9 @@ pub(super) fn parse_scopes<'a>(
322320
}
323321
}
324322
_ => {
325-
let err = format!("found keyword `{word}` but expected one \
326-
of `{expected_keywords:?}` on {cursor:?}");
323+
let err = format!("Error near {}:{} \
324+
found keyword `{word}` but expected one of \
325+
{expected_keywords:?} on {cursor:?}", file!(), line!());
327326
return Err(err)
328327

329328
}

0 commit comments

Comments
 (0)