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