git.delta.rocks / jrsonnet / refs/commits / 4e8e144facbc

difftreelog

fix(ir-parser) identifiers can't be reserved

onkxzzmmLach2026-04-04parent: #8885f21.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth
130 message,130 message,
131 }131 }
132 }132 }
133
134 fn expect_ident(&mut self) -> Result<IStr> {
135 if !self.at(SyntaxKind::IDENT) {
136 return Err(self.error(format!("expected identifier, got {}", self.current_desc())));
137 }
138 let text = self.text();
139 let s: IStr = text.into();
140 self.eat_any();
141 Ok(s)
142 }
143
144 fn at_ident(&self) -> bool {
145 self.at(SyntaxKind::IDENT) && !is_reserved(self.lexemes[self.offset].text)
146 }
147}133}
148134
149fn spanned<T: Acyclic>(135fn spanned<T: Acyclic>(
222 Ok(n)208 Ok(n)
223}209}
224210
211fn ident(p: &mut Parser<'_>) -> Result<IStr> {
212 let text = p.text();
213 p.eat(SyntaxKind::IDENT)?;
214 Ok(IStr::from(text))
215}
216
225fn literal(p: &mut Parser<'_>) -> Option<LiteralType> {217fn literal(p: &mut Parser<'_>) -> Option<LiteralType> {
226 let t = match p.peek() {218 let t = match p.peek() {
227 T![self] => LiteralType::This,219 T![self] => LiteralType::This,
289}281}
290282
291fn destruct(p: &mut Parser<'_>) -> Result<Destruct> {283fn destruct(p: &mut Parser<'_>) -> Result<Destruct> {
292 if p.at_ident() {284 if p.at(SyntaxKind::IDENT) {
293 return Ok(Destruct::Full(p.expect_ident()?));285 return Ok(Destruct::Full(ident(p)?));
294 }286 }
295 #[cfg(not(feature = "exp-destruct"))]287 #[cfg(not(feature = "exp-destruct"))]
296 return Err(p.error(format!("expected identifier, got {}", p.current_desc())));288 return Err(p.error(format!("expected identifier, got {}", p.current_desc())));
315#[cfg(feature = "exp-destruct")]307#[cfg(feature = "exp-destruct")]
316fn destruct_rest(p: &mut Parser<'_>) -> Result<jrsonnet_ir::DestructRest> {308fn destruct_rest(p: &mut Parser<'_>) -> Result<jrsonnet_ir::DestructRest> {
317 p.eat(T![...])?;309 p.eat(T![...])?;
318 if p.at_ident() {310 if p.at(SyntaxKind::IDENT) {
319 Ok(jrsonnet_ir::DestructRest::Keep(p.expect_ident()?))311 Ok(jrsonnet_ir::DestructRest::Keep(ident(p)?))
320 } else {312 } else {
321 Ok(jrsonnet_ir::DestructRest::Drop)313 Ok(jrsonnet_ir::DestructRest::Drop)
322 }314 }
372 p.try_eat(T![,]);364 p.try_eat(T![,]);
373 break;365 break;
374 }366 }
375 let name = p.expect_ident()?;367 let name = ident(p)?;
376 let into = if p.try_eat(T![:]) {368 let into = if p.try_eat(T![:]) {
377 Some(destruct(p)?)369 Some(destruct(p)?)
378 } else {370 } else {
430 let mut named = Vec::new();422 let mut named = Vec::new();
431 let mut named_started = false;423 let mut named_started = false;
432 loop {424 loop {
433 let is_named = p.at_ident() && {425 let is_named = p.at(SyntaxKind::IDENT) && {
434 let next_offset = p.offset + 1;426 let next_offset = p.offset + 1;
435 next_offset < p.lexemes.len() && p.lexemes[next_offset].kind == T![=] && {427 next_offset < p.lexemes.len() && p.lexemes[next_offset].kind == T![=]
436 let after_eq = next_offset + 1;
437 after_eq >= p.lexemes.len() || p.lexemes[after_eq].kind != T![=]
438 }
439 };428 };
440 if is_named {429 if is_named {
441 let name: IStr = p.expect_ident()?;430 let name: IStr = ident(p)?;
442 p.eat(T![=])?;431 p.eat(T![=])?;
443 let value = Rc::new(expr(p)?);432 let value = Rc::new(expr(p)?);
444 named.push((name, value));433 named.push((name, value));
462fn bind(p: &mut Parser<'_>) -> Result<BindSpec> {451fn bind(p: &mut Parser<'_>) -> Result<BindSpec> {
463 #[cfg(feature = "exp-destruct")]452 #[cfg(feature = "exp-destruct")]
464 {453 {
465 if !p.at_ident() {454 if !p.at(SyntaxKind::IDENT) {
466 let d = destruct(p)?;455 let d = destruct(p)?;
467 p.eat(T![=])?;456 p.eat(T![=])?;
468 let value = Rc::new(expr(p)?);457 let value = Rc::new(expr(p)?);
469 return Ok(BindSpec::Field { into: d, value });458 return Ok(BindSpec::Field { into: d, value });
470 }459 }
471 }460 }
472 let name = p.expect_ident()?;461 let name = ident(p)?;
473 if p.try_eat(T!['(']) {462 if p.try_eat(T!['(']) {
474 let ps = params(p)?;463 let ps = params(p)?;
475 p.eat(T![')'])?;464 p.eat(T![')'])?;
504}493}
505494
506fn field_name(p: &mut Parser<'_>) -> Result<FieldName> {495fn field_name(p: &mut Parser<'_>) -> Result<FieldName> {
507 if p.at_ident() {496 if p.at(SyntaxKind::IDENT) {
508 Ok(FieldName::Fixed(p.expect_ident()?))497 Ok(FieldName::Fixed(ident(p)?))
509 } else if is_string_token(p.peek()) {498 } else if is_string_token(p.peek()) {
510 Ok(FieldName::Fixed(parse_string_content(p)?))499 Ok(FieldName::Fixed(parse_string_content(p)?))
511 } else if p.at(T!['[']) {500 } else if p.at(T!['[']) {
776765
777 SyntaxKind::IDENT => {766 SyntaxKind::IDENT => {
778 let text = p.text();767 let text = p.text();
779 if is_reserved(text) {
780 return Err(p.error(format!("unexpected reserved word '{text}'")));
781 }
782 let n = spanned(p, |p| {768 let n = spanned(p, |p| {
783 let s: IStr = p.text().into();769 let s: IStr = p.text().into();
784 p.eat_any();770 p.eat_any();
826 });812 });
827 } else {813 } else {
828 // ?.field814 // ?.field
829 let id_spanned = spanned(p, |p| {815 let id_spanned = spanned(p, |p| Ok(Expr::Str(ident(p)?)))?;
830 let name = p.expect_ident()?;
831 Ok(Expr::Str(name))
832 })?;
833 parts.push(IndexPart {816 parts.push(IndexPart {
834 span: id_spanned.span,817 span: id_spanned.span,
835 value: id_spanned.value,818 value: id_spanned.value,
844827
845 if p.at(T![.]) {828 if p.at(T![.]) {
846 p.eat(T![.])?;829 p.eat(T![.])?;
847 let id_spanned = spanned(p, |p| {830 let id_spanned = spanned(p, |p| Ok(Expr::Str(ident(p)?)))?;
848 let name = p.expect_ident()?;
849 Ok(Expr::Str(name))
850 })?;
851 parts.push(IndexPart {831 parts.push(IndexPart {
852 span: id_spanned.span,832 span: id_spanned.span,
853 value: id_spanned.value,833 value: id_spanned.value,