git.delta.rocks / jrsonnet / refs/commits / 7eb771ff363d

difftreelog

feat allow both parsers at the same time

uwkkuzmuYaroslav Bolyukin2026-03-23parent: #b6f9e83.patch.diff
in: master

4 files changed

modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
18explaining-traces = ["annotate-snippets", "hi-doc"]18explaining-traces = ["annotate-snippets", "hi-doc"]
19# Allows library authors to throw custom errors19# Allows library authors to throw custom errors
20anyhow-error = ["anyhow"]20anyhow-error = ["anyhow"]
21# Use hand-written recursive descent parser instead of PEG parser21# Use hand-written recursive descent parser
22ir-parser = ["dep:jrsonnet-ir-parser"]22ir-parser = ["dep:jrsonnet-ir-parser"]
23# Use PEG parser
24peg-parser = ["dep:jrsonnet-peg-parser"]
2325
24# Allows to preserve field order in objects26# Allows to preserve field order in objects
25exp-preserve-order = []27exp-preserve-order = []
26# Implements field destructuring28# Implements field destructuring
27exp-destruct = ["jrsonnet-peg-parser/exp-destruct"]29exp-destruct = ["jrsonnet-peg-parser?/exp-destruct", "jrsonnet-ir-parser?/exp-destruct"]
28# Iteration over objects yields [key, value] elements30# Iteration over objects yields [key, value] elements
29exp-object-iteration = []31exp-object-iteration = []
30# Bigint type32# Bigint type
31exp-bigint = ["num-bigint", "jrsonnet-types/exp-bigint"]33exp-bigint = ["num-bigint", "jrsonnet-types/exp-bigint"]
32# obj?.field, obj?.['field']34# obj?.field, obj?.['field']
33exp-null-coaelse = ["jrsonnet-peg-parser/exp-null-coaelse", "jrsonnet-ir-parser?/exp-null-coaelse"]35exp-null-coaelse = ["jrsonnet-peg-parser?/exp-null-coaelse", "jrsonnet-ir-parser?/exp-null-coaelse"]
3436
35[dependencies]37[dependencies]
36jrsonnet-interner.workspace = true38jrsonnet-interner.workspace = true
37jrsonnet-ir.workspace = true39jrsonnet-ir.workspace = true
38jrsonnet-peg-parser.workspace = true40jrsonnet-peg-parser = { workspace = true, optional = true }
39jrsonnet-ir-parser = { workspace = true, optional = true }41jrsonnet-ir-parser = { workspace = true, optional = true }
40jrsonnet-types.workspace = true42jrsonnet-types.workspace = true
41jrsonnet-macros.workspace = true43jrsonnet-macros.workspace = true
modifiedcrates/jrsonnet-evaluator/src/async_import.rsdiffbeforeafterboth
7 FieldMember, FieldName, ForSpecData, IfElse, IfSpecData, ImportKind, ObjBody, Slice, SliceDesc,7 FieldMember, FieldName, ForSpecData, IfElse, IfSpecData, ImportKind, ObjBody, Slice, SliceDesc,
8 Source, SourcePath, Spanned,8 Source, SourcePath, Spanned,
9};9};
10#[cfg(feature = "ir-parser")]
11use jrsonnet_ir_parser::ParserSettings;
12#[cfg(not(feature = "ir-parser"))]
13use jrsonnet_peg_parser::ParserSettings;
14use rustc_hash::FxHashMap;10use rustc_hash::FxHashMap;
1511
16use crate::{AsPathLike, FileData, ImportResolver, ResolvePathOwned, State};12use crate::{AsPathLike, FileData, ImportResolver, ResolvePathOwned, State};
326 };322 };
327 let source = Source::new(path.clone(), code.clone());323 let source = Source::new(path.clone(), code.clone());
328 // If failed - then skip import324 // If failed - then skip import
329 file.parsed = crate::parse_jsonnet(&code, &ParserSettings { source })325 file.parsed = crate::parse_jsonnet(&code, source)
330 .map(Rc::new)326 .map(Rc::new)
331 .ok();327 .ok();
332 if let Some(parsed) = &file.parsed {328 if let Some(parsed) = &file.parsed {
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
14 ObjValue, ResolvePathOwned,14 ObjValue, ResolvePathOwned,
15};15};
16
17#[derive(Debug, Clone)]
18pub struct SyntaxErrorLocation {
19 pub offset: usize,
20}
21
22#[derive(Debug, Clone)]
23pub struct SyntaxError {
24 pub message: String,
25 pub location: SyntaxErrorLocation,
26}
27impl fmt::Display for SyntaxError {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(f, "{}", self.message)
30 }
31}
1632
17pub(crate) fn format_found(list: &[IStr], what: &str) -> String {33pub(crate) fn format_found(list: &[IStr], what: &str) -> String {
18 if list.is_empty() {34 if list.is_empty() {
154 ImportNotSupported(SourcePath, ResolvePathOwned),170 ImportNotSupported(SourcePath, ResolvePathOwned),
155 #[error("can't import from virtual file")]171 #[error("can't import from virtual file")]
156 CantImportFromVirtualFile,172 CantImportFromVirtualFile,
157 #[cfg(not(feature = "ir-parser"))]
158 #[error(
159 "syntax error: {}",
160 // Peg has no fancier way to handle critical parsing errors https://github.com/kevinmehall/rust-peg/issues/225
161 {.error.expected.tokens().find(|t| t.starts_with("!!!")).map_or_else(|| {
162 format!(
163 "expected {}, got {:?}",
164 .error.expected,
165 .path.code().chars().nth(error.location.offset)
166 .map_or_else(|| "EOF".into(), |c| c.to_string())
167 )
168 }, |v| v[3..].into())}
169 )]
170 ImportSyntaxError {
171 path: Source,
172 #[trace(skip)]
173 error: Box<jrsonnet_peg_parser::ParseError>,
174 },
175
176 #[cfg(feature = "ir-parser")]
177 #[error("syntax error: {error}")]173 #[error("syntax error: {error}")]
178 ImportSyntaxError {174 ImportSyntaxError {
179 path: Source,175 path: Source,
180 #[trace(skip)]176 #[trace(skip)]
181 error: Box<jrsonnet_ir_parser::ParseError>,177 error: Box<SyntaxError>,
182 },178 },
183179
184 #[error("runtime error: {}", format_empty_str(.0))]180 #[error("runtime error: {}", format_empty_str(.0))]
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
47#[doc(hidden)]47#[doc(hidden)]
48pub use jrsonnet_macros;48pub use jrsonnet_macros;
49
49#[cfg(feature = "ir-parser")]50#[cfg(not(any(feature = "ir-parser", feature = "peg-parser")))]
50use jrsonnet_ir_parser::ParserSettings;51compile_error!("at least one of `ir-parser` or `peg-parser` features must be enabled");
51#[cfg(not(feature = "ir-parser"))]52
52use jrsonnet_peg_parser::ParserSettings;53pub use error::{SyntaxError, SyntaxErrorLocation};
53pub use obj::*;54pub use obj::*;
54pub use rustc_hash;55pub use rustc_hash;
55use rustc_hash::FxHashMap;56use rustc_hash::FxHashMap;
5960
60use crate::gc::WithCapacityExt as _;61use crate::gc::WithCapacityExt as _;
62
63pub(crate) fn parse_jsonnet(code: &str, source: Source) -> Result<Expr, SyntaxError> {
64 #[cfg(all(feature = "ir-parser", feature = "peg-parser"))]
65 {
66 if std::env::var_os("JRSONNET_LEGACY_PARSER").is_some() {
67 return parse_peg(code, source);
68 }
69 return parse_ir(code, source);
70 }
71 #[cfg(all(feature = "ir-parser", not(feature = "peg-parser")))]
72 {
73 return parse_ir(code, source);
74 }
75 #[cfg(all(feature = "peg-parser", not(feature = "ir-parser")))]
76 {
77 return parse_peg(code, source);
78 }
79}
6180
62#[cfg(feature = "ir-parser")]81#[cfg(feature = "ir-parser")]
63pub(crate) fn parse_jsonnet(82fn parse_ir(code: &str, source: Source) -> Result<Expr, SyntaxError> {
64 code: &str,
65 settings: &ParserSettings,
66) -> Result<Expr, jrsonnet_ir_parser::ParseError> {
67 jrsonnet_ir_parser::parse(code, settings)83 jrsonnet_ir_parser::parse(code, &jrsonnet_ir_parser::ParserSettings { source }).map_err(
84 |e| SyntaxError {
85 message: e.message,
86 location: SyntaxErrorLocation {
87 offset: e.location.offset,
88 },
89 },
90 )
68}91}
6992
70#[cfg(not(feature = "ir-parser"))]93#[cfg(feature = "peg-parser")]
71pub(crate) fn parse_jsonnet(94fn parse_peg(code: &str, source: Source) -> Result<Expr, SyntaxError> {
72 code: &str,
73 settings: &ParserSettings,
74) -> Result<Expr, jrsonnet_peg_parser::ParseError> {
75 jrsonnet_peg_parser::parse(code, settings)95 jrsonnet_peg_parser::parse(code, &jrsonnet_peg_parser::ParserSettings { source }).map_err(
96 |e| {
97 let message = e
98 .expected
99 .tokens()
100 .find(|t| t.starts_with("!!!"))
101 .map_or_else(
102 || {
103 format!(
104 "expected {}, got {:?}",
105 e.expected,
106 code.chars()
107 .nth(e.location.offset)
108 .map_or_else(|| "EOF".into(), |c: char| c.to_string())
109 )
110 },
111 |v| v[3..].into(),
112 );
113 SyntaxError {
114 message,
115 location: SyntaxErrorLocation {
116 offset: e.location.offset,
117 },
118 }
119 },
120 )
76}121}
77122
78cc_dyn!(123cc_dyn!(
366 file.parsed = Some(411 file.parsed = Some(
367 parse_jsonnet(412 parse_jsonnet(&code, file_name.clone())
368 &code,
369 &ParserSettings {
370 source: file_name.clone(),
371 },
372 )
373 .map(Rc::new)413 .map(Rc::new)
374 .map_err(|e| ImportSyntaxError {414 .map_err(|e| ImportSyntaxError {
482 let source = Source::new_virtual(name.into(), code.clone());522 let source = Source::new_virtual(name.into(), code.clone());
483 let parsed = parse_jsonnet(523 let parsed = parse_jsonnet(&code, source.clone())
484 &code,
485 &ParserSettings {
486 source: source.clone(),
487 },
488 )
489 .map_err(|e| ImportSyntaxError {524 .map_err(|e| ImportSyntaxError {
490 path: source.clone(),525 path: source.clone(),
503 let source = Source::new_virtual(name.into(), code.clone());538 let source = Source::new_virtual(name.into(), code.clone());
504 let parsed = parse_jsonnet(539 let parsed = parse_jsonnet(&code, source.clone())
505 &code,
506 &ParserSettings {
507 source: source.clone(),
508 },
509 )
510 .map_err(|e| ImportSyntaxError {540 .map_err(|e| ImportSyntaxError {
511 path: source.clone(),541 path: source.clone(),