aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse/regex
diff options
context:
space:
mode:
authorJonas Maier <jonas@x77.dev>2026-06-01 21:55:53 +0200
committerJonas Maier <jonas@x77.dev>2026-06-01 21:55:53 +0200
commitc73ed9310d8162b71183688de62bf8c1fc8420df (patch)
treec49063954f665a072cb8e63b10c4e95e31769826 /src/parse/regex
parentc52169f535f89c0300ec06e13ddcaa7e0f459a0b (diff)
downloadpish-c73ed9310d8162b71183688de62bf8c1fc8420df.tar.gz
syntax highlighting for regex; syntax highlighting syntax errors
Diffstat (limited to 'src/parse/regex')
-rw-r--r--src/parse/regex/mod.rs33
1 files changed, 31 insertions, 2 deletions
diff --git a/src/parse/regex/mod.rs b/src/parse/regex/mod.rs
index d5e4cdf..98056cb 100644
--- a/src/parse/regex/mod.rs
+++ b/src/parse/regex/mod.rs
@@ -1,3 +1,5 @@
+use crate::parse::OtherHighlights;
+
use super::{Parse, ParseError, Result};
mod byte_range;
@@ -16,10 +18,19 @@ pub enum Pattern {
impl Parse for Pattern {
fn parse(b: &mut super::Cursor<'_>) -> super::Result<Self> {
- parse_alt(b)
+ let begin = b.loc();
+ let result = parse0(b);
+ if result.is_ok() {
+ b.highlight_from(begin, OtherHighlights::Regex);
+ }
+ result
}
}
+fn parse0(s: &mut super::Cursor<'_>) -> Result<Pattern> {
+ parse_alt(s)
+}
+
fn parse_alt(s: &mut super::Cursor<'_>) -> Result<Pattern> {
let mut seqs = vec![];
loop {
@@ -27,8 +38,10 @@ fn parse_alt(s: &mut super::Cursor<'_>) -> Result<Pattern> {
if seq != Pattern::Nothing {
seqs.push(seq);
}
+ let begin = s.loc();
if s.has() && s.peek() == b'|' {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
} else {
break;
}
@@ -70,17 +83,22 @@ fn parse_rep(s: &mut super::Cursor<'_>) -> Result<Pattern> {
return Ok(atom);
}
+ let begin = s.loc();
+
match s.peek() {
b'*' => {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
Ok(Pattern::Rep(Box::new(atom), 0, None))
}
b'+' => {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
Ok(Pattern::Rep(Box::new(atom), 1, None))
}
b'?' => {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
Ok(Pattern::Rep(Box::new(atom), 0, Some(1)))
}
_ => Ok(atom),
@@ -99,21 +117,26 @@ fn parse_atom(s: &mut super::Cursor<'_>) -> Result<Pattern> {
return Ok(Pattern::Nothing);
}
+ let begin = s.loc();
+
match s.peek() {
b'[' => {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
let mut ranges = Vec::new();
loop {
if !s.has() {
return Err(ParseError::Eof);
}
+ let begin = s.loc();
let tok = s.adv();
if tok == b']' {
if ranges.is_empty() {
todo!("error handling for empty alternative list");
}
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
return Ok(Pattern::Alt(ranges));
}
@@ -121,8 +144,10 @@ fn parse_atom(s: &mut super::Cursor<'_>) -> Result<Pattern> {
return Err(ParseError::Unknown(tok));
}
+ let begin = s.loc();
if s.has() && s.peek() == b'-' {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
if !s.has() {
return Err(ParseError::Eof);
@@ -141,17 +166,21 @@ fn parse_atom(s: &mut super::Cursor<'_>) -> Result<Pattern> {
}
b'(' => {
s.adv();
- let inner = Pattern::parse(s)?;
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
+ let inner = parse0(s)?;
if !s.has() {
return Err(ParseError::Eof);
}
+ let begin = s.loc();
if s.adv() != b')' {
return Err(ParseError::Expected(')'));
}
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
Ok(inner)
}
b'.' => {
s.adv();
+ s.highlight_from(begin, OtherHighlights::RegexSymbol);
Ok(Pattern::Range(0, 127))
}
x if is_symbol(x) => Ok(Pattern::Nothing),