ligen_python_parser/
literal.rs1use rustpython_parser::ast::{Constant, ExprConstant, Expr};
2use ligen::ir::Literal;
3use ligen::parser::{Parser, ParserConfig};
4use crate::prelude::*;
5
6#[derive(Default)]
7pub struct LiteralParser {}
8
9impl ligen::parser::universal::literal::LiteralParser for LiteralParser {}
10
11impl Parser<String> for LiteralParser {
12 type Output = Literal;
13 fn parse(&self, input: String, config: &ParserConfig) -> Result<Self::Output> {
14 self.parse(input.as_str(), config)
15 }
16}
17
18impl Parser<&str> for LiteralParser {
19 type Output = Literal;
20 fn parse(&self, input: &str, config: &ParserConfig) -> Result<Self::Output> {
21 if let Ok(integer) = input.parse::<i64>() {
22 Ok(Literal::Integer(integer))
23 } else {
24 ExprConstant::parse(input, "<embedded>")
25 .map_err(|e| Error::Message(format!("Failed to parse literal from ExprConstant: {:?}", e)))
26 .and_then(|constant| self.parse(&constant, config))
27 }
28 }
29}
30
31impl Parser<&Constant> for LiteralParser {
32 type Output = Literal;
33 fn parse(&self, input: &Constant, _config: &ParserConfig) -> Result<Self::Output> {
34 match input {
35 Constant::Bool(bool) => Ok(Literal::Boolean(*bool)),
36 Constant::Float(float) => Ok(Literal::Float(*float)),
37 Constant::Str(string) => Ok(Literal::String(string.clone())),
38 Constant::Int(big_int) => Ok(
39 Literal::Integer(
40 big_int
41 .try_into()
42 .map_err(|_| Error::Message("Failed to convert BigInt to usize".into()))?
43 )
44 ),
45 Constant::None => Ok(Literal::None),
46 Constant::Tuple(tuple) => {
47 let mut result = Vec::new();
48 for element in tuple {
49 result.push(self.parse(element, _config)?);
50 }
51 Ok(Literal::Tuple(result))
52 },
53 _ => Err(Error::Message(format!("Failed to parse literal from constant: {:?}", input)))
54 }
55 }
56}
57
58impl Parser<&ExprConstant> for LiteralParser {
59 type Output = Literal;
60 fn parse(&self, input: &ExprConstant, config: &ParserConfig) -> Result<Self::Output> {
61 self.parse(&input.value, config)
62 }
63}
64
65impl Parser<&Expr> for LiteralParser {
66 type Output = Literal;
67 fn parse(&self, input: &Expr, config: &ParserConfig) -> Result<Self::Output> {
68 match input {
69 Expr::Constant(constant) => self.parse(constant, config),
70 Expr::List(list) => {
71 let mut result = Vec::new();
72 for element in &list.elts {
73 result.push(self.parse(element, config)?);
74 }
75 Ok(Literal::Vector(result))
76 },
77 _ => Ok(Literal::Unknown("Unimplemented".into()))
78 }
79 }
80}
81
82#[cfg(test)]
83mod test {
84 use crate::literal::LiteralParser;
85 use crate::prelude::*;
86 use ligen::ir::literal::mock;
87 use ligen::parser::assert::*;
88
89 #[test]
90 fn literal_string() -> Result<()> {
91 assert_eq(LiteralParser::default(), mock::literal_string(), "\"string\"")
92 }
93
94 #[test]
95 fn literal_bool() -> Result<()> {
96 assert_eq(LiteralParser::default(), mock::literal_bool(), "False")
97 }
98
99 #[test]
100 fn literal_integer() -> Result<()> {
101 assert_eq(LiteralParser::default(), mock::literal_integer(), "-2")
102 }
103
104 #[test]
105 fn literal_float() -> Result<()> {
106 assert_eq(LiteralParser::default(), mock::literal_float(), "3.5")
107 }
108}