microcad_lang/parse/
format_string.rs1use crate::{parse::*, parser::*, syntax::*};
5use microcad_syntax::ast;
6
7impl FromAst for FormatExpression {
8 type AstNode = ast::StringExpression;
9
10 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
11 Ok(FormatExpression::new(
12 node.specification
13 .is_some()
14 .then(|| FormatSpec::from_ast(&node.specification, context))
15 .transpose()?,
16 Expression::from_ast(&node.expression, context)?,
17 context.src_ref(&node.span),
18 ))
19 }
20}
21
22impl FromAst for FormatSpec {
23 type AstNode = ast::StringFormatSpecification;
24
25 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
26 fn transpose_ref<T: Clone, E: Clone>(opt: &Option<Result<T, E>>) -> Result<Option<&T>, E> {
27 match opt.as_ref() {
28 None => Ok(None),
29 Some(Err(e)) => Err(e.clone()),
30 Some(Ok(t)) => Ok(Some(t)),
31 }
32 }
33 Ok(FormatSpec {
34 width: transpose_ref(&node.width)
35 .map_err(|(e, span)| {
36 ParseError::ParseIntError(Refer::new(e, context.src_ref(&span)))
37 })?
38 .copied(),
39 precision: transpose_ref(&node.precision)
40 .map_err(|(e, span)| {
41 ParseError::ParseIntError(Refer::new(e, context.src_ref(&span)))
42 })?
43 .copied(),
44 src_ref: context.src_ref(&node.span),
45 })
46 }
47}
48
49impl FromAst for FormatString {
50 type AstNode = ast::FormatString;
51
52 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
53 let parts = node
54 .parts
55 .iter()
56 .map(|part| FormatStringInner::from_ast(part, context))
57 .collect::<Result<Vec<_>, _>>()?;
58 Ok(FormatString(Refer::new(parts, context.src_ref(&node.span))))
59 }
60}
61
62impl FromAst for FormatStringInner {
63 type AstNode = ast::StringPart;
64
65 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
66 Ok(match node {
67 ast::StringPart::Char(c) => {
68 FormatStringInner::String(Refer::new(c.character.into(), context.src_ref(&c.span)))
69 }
70 ast::StringPart::Content(s) => {
71 FormatStringInner::String(Refer::new(s.content.clone(), context.src_ref(&s.span)))
72 }
73 ast::StringPart::Expression(e) => {
74 FormatStringInner::FormatExpression(FormatExpression::from_ast(e, context)?)
75 }
76 })
77 }
78}