Skip to content

Commit b1022da

Browse files
authored
Parse and format Quantities (#63)
The last thing remaining needing support from the v0 version of the language was the Quantity type, whereby numeric values can have uncertainty, magnitude, and units, for example 5.9722 ± 0.0006 × 10²⁴ kg We add support in the parser for detecting quantity numericals, and appropriate code for presenting them nicely when formatting output. It also turned out that we weren't accounting for the width of Unicode characters when printing error messages. That is fixed, along with ensuring that the caret points to the best location relative to where the problem is.
2 parents 2cc00f6 + a2e93a9 commit b1022da

File tree

8 files changed

+873
-86
lines changed

8 files changed

+873
-86
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ tracing = "0.1.40"
1717
tracing-subscriber = { version = "0.3.18", features = [ "env-filter" ] }
1818

1919
[build-dependencies]
20+
21+
[profile.release]
22+
debug = "limited"
23+
strip = true
24+
lto = true

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright © 2002-2024 Athae Eredh Siniath and Others
1+
Copyright © 2002-2025 Athae Eredh Siniath and Others
22

33
Permission is hereby granted, free of charge, to any person obtaining a
44
copy of this software and associated documentation files (the "Software"),

src/error/display.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl<'i> TechniqueError<'i> {
2525
.unwrap_or("?");
2626

2727
let line = i + 1;
28-
let column = j;
28+
let column = j + 1;
2929

3030
let width = line
3131
.to_string()
@@ -38,7 +38,7 @@ impl<'i> TechniqueError<'i> {
3838
3939
{:width$} {}
4040
{:width$} {} {}
41-
{:width$} {} {:>j$}
41+
{:width$} {} {:>column$}
4242
4343
{}
4444
"#,
@@ -68,7 +68,7 @@ impl<'i> TechniqueError<'i> {
6868
let j = calculate_column_number(self.source, self.offset);
6969

7070
let line = i + 1;
71-
let column = j;
71+
let column = j + 1;
7272

7373
format!(
7474
"{}: {}:{}:{} {}",
@@ -103,8 +103,18 @@ fn calculate_line_number(content: &str, offset: usize) -> usize {
103103
fn calculate_column_number(content: &str, offset: usize) -> usize {
104104
let before = &content[..offset];
105105
match before.rfind('\n') {
106-
Some(start) => offset - start,
107-
None => offset,
106+
Some(start) => {
107+
// Count Unicode characters from the start of the line to the offset
108+
content[start + 1..offset]
109+
.chars()
110+
.count()
111+
}
112+
None => {
113+
// No newline found, count characters from the beginning
114+
before
115+
.chars()
116+
.count()
117+
}
108118
}
109119
}
110120

@@ -136,6 +146,35 @@ test
136146
.unwrap();
137147
assert_eq!(after, "test");
138148
}
149+
150+
#[test]
151+
fn counting_columns_ascii() {
152+
let content = "This is a test";
153+
154+
let col = calculate_column_number(content, 5);
155+
assert_eq!(col, 5); // After "This "
156+
}
157+
158+
#[test]
159+
fn counting_columns_unicode() {
160+
// Test with Unicode characters like those in Three.t: "3.0 × 10⁸ m_s"
161+
let content = "3.0 × 10⁸ m_s";
162+
163+
// At the underscore (× and ⁸ are multi-byte Unicode chars)
164+
let offset = "3.0 × 10⁸ m".len();
165+
let col = calculate_column_number(content, offset);
166+
assert_eq!(col, 11); // Should count 11 characters, not bytes
167+
}
168+
169+
#[test]
170+
fn counting_columns_multiline() {
171+
let content = "First line\nSecond × line";
172+
173+
// After "Second " on second line (× is multi-byte)
174+
let offset = "First line\n".len();
175+
let col = calculate_column_number(content, offset + 7);
176+
assert_eq!(col, 7);
177+
}
139178
}
140179

141180
#[derive(Debug)]

src/formatting/formatter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ impl Formatter {
822822
fn append_numeric(&mut self, numeric: &Numeric) {
823823
match numeric {
824824
Numeric::Integral(num) => self.append(Syntax::Numeric, &num.to_string()),
825-
Numeric::Scientific(_) => todo!(),
825+
Numeric::Scientific(quantity) => self.append(Syntax::Numeric, &quantity.to_string()),
826826
}
827827
}
828828

src/language/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Types representing the Technique procedures language
22

3+
mod quantity;
34
mod types;
45

56
// Re-export all public symbols
7+
pub use quantity::*;
68
pub use types::*;

0 commit comments

Comments
 (0)