1use serde_json::Value;
8
9use super::super::feature::{class_expression, feature_expression_fields, operation_form};
10use super::super::{
11 ByteClassItem, CharClassItem, FeatureExpr, FeatureForm, FieldType, FieldValue, Grammar,
12 GrammarDeclarations, GrammarExpr, GrammarFormat, GrammarImportError, GrammarMacro, GrammarRule,
13 GrammarScanner, Operation, OperationCategory, PrecedenceEntry, RuleAttributes, RuleKind,
14 UnicodeClassItem,
15};
16
17enum Json {
19 Null,
20 Bool(bool),
21 Int(i64),
22 Str(String),
23 Array(Vec<Self>),
24 Object(Vec<(&'static str, Self)>),
25}
26
27impl Json {
28 fn str(value: &str) -> Self {
29 Self::Str(value.to_owned())
30 }
31
32 fn strings(values: &[String]) -> Self {
33 Self::Array(values.iter().map(|value| Self::str(value)).collect())
34 }
35
36 fn render(&self, indent: usize, out: &mut String) {
37 match self {
38 Self::Null => out.push_str("null"),
39 Self::Bool(value) => out.push_str(if *value { "true" } else { "false" }),
40 Self::Int(value) => out.push_str(&value.to_string()),
41 Self::Str(value) => {
42 out.push_str(&serde_json::to_string(value).unwrap_or_default());
43 }
44 Self::Array(items) if items.is_empty() => out.push_str("[]"),
45 Self::Object(entries) if entries.is_empty() => out.push_str("{}"),
46 Self::Array(items) => {
47 out.push('[');
48 for (index, item) in items.iter().enumerate() {
49 out.push_str(if index == 0 { "\n" } else { ",\n" });
50 push_indent(indent + 1, out);
51 item.render(indent + 1, out);
52 }
53 out.push('\n');
54 push_indent(indent, out);
55 out.push(']');
56 }
57 Self::Object(entries) => {
58 out.push('{');
59 for (index, (key, value)) in entries.iter().enumerate() {
60 out.push_str(if index == 0 { "\n" } else { ",\n" });
61 push_indent(indent + 1, out);
62 out.push('"');
63 out.push_str(key);
64 out.push_str("\": ");
65 value.render(indent + 1, out);
66 }
67 out.push('\n');
68 push_indent(indent, out);
69 out.push('}');
70 }
71 }
72 }
73}
74
75fn push_indent(indent: usize, out: &mut String) {
76 for _ in 0..indent {
77 out.push_str(" ");
78 }
79}
80
81fn int(value: usize) -> Json {
82 Json::Int(i64::try_from(value).unwrap_or(i64::MAX))
83}
84
85fn char_json(value: char) -> Json {
86 Json::Str(value.to_string())
87}
88
89fn unary(kind: &'static str, item: &GrammarExpr) -> Json {
90 Json::Object(vec![
91 ("kind", Json::str(kind)),
92 ("item", expression_json(item)),
93 ])
94}
95
96fn class_json(kind: &'static str, negated: bool, items: Vec<Json>) -> Json {
97 Json::Object(vec![
98 ("kind", Json::str(kind)),
99 ("negated", Json::Bool(negated)),
100 ("items", Json::Array(items)),
101 ])
102}
103
104fn char_item_json(item: &CharClassItem) -> Json {
105 match item {
106 CharClassItem::Char(value) => Json::Object(vec![
107 ("kind", Json::str("char")),
108 ("value", char_json(*value)),
109 ]),
110 CharClassItem::Range(start, end) => Json::Object(vec![
111 ("kind", Json::str("range")),
112 ("start", char_json(*start)),
113 ("end", char_json(*end)),
114 ]),
115 }
116}
117
118fn expressions_json(items: &[GrammarExpr]) -> Json {
119 Json::Array(items.iter().map(expression_json).collect())
120}
121
122fn expression_json(expr: &GrammarExpr) -> Json {
123 let kind = |kind: &str| ("kind", Json::str(kind));
124 match expr {
125 GrammarExpr::Empty => Json::Object(vec![kind("empty")]),
126 GrammarExpr::AnyChar => Json::Object(vec![kind("any")]),
127 GrammarExpr::Terminal(value) => {
128 Json::Object(vec![kind("literal"), ("value", Json::str(value))])
129 }
130 GrammarExpr::TerminalInsensitive(value) => Json::Object(vec![
131 kind("literalInsensitive"),
132 ("value", Json::str(value)),
133 ]),
134 GrammarExpr::CharRange(start, end) => Json::Object(vec![
135 kind("charRange"),
136 ("start", char_json(*start)),
137 ("end", char_json(*end)),
138 ]),
139 GrammarExpr::CharClass { negated, items } => class_json(
140 "charClass",
141 *negated,
142 items.iter().map(char_item_json).collect(),
143 ),
144 GrammarExpr::NonTerminal(name) => {
145 Json::Object(vec![kind("ref"), ("name", Json::str(name))])
146 }
147 GrammarExpr::Choice {
148 ordered,
149 alternatives,
150 } => Json::Object(vec![
151 kind("choice"),
152 ("items", expressions_json(alternatives)),
153 ("ordered", Json::Bool(*ordered)),
154 ]),
155 GrammarExpr::Sequence(items) => {
156 Json::Object(vec![kind("seq"), ("items", expressions_json(items))])
157 }
158 GrammarExpr::Optional(item) => unary("optional", item),
159 GrammarExpr::ZeroOrMore(item) => unary("repeat0", item),
160 GrammarExpr::OneOrMore(item) => unary("repeat1", item),
161 GrammarExpr::And(item) => unary("and", item),
162 GrammarExpr::Not(item) => unary("not", item),
163 GrammarExpr::Repeat { expr, min, max } => Json::Object(vec![
164 kind("repeat"),
165 ("item", expression_json(expr)),
166 ("min", int(*min)),
167 ("max", max.map_or(Json::Null, int)),
168 ]),
169 GrammarExpr::Capture { label, expr } => Json::Object(vec![
170 kind("capture"),
171 ("label", label.as_deref().map_or(Json::Null, Json::str)),
172 ("item", expression_json(expr)),
173 ]),
174 GrammarExpr::Feature(feature) => feature_json(feature),
175 }
176}
177
178fn feature_json(feature: &FeatureExpr) -> Json {
179 match feature {
180 FeatureExpr::UnicodeClass { negated, items } => class_json(
181 "charClass",
182 *negated,
183 items
184 .iter()
185 .map(|item| match item {
186 UnicodeClassItem::Char(value) => char_item_json(&CharClassItem::Char(*value)),
187 UnicodeClassItem::Range(start, end) => {
188 char_item_json(&CharClassItem::Range(*start, *end))
189 }
190 UnicodeClassItem::Category(value) => Json::Object(vec![
191 ("kind", Json::str("category")),
192 ("value", Json::str(value)),
193 ]),
194 UnicodeClassItem::Script(value) => Json::Object(vec![
195 ("kind", Json::str("script")),
196 ("value", Json::str(value)),
197 ]),
198 })
199 .collect(),
200 ),
201 FeatureExpr::ByteClass { negated, items } => class_json(
202 "byteClass",
203 *negated,
204 items
205 .iter()
206 .map(|item| match item {
207 ByteClassItem::Byte(value) => Json::Object(vec![
208 ("kind", Json::str("byte")),
209 ("value", Json::Int(i64::from(*value))),
210 ]),
211 ByteClassItem::Range(start, end) => Json::Object(vec![
212 ("kind", Json::str("byteRange")),
213 ("start", Json::Int(i64::from(*start))),
214 ("end", Json::Int(i64::from(*end))),
215 ]),
216 })
217 .collect(),
218 ),
219 FeatureExpr::Call { name, arguments } => Json::Object(vec![
220 ("kind", Json::str("ref")),
221 ("name", Json::str(name)),
222 ("arguments", expressions_json(arguments)),
223 ]),
224 FeatureExpr::Form(form) => form_json("kind", form),
225 }
226}
227
228fn form_json(head_key: &'static str, form: &FeatureForm) -> Json {
230 let mut entries = vec![(head_key, Json::str(&form.head))];
231 for ((key, _), value) in form.spec().iter().zip(&form.fields) {
232 let value = match value {
233 FieldValue::Word(text) | FieldValue::Name(text) | FieldValue::Text(text) => {
234 Json::str(text)
235 }
236 FieldValue::Integer(value) => Json::Int(*value),
237 FieldValue::Expression(expr) => expression_json(expr),
238 FieldValue::Expressions(items) => expressions_json(items),
239 FieldValue::Operation(operation) => operation_json(operation),
240 FieldValue::Operations(items) | FieldValue::Block(Some(items)) => {
241 operations_json(items)
242 }
243 FieldValue::Block(None) => continue,
244 };
245 entries.push((key, value));
246 }
247 Json::Object(entries)
248}
249
250fn operation_json(operation: &Operation) -> Json {
251 form_json("operation", operation)
252}
253
254fn operations_json(operations: &[Operation]) -> Json {
255 Json::Array(operations.iter().map(operation_json).collect())
256}
257
258fn rule_json(rule: &GrammarRule) -> Json {
259 let mut entries = vec![
260 ("name", Json::str(&rule.name)),
261 ("kind", Json::str(rule.kind.as_str())),
262 ("expression", expression_json(&rule.expr)),
263 ];
264 let attributes = &rule.attributes;
265 if !attributes.parameters.is_empty() {
266 entries.push(("parameters", Json::strings(&attributes.parameters)));
267 }
268 if let Some(channel) = &attributes.channel {
269 entries.push(("channel", Json::str(channel)));
270 }
271 if let Some(modes) = &attributes.modes {
272 entries.push(("modes", Json::strings(modes)));
273 }
274 if let Some(action) = &attributes.action {
275 entries.push(("action", operations_json(action)));
276 }
277 Json::Object(entries)
278}
279
280fn declarations_json(declarations: &GrammarDeclarations) -> Json {
281 let mut entries = Vec::new();
282 if let Some(matching) = &declarations.matching {
283 entries.push(("matching", Json::str(matching)));
284 }
285 if let Some(settling) = &declarations.settling {
286 entries.push(("settling", Json::strings(settling)));
287 }
288 if !declarations.imports.is_empty() {
289 entries.push(("imports", Json::strings(&declarations.imports)));
290 }
291 if !declarations.modes.is_empty() {
292 entries.push(("modes", Json::strings(&declarations.modes)));
293 }
294 if !declarations.extras.is_empty() {
295 entries.push(("extras", expressions_json(&declarations.extras)));
296 }
297 if !declarations.conflicts.is_empty() {
298 let groups = declarations
299 .conflicts
300 .iter()
301 .map(|group| Json::strings(group));
302 entries.push(("conflicts", Json::Array(groups.collect())));
303 }
304 if !declarations.precedences.is_empty() {
305 let orders = declarations.precedences.iter().map(|order| {
306 Json::Array(
307 order
308 .iter()
309 .map(|entry| {
310 Json::Object(vec![
311 ("kind", Json::str(entry.kind())),
312 ("value", Json::str(entry.value())),
313 ])
314 })
315 .collect(),
316 )
317 });
318 entries.push(("precedences", Json::Array(orders.collect())));
319 }
320 if !declarations.macros.is_empty() {
321 let macros = declarations.macros.iter().map(|declared| {
322 Json::Object(vec![
323 ("name", Json::str(&declared.name)),
324 ("parameters", Json::strings(&declared.parameters)),
325 ("expression", expression_json(&declared.expression)),
326 ])
327 });
328 entries.push(("macros", Json::Array(macros.collect())));
329 }
330 if !declarations.scanners.is_empty() {
331 let scanners = declarations.scanners.iter().map(|scanner| {
332 Json::Object(vec![
333 ("name", Json::str(&scanner.name)),
334 ("tokens", Json::strings(&scanner.tokens)),
335 ("operations", operations_json(&scanner.operations)),
336 ])
337 });
338 entries.push(("scanners", Json::Array(scanners.collect())));
339 }
340 Json::Object(entries)
341}
342
343#[must_use]
346pub fn serialize_grammar(grammar: &Grammar) -> String {
347 let mut entries = vec![
348 ("schemaVersion", Json::Int(1)),
349 ("start", grammar.start().map_or(Json::Null, Json::str)),
350 (
351 "sourceFormat",
352 grammar
353 .source_format()
354 .map_or(Json::Null, |format| Json::str(format.as_str())),
355 ),
356 (
357 "rules",
358 Json::Array(grammar.rules().iter().map(rule_json).collect()),
359 ),
360 ];
361 if !grammar.declarations().is_empty() {
362 entries.push(("declarations", declarations_json(grammar.declarations())));
363 }
364 let mut out = String::new();
365 Json::Object(entries).render(0, &mut out);
366 out.push('\n');
367 out
368}
369
370fn json_error(detail: impl Into<String>) -> GrammarImportError {
371 GrammarImportError::Parse {
372 format: GrammarFormat::MetaLanguage,
373 message: detail.into(),
374 }
375}
376
377fn invalid(what: &str) -> GrammarImportError {
378 json_error(format!("invalid serialized grammar {what}"))
379}
380
381fn field<'a>(value: &'a Value, key: &str, what: &str) -> Result<&'a Value, GrammarImportError> {
382 value.get(key).ok_or_else(|| invalid(what))
383}
384
385fn string(value: &Value, key: &str, what: &str) -> Result<String, GrammarImportError> {
386 field(value, key, what)?
387 .as_str()
388 .map(str::to_owned)
389 .ok_or_else(|| invalid(what))
390}
391
392fn optional_string(
393 value: &Value,
394 key: &str,
395 what: &str,
396) -> Result<Option<String>, GrammarImportError> {
397 match value.get(key) {
398 None | Some(Value::Null) => Ok(None),
399 Some(Value::String(text)) => Ok(Some(text.clone())),
400 Some(_) => Err(invalid(what)),
401 }
402}
403
404fn strings(value: Option<&Value>, what: &str) -> Result<Vec<String>, GrammarImportError> {
405 match value {
406 None | Some(Value::Null) => Ok(Vec::new()),
407 Some(Value::Array(items)) => items
408 .iter()
409 .map(|item| {
410 item.as_str()
411 .map(str::to_owned)
412 .ok_or_else(|| invalid(what))
413 })
414 .collect(),
415 Some(_) => Err(invalid(what)),
416 }
417}
418
419fn array<'a>(value: &'a Value, key: &str, what: &str) -> Result<&'a [Value], GrammarImportError> {
420 field(value, key, what)?
421 .as_array()
422 .map(Vec::as_slice)
423 .ok_or_else(|| invalid(what))
424}
425
426fn character(value: &Value, key: &str) -> Result<char, GrammarImportError> {
427 let text = string(value, key, "expression")?;
428 let mut chars = text.chars();
429 match (chars.next(), chars.next()) {
430 (Some(value), None) => Ok(value),
431 _ => Err(invalid("expression")),
432 }
433}
434
435fn integer(value: &Value, key: &str, what: &str) -> Result<i64, GrammarImportError> {
436 field(value, key, what)?
437 .as_i64()
438 .ok_or_else(|| invalid(what))
439}
440
441fn count(value: &Value, key: &str) -> Result<usize, GrammarImportError> {
442 usize::try_from(integer(value, key, "expression")?).map_err(|_| invalid("expression"))
443}
444
445fn byte(value: &Value, key: &str) -> Result<u8, GrammarImportError> {
446 u8::try_from(integer(value, key, "expression")?).map_err(|_| invalid("expression"))
447}
448
449fn read_expressions(value: &Value, key: &str) -> Result<Vec<GrammarExpr>, GrammarImportError> {
450 array(value, key, "expression")?
451 .iter()
452 .map(read_expression)
453 .collect()
454}
455
456fn read_item(value: &Value) -> Result<Box<GrammarExpr>, GrammarImportError> {
457 Ok(Box::new(read_expression(field(
458 value,
459 "item",
460 "expression",
461 )?)?))
462}
463
464fn read_expression(value: &Value) -> Result<GrammarExpr, GrammarImportError> {
465 let kind = string(value, "kind", "expression")?;
466 Ok(match kind.as_str() {
467 "empty" => GrammarExpr::Empty,
468 "any" => GrammarExpr::AnyChar,
469 "literal" => GrammarExpr::Terminal(string(value, "value", "expression")?),
470 "literalInsensitive" => {
471 GrammarExpr::TerminalInsensitive(string(value, "value", "expression")?)
472 }
473 "charRange" => GrammarExpr::CharRange(character(value, "start")?, character(value, "end")?),
474 "charClass" => {
475 let negated = value
476 .get("negated")
477 .and_then(Value::as_bool)
478 .unwrap_or(false);
479 let items = array(value, "items", "expression")?
480 .iter()
481 .map(read_class_item)
482 .collect::<Result<_, _>>()?;
483 class_expression(negated, items)
484 }
485 "byteClass" => {
486 let negated = value
487 .get("negated")
488 .and_then(Value::as_bool)
489 .unwrap_or(false);
490 let items = array(value, "items", "expression")?
491 .iter()
492 .map(|item| match string(item, "kind", "expression")?.as_str() {
493 "byte" => Ok(ByteClassItem::Byte(byte(item, "value")?)),
494 "byteRange" => Ok(ByteClassItem::Range(
495 byte(item, "start")?,
496 byte(item, "end")?,
497 )),
498 _ => Err(invalid("expression")),
499 })
500 .collect::<Result<_, _>>()?;
501 GrammarExpr::feature(FeatureExpr::ByteClass { negated, items })
502 }
503 "ref" => {
504 let name = string(value, "name", "expression")?;
505 match value.get("arguments") {
506 None | Some(Value::Null) => GrammarExpr::NonTerminal(name),
507 Some(_) => GrammarExpr::feature(FeatureExpr::Call {
508 name,
509 arguments: read_expressions(value, "arguments")?,
510 }),
511 }
512 }
513 "choice" => GrammarExpr::Choice {
514 ordered: value
515 .get("ordered")
516 .and_then(Value::as_bool)
517 .unwrap_or(false),
518 alternatives: read_expressions(value, "items")?,
519 },
520 "seq" => GrammarExpr::Sequence(read_expressions(value, "items")?),
521 "optional" => GrammarExpr::Optional(read_item(value)?),
522 "repeat0" => GrammarExpr::ZeroOrMore(read_item(value)?),
523 "repeat1" => GrammarExpr::OneOrMore(read_item(value)?),
524 "and" => GrammarExpr::And(read_item(value)?),
525 "not" => GrammarExpr::Not(read_item(value)?),
526 "repeat" => GrammarExpr::Repeat {
527 expr: read_item(value)?,
528 min: count(value, "min")?,
529 max: match value.get("max") {
530 None | Some(Value::Null) => None,
531 Some(_) => Some(count(value, "max")?),
532 },
533 },
534 "capture" => GrammarExpr::Capture {
535 label: optional_string(value, "label", "expression")?,
536 expr: read_item(value)?,
537 },
538 other => {
539 let fields = feature_expression_fields(other).ok_or_else(|| {
540 json_error(format!(
541 "unsupported serialized grammar expression kind {other}"
542 ))
543 })?;
544 GrammarExpr::feature(FeatureExpr::Form(read_form(other, fields, value)?))
545 }
546 })
547}
548
549fn read_class_item(item: &Value) -> Result<UnicodeClassItem, GrammarImportError> {
550 Ok(match string(item, "kind", "expression")?.as_str() {
551 "char" => UnicodeClassItem::Char(character(item, "value")?),
552 "range" => UnicodeClassItem::Range(character(item, "start")?, character(item, "end")?),
553 "category" => UnicodeClassItem::Category(string(item, "value", "expression")?),
554 "script" => UnicodeClassItem::Script(string(item, "value", "expression")?),
555 _ => return Err(invalid("expression")),
556 })
557}
558
559fn read_form(
560 head: &str,
561 fields: &[(&'static str, FieldType)],
562 value: &Value,
563) -> Result<FeatureForm, GrammarImportError> {
564 let mut values = Vec::with_capacity(fields.len());
565 for (key, kind) in fields {
566 let what = "expression";
567 values.push(match kind {
568 FieldType::Choice(words) => {
569 let word = string(value, key, what)?;
570 if !words.contains(&word.as_str()) {
571 return Err(invalid(what));
572 }
573 FieldValue::Word(word)
574 }
575 FieldType::Integer => FieldValue::Integer(integer(value, key, what)?),
576 FieldType::Name => FieldValue::Name(string(value, key, what)?),
577 FieldType::Text => FieldValue::Text(string(value, key, what)?),
578 FieldType::Expression => {
579 FieldValue::Expression(read_expression(field(value, key, what)?)?)
580 }
581 FieldType::Expressions => FieldValue::Expressions(read_expressions(value, key)?),
582 FieldType::Condition => FieldValue::Operation(read_operation(
583 field(value, key, what)?,
584 OperationCategory::Condition,
585 )?),
586 FieldType::Value => FieldValue::Operation(read_operation(
587 field(value, key, what)?,
588 OperationCategory::Value,
589 )?),
590 FieldType::Conditions => FieldValue::Operations(read_operations(
591 array(value, key, what)?,
592 OperationCategory::Condition,
593 )?),
594 FieldType::Block(_, optional) => match value.get(*key) {
595 None | Some(Value::Null) if *optional => FieldValue::Block(None),
596 _ => FieldValue::Block(Some(read_operations(
597 array(value, key, what)?,
598 OperationCategory::Statement,
599 )?)),
600 },
601 });
602 }
603 Ok(FeatureForm::new(head, values))
604}
605
606fn read_operation(
607 value: &Value,
608 category: OperationCategory,
609) -> Result<Operation, GrammarImportError> {
610 let head = string(value, "operation", "operation")?;
611 let (found, fields) = operation_form(&head)
612 .ok_or_else(|| json_error(format!("unsupported serialized grammar operation {head}")))?;
613 if found != category {
614 return Err(json_error(format!(
615 "serialized grammar operation {head} is not a {}",
616 category.as_str()
617 )));
618 }
619 read_form(&head, fields, value)
620}
621
622fn read_operations(
623 values: &[Value],
624 category: OperationCategory,
625) -> Result<Vec<Operation>, GrammarImportError> {
626 values
627 .iter()
628 .map(|value| read_operation(value, category))
629 .collect()
630}
631
632fn read_declarations(value: &Value) -> Result<GrammarDeclarations, GrammarImportError> {
633 let what = "declarations";
634 let mut declarations = GrammarDeclarations {
635 matching: optional_string(value, "matching", what)?,
636 settling: value
637 .get("settling")
638 .map(|steps| strings(Some(steps), what))
639 .transpose()?,
640 imports: strings(value.get("imports"), what)?,
641 modes: strings(value.get("modes"), what)?,
642 ..GrammarDeclarations::default()
643 };
644 if let Some(Value::Array(extras)) = value.get("extras") {
645 declarations.extras = extras
646 .iter()
647 .map(read_expression)
648 .collect::<Result<_, _>>()?;
649 }
650 if let Some(Value::Array(groups)) = value.get("conflicts") {
651 declarations.conflicts = groups
652 .iter()
653 .map(|group| strings(Some(group), what))
654 .collect::<Result<_, _>>()?;
655 }
656 if let Some(Value::Array(orders)) = value.get("precedences") {
657 for order in orders {
658 let Value::Array(entries) = order else {
659 return Err(invalid(what));
660 };
661 let mut read = Vec::new();
662 for entry in entries {
663 let kind = string(entry, "kind", what)?;
664 let value = string(entry, "value", what)?;
665 let Some(entry) = PrecedenceEntry::from_kind(&kind, value) else {
666 return Err(invalid(what));
667 };
668 read.push(entry);
669 }
670 declarations.precedences.push(read);
671 }
672 }
673 if let Some(Value::Array(macros)) = value.get("macros") {
674 for declared in macros {
675 declarations.macros.push(GrammarMacro {
676 name: string(declared, "name", what)?,
677 parameters: strings(declared.get("parameters"), what)?,
678 expression: read_expression(field(declared, "expression", what)?)?,
679 });
680 }
681 }
682 if let Some(Value::Array(scanners)) = value.get("scanners") {
683 for scanner in scanners {
684 declarations.scanners.push(GrammarScanner {
685 name: string(scanner, "name", what)?,
686 tokens: strings(scanner.get("tokens"), what)?,
687 operations: read_operations(
688 array(scanner, "operations", what)?,
689 OperationCategory::Statement,
690 )?,
691 });
692 }
693 }
694 Ok(declarations)
695}
696
697fn read_rule(value: &Value) -> Result<GrammarRule, GrammarImportError> {
698 let name = value.get("name").and_then(Value::as_str);
699 let expression = value
700 .get("expression")
701 .filter(|expr| expr.get("kind").is_some());
702 let (Some(name), Some(expression)) = (name, expression) else {
703 return Err(invalid("rule"));
704 };
705 let kind = match value.get("kind") {
706 None | Some(Value::Null) => RuleKind::Normal,
707 Some(kind) => kind
708 .as_str()
709 .and_then(RuleKind::from_tag)
710 .ok_or_else(|| invalid("rule"))?,
711 };
712 let attributes = RuleAttributes {
713 parameters: strings(value.get("parameters"), "rule")?,
714 channel: optional_string(value, "channel", "rule")?,
715 modes: match value.get("modes") {
716 None | Some(Value::Null) => None,
717 modes => Some(strings(modes, "rule")?),
718 },
719 action: match value.get("action") {
720 None | Some(Value::Null) => None,
721 Some(_) => Some(read_operations(
722 array(value, "action", "rule")?,
723 OperationCategory::Statement,
724 )?),
725 },
726 };
727 Ok(GrammarRule::new(name, read_expression(expression)?)
728 .with_kind(kind)
729 .with_attributes(attributes))
730}
731
732pub fn deserialize_grammar(source: &str) -> Result<Grammar, GrammarImportError> {
741 let value: Value = serde_json::from_str(source)
742 .map_err(|error| json_error(format!("invalid serialized grammar JSON: {error}")))?;
743 let (Some(1), Some(Value::Array(rules))) = (
744 value.get("schemaVersion").and_then(Value::as_i64),
745 value.get("rules"),
746 ) else {
747 return Err(invalid("document"));
748 };
749 let mut grammar = Grammar::new();
750 for rule in rules {
751 let rule = read_rule(rule)?;
752 if grammar.rule(&rule.name).is_some() {
753 return Err(json_error(format!(
754 "duplicate serialized grammar rule {}",
755 rule.name
756 )));
757 }
758 grammar.add_rule(rule);
759 }
760 if let Some(start) = value.get("start").and_then(Value::as_str) {
761 grammar.set_start(start);
762 }
763 if let Some(format) = value.get("sourceFormat").and_then(Value::as_str) {
764 let format = GrammarFormat::from_tag(format)
765 .ok_or_else(|| json_error(format!("unknown serialized grammar format {format}")))?;
766 grammar.set_source_format(format);
767 }
768 if let Some(declarations) = value.get("declarations").filter(|value| !value.is_null()) {
769 grammar.set_declarations(read_declarations(declarations)?);
770 }
771 if grammar.start_rule().is_none() {
772 return Err(json_error("serialized grammar has no start rule"));
773 }
774 Ok(grammar)
775}