Admit private syntax text before named producers grow
This commit is contained in:
@@ -1018,6 +1018,16 @@ fn edit_positions_from_tokens(
|
||||
token: impl Fn(usize) -> Lexeme,
|
||||
count: usize,
|
||||
value_ends: Option<&BTreeMap<usize, usize>>,
|
||||
) -> Result<Vec<(Id, EditDeclaration)>, Box<Diagnostic>> {
|
||||
edit_positions_from_tokens_with_text(source, unit, token, count, value_ends, |_, _| Ok(()))
|
||||
}
|
||||
fn edit_positions_from_tokens_with_text(
|
||||
source: &str,
|
||||
unit: &SourceUnit,
|
||||
token: impl Fn(usize) -> Lexeme,
|
||||
count: usize,
|
||||
value_ends: Option<&BTreeMap<usize, usize>>,
|
||||
text: impl FnMut(usize, Span) -> Result<(), Box<Diagnostic>>,
|
||||
) -> Result<Vec<(Id, EditDeclaration)>, Box<Diagnostic>> {
|
||||
let mut ends: Vec<_> = (0..count).map(|at| token(at).span.end).collect();
|
||||
let mut stack = Vec::new();
|
||||
@@ -1029,12 +1039,15 @@ fn edit_positions_from_tokens(
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
struct Positions<'a, F> {
|
||||
struct Positions<'a, F, H> {
|
||||
token_at: F,
|
||||
ends: Vec<usize>,
|
||||
value_ends: Option<&'a BTreeMap<usize, usize>>,
|
||||
text: H,
|
||||
}
|
||||
impl<F: Fn(usize) -> Lexeme> Positions<'_, F> {
|
||||
impl<F: Fn(usize) -> Lexeme, H: FnMut(usize, Span) -> Result<(), Box<Diagnostic>>>
|
||||
Positions<'_, F, H>
|
||||
{
|
||||
fn token(&self, start: usize) -> usize {
|
||||
let mut low = 0;
|
||||
let mut high = self.ends.len();
|
||||
@@ -1048,24 +1061,28 @@ fn edit_positions_from_tokens(
|
||||
}
|
||||
low
|
||||
}
|
||||
fn fields(&self, fields: &BTreeMap<String, Ast>) -> BTreeMap<String, EditField> {
|
||||
fn fields(
|
||||
&mut self,
|
||||
fields: &BTreeMap<String, Ast>,
|
||||
) -> Result<BTreeMap<String, EditField>, Box<Diagnostic>> {
|
||||
fields
|
||||
.iter()
|
||||
.map(|(key, ast)| {
|
||||
let value = self.value(ast);
|
||||
let value = self.value(ast)?;
|
||||
let start = (self.token_at)(self.token(value.span.start) - 1).span.start;
|
||||
let end = (self.token_at)(self.token(value.span.end)).span.end;
|
||||
(
|
||||
(self.text)(key.len(), Span { start, end })?;
|
||||
Ok((
|
||||
key.clone(),
|
||||
EditField {
|
||||
span: Span { start, end },
|
||||
value,
|
||||
},
|
||||
)
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
fn value(&self, ast: &Ast) -> EditValue {
|
||||
fn value(&mut self, ast: &Ast) -> Result<EditValue, Box<Diagnostic>> {
|
||||
let index = self.token(ast.offset());
|
||||
let span = Span {
|
||||
start: ast.offset(),
|
||||
@@ -1080,21 +1097,28 @@ fn edit_positions_from_tokens(
|
||||
}),
|
||||
};
|
||||
let kind = match ast {
|
||||
Ast::Object(fields, _) => EditKind::Record(self.fields(fields)),
|
||||
Ast::Array(items, _) => {
|
||||
EditKind::List(items.iter().map(|item| self.value(item)).collect())
|
||||
Ast::Object(fields, _) => EditKind::Record(self.fields(fields)?),
|
||||
Ast::Array(items, _) => EditKind::List(
|
||||
items
|
||||
.iter()
|
||||
.map(|item| self.value(item))
|
||||
.collect::<Result<_, _>>()?,
|
||||
),
|
||||
Ast::Reference(alias, _) => {
|
||||
(self.text)(alias.len(), span)?;
|
||||
EditKind::Reference(alias.clone())
|
||||
}
|
||||
Ast::Reference(alias, _) => EditKind::Reference(alias.clone()),
|
||||
Ast::HistoricalUuid(id, _) => EditKind::HistoricalUuid(*id),
|
||||
_ => EditKind::Atom,
|
||||
};
|
||||
EditValue { span, kind }
|
||||
Ok(EditValue { span, kind })
|
||||
}
|
||||
}
|
||||
let positions = Positions {
|
||||
let mut positions = Positions {
|
||||
token_at: &token,
|
||||
ends,
|
||||
value_ends,
|
||||
text,
|
||||
};
|
||||
unit.declarations
|
||||
.iter()
|
||||
@@ -1132,7 +1156,7 @@ fn edit_positions_from_tokens(
|
||||
start: declaration.body.start - 1,
|
||||
end: declaration.body.end + 1,
|
||||
},
|
||||
kind: EditKind::Record(positions.fields(&declaration.fields)),
|
||||
kind: EditKind::Record(positions.fields(&declaration.fields)?),
|
||||
},
|
||||
},
|
||||
))
|
||||
@@ -1196,11 +1220,24 @@ impl Parser<'_> {
|
||||
if self.current().class != TokenClass::String {
|
||||
return Err(self.error("Expected a double-quoted string."));
|
||||
}
|
||||
#[cfg(test)]
|
||||
if self.mixed.is_some() {
|
||||
let span = self.current().span;
|
||||
let raw = &self.source[span.start..span.end];
|
||||
let value = self
|
||||
.mixed
|
||||
.as_mut()
|
||||
.expect("mixed quoted consumer")
|
||||
.quoted_text(raw, span)?;
|
||||
self.cursor += 1;
|
||||
return Ok(value);
|
||||
}
|
||||
let value = serde_json::from_str(self.text()).unwrap();
|
||||
self.cursor += 1;
|
||||
Ok(value)
|
||||
}
|
||||
fn identifier(&mut self) -> Result<String, Error> {
|
||||
self.own_text(self.text().len(), self.current().span)?;
|
||||
let value = self.text().to_owned();
|
||||
if !crate::valid_alias(&value) {
|
||||
return Err(self.error(std::format!("Invalid or reserved alias '{value}'.")));
|
||||
@@ -1230,11 +1267,32 @@ impl Parser<'_> {
|
||||
message: "Expected UUID in 8-4-4-4-12 hexadecimal form.".into(),
|
||||
});
|
||||
}
|
||||
Id::parse_str(&value).map_err(|_| Error {
|
||||
let id = Id::parse_str(&value).map_err(|_| Error {
|
||||
code: "invalid_source",
|
||||
offset,
|
||||
message: "Invalid UUID identity.".into(),
|
||||
})
|
||||
})?;
|
||||
let bytes = value.len();
|
||||
drop(value);
|
||||
self.release_text(bytes);
|
||||
Ok(id)
|
||||
}
|
||||
fn own_text(&mut self, bytes: usize, span: Span) -> Result<(), Error> {
|
||||
#[cfg(test)]
|
||||
if let Some(mixed) = &mut self.mixed {
|
||||
mixed.own_text(bytes, span)?;
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
let _ = (bytes, span);
|
||||
Ok(())
|
||||
}
|
||||
fn release_text(&mut self, bytes: usize) {
|
||||
#[cfg(test)]
|
||||
if let Some(mixed) = &mut self.mixed {
|
||||
mixed.release_text(bytes);
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
let _ = bytes;
|
||||
}
|
||||
fn fields(&mut self) -> Result<BTreeMap<String, Ast>, Error> {
|
||||
self.take("{")?;
|
||||
@@ -1242,6 +1300,13 @@ impl Parser<'_> {
|
||||
while self.text() != "}" {
|
||||
let offset = self.current().span.start;
|
||||
let (key, value, _) = self.field()?;
|
||||
self.own_text(
|
||||
key.len(),
|
||||
Span {
|
||||
start: offset,
|
||||
end: offset,
|
||||
},
|
||||
)?;
|
||||
if fields.insert(key.clone(), value).is_some() {
|
||||
return Err(Error {
|
||||
code: "invalid_source",
|
||||
@@ -1249,12 +1314,16 @@ impl Parser<'_> {
|
||||
message: std::format!("Duplicate field '{key}'."),
|
||||
});
|
||||
}
|
||||
let bytes = key.len();
|
||||
drop(key);
|
||||
self.release_text(bytes);
|
||||
}
|
||||
self.take("}")?;
|
||||
Ok(fields)
|
||||
}
|
||||
fn field(&mut self) -> Result<(String, Ast, Span), Error> {
|
||||
self.syntax_entry()?;
|
||||
self.own_text(self.text().len(), self.current().span)?;
|
||||
let key = self.text().to_owned();
|
||||
if !matches!(
|
||||
self.current().class,
|
||||
@@ -1328,6 +1397,9 @@ impl Parser<'_> {
|
||||
offset,
|
||||
message: "Expected a UUID after uuid.".into(),
|
||||
})?;
|
||||
let bytes = value.len();
|
||||
drop(value);
|
||||
self.release_text(bytes);
|
||||
Ok(Ast::HistoricalUuid(id, offset))
|
||||
}
|
||||
"@" => {
|
||||
@@ -1368,6 +1440,7 @@ impl Parser<'_> {
|
||||
Ok(Ast::Literal(value, offset))
|
||||
}
|
||||
TokenClass::Identifier | TokenClass::Keyword => {
|
||||
self.own_text(self.text().len(), self.current().span)?;
|
||||
let value = self.text().to_owned();
|
||||
self.cursor += 1;
|
||||
Ok(Ast::Word(value, offset))
|
||||
@@ -1514,6 +1587,7 @@ impl Parser<'_> {
|
||||
}
|
||||
} else {
|
||||
let (key, value, span) = self.field()?;
|
||||
self.own_text(key.len(), span)?;
|
||||
let declaration = &mut declarations[owner];
|
||||
if declaration.fields.insert(key.clone(), value).is_some() {
|
||||
return Err(Error {
|
||||
@@ -1584,8 +1658,8 @@ impl Parser<'_> {
|
||||
return Err(self.error("Use the short source8 analysis declaration word."));
|
||||
}
|
||||
self.syntax_entry()?;
|
||||
let word = self.text().to_owned();
|
||||
let kind = declaration_kind(&word)
|
||||
let word = self.current().text(self.source);
|
||||
let kind = declaration_kind(word)
|
||||
.ok_or_else(|| self.error(format!("Unknown declaration '{word}'.")))?;
|
||||
#[cfg(test)]
|
||||
if let Some(mixed) = &mut self.mixed {
|
||||
|
||||
Reference in New Issue
Block a user