Skip to content

Commit ef09758

Browse files
authored
make ?,n merge adjacent ?s (#806)
* merge ?s into adjacent ?,n * document ?,n merging ?s * document ?,n merging ?s in /docs/stack
1 parent 31df9bc commit ef09758

File tree

3 files changed

+70
-7
lines changed

3 files changed

+70
-7
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ This version is not yet released. If you are reading this on the website, then t
4545
- [`un °`](https://uiua.org/docs/un)[`&cd`](https://uiua.org/docs/&cd) will output the current working directory
4646
- [`under ⍜`](https://uiua.org/docs/under)[`&cd`](https://uiua.org/docs/&cd) will return to the original directory afterward
4747
- Add experimental [`reciprocal ⨪`](https://uiua.org/docs/reciprocal) function, which computes the multiplicative inverse AKA reciprocal of a number
48+
- Make subscripted [`stack ?`](https://uiua.org/docs/stack) merge adjacent non-subscripted [`stack ?`](https://uiua.org/docs/stack) chains
4849
### Interpreter
4950
- Speed up the implementation of [`or ∨`](https://uiua.org/docs/or)
5051
- The fomatter no longer truncates trailing decimal `0`s from number literals

parser/src/defs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2923,7 +2923,10 @@ primitive!(
29232923
/// Subscripted [stack] prints that many values from the stack.
29242924
/// ex: ?₂ 1 2 3 4
29252925
/// If you type `N+1` `?`s, it will format to [stack] subscripted with `N`.
2926-
/// ex: ??? 1 2 3 4 # Try formatting!
2926+
/// A subscripted `?` will merge adjacent `?s` into its subscript.
2927+
/// ex: # Try formatting!
2928+
/// : ???? 1 2 3 4
2929+
/// : ?₂?? 5 6 7 8
29272930
(0(0), Stack, Debug, ("stack", '?'), Mutating),
29282931
/// Preprocess and print all stack values without popping them
29292932
///

parser/src/lex.rs

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,13 +1118,68 @@ impl<'a> Lexer<'a> {
11181118
// Stack
11191119
"?" => {
11201120
self.end(Primitive::Stack, start);
1121-
let mut n = 0;
11221121
let start = self.loc;
1123-
while self.next_char_exact("?") {
1124-
n += 1;
1122+
1123+
fn read_chain(lexer: &mut Lexer) -> (i32, Loc) {
1124+
let mut n = 0;
1125+
let mut before_last = lexer.loc;
1126+
loop {
1127+
let start = lexer.loc;
1128+
if lexer.next_char_exact("?") {
1129+
n += 1;
1130+
if lexer.peek_char() != Some("?") {
1131+
before_last = start;
1132+
break;
1133+
}
1134+
} else {
1135+
break;
1136+
}
1137+
}
1138+
(n, before_last)
11251139
}
1126-
if n > 0 {
1127-
self.end(Subscr(Subscript::numeric(n)), start);
1140+
1141+
let (n, before_last_in_chain) = read_chain(&mut self);
1142+
1143+
let subscript = {
1144+
if self.next_char_exact(",") || self.next_chars_exact(["_"; 2]) {
1145+
Some(self.subscript(","))
1146+
} else if self.peek_char().map_or(false, is_formatted_subscript) {
1147+
let init = self.next_char().unwrap();
1148+
Some(self.subscript(init))
1149+
} else {
1150+
None
1151+
}
1152+
};
1153+
match subscript {
1154+
Some(Subscript {
1155+
num: Some(NumericSubscript::N(num)),
1156+
side: None,
1157+
}) => {
1158+
let (m, before_last_2nd_chain) = read_chain(&mut self);
1159+
let has_2nd_subscript = self.next_char_exact(",")
1160+
|| self.next_chars_exact(["_"; 2])
1161+
|| self.peek_char().map_or(false, is_formatted_subscript);
1162+
if !has_2nd_subscript {
1163+
self.end(Subscr(Subscript::numeric(n + num + m)), start);
1164+
} else {
1165+
let sub_num = n + num + (m - 1).max(0);
1166+
self.loc = before_last_2nd_chain;
1167+
self.end(Subscr(Subscript::numeric(sub_num)), start);
1168+
}
1169+
}
1170+
Some(_) => {
1171+
// invalid subscript
1172+
self.loc = before_last_in_chain;
1173+
if n > 1 {
1174+
self.end(Subscr(Subscript::numeric(n - 1)), start);
1175+
}
1176+
}
1177+
None => {
1178+
// no subscript
1179+
if n != 0 {
1180+
self.end(Subscr(Subscript::numeric(n)), start);
1181+
}
1182+
}
11281183
}
11291184
}
11301185
// Comments
@@ -1263,7 +1318,7 @@ impl<'a> Lexer<'a> {
12631318
}
12641319
}
12651320
// Formatted subscripts
1266-
c if "₋⌞⌟".contains(c) || c.chars().all(|c| SUBSCRIPT_DIGITS.contains(&c)) => {
1321+
c if is_formatted_subscript(c) => {
12671322
let sub = self.subscript(c);
12681323
self.end(Subscr(sub), start)
12691324
}
@@ -1706,6 +1761,10 @@ pub fn is_custom_glyph(c: &str) -> bool {
17061761
}
17071762
}
17081763

1764+
fn is_formatted_subscript(c: &str) -> bool {
1765+
"₋⌞⌟".contains(c) || c.chars().all(|c| SUBSCRIPT_DIGITS.contains(&c))
1766+
}
1767+
17091768
pub(crate) fn canonicalize_ident(ident: &str) -> Ident {
17101769
canonicalize_subscripts(canonicalize_exclams(ident))
17111770
}

0 commit comments

Comments
 (0)