leap_lang/parser/
valuetypeparser.rs1use super::itemposition::ItemPosition;
2use super::parsetree::ParseTree;
3use super::proptypesimple::PropTypeSimple;
4use super::token::Token;
5use super::tokenstream::TokenStream;
6use super::treevariant::TreeVariant;
7use crate::leaptypes::{Name, SimpleType};
8
9#[derive(Debug, Clone)]
23pub enum ValueType {
24 Simple(SimpleType),
25 List(Box<ValueType>),
26 LeapType { name: Name, args: Vec<ValueType> },
27}
28
29impl From<PropTypeSimple> for ValueType {
30 fn from(item: PropTypeSimple) -> Self {
31 let mut item = item;
32 match item.name.as_str() {
33 "str" => Self::Simple(SimpleType::String),
34 "int" => Self::Simple(SimpleType::Integer),
35 "float" => Self::Simple(SimpleType::Float),
36 "bool" => Self::Simple(SimpleType::Boolean),
37 "list" => Self::List(Box::new(Self::from(item.args.remove(0)))),
38 name => {
39 let name = Name::new(name.to_owned(), item.position).unwrap();
40 let args = item.args.into_iter().map(Self::from).collect();
41 Self::LeapType { name, args }
42 }
43 }
44 }
45}
46
47impl ValueType {
48 pub fn args(&self) -> Vec<&ValueType> {
49 match self {
50 ValueType::Simple(_) => vec![],
51 ValueType::List(t) => vec![&t],
52 ValueType::LeapType { args, .. } => args.iter().collect(),
53 }
54 }
55}
56
57pub struct ValueTypeParser {
58 stream: TokenStream,
59}
60
61impl ValueTypeParser {
62 pub fn parse(data: &str) -> Result<ValueType, ItemPosition<String>> {
63 let stream = TokenStream::new(&data);
64 let mut parser = ValueTypeParser { stream };
65 let tree = parser.parse_ptype()?;
66 let value_type = Self::tree_to_prop_type_simple(&tree);
67 Ok(ValueType::from(value_type))
68 }
69
70 fn parse_ptype(&mut self) -> Result<ParseTree, ItemPosition<String>> {
71 let mut tree = ParseTree::new(TreeVariant::PType, self.stream.get().0);
72 tree.nodes.push(self.parse_name()?);
73 if self.stream.get().1 == Token::BracketLeft {
74 tree.nodes.push(self.parse_pt_args_block()?);
75 }
76 Ok(tree)
77 }
78
79 fn parse_pt_args_block(&mut self) -> Result<ParseTree, ItemPosition<String>> {
80 let mut tree = ParseTree::new(TreeVariant::PTArgsBlock, self.stream.get().0);
81 if self.stream.get().1 == Token::BracketLeft {
82 self.stream.next();
83 tree.nodes.push(self.parse_pt_args()?);
84 if self.stream.get().1 == Token::BracketRight {
85 self.stream.next();
86 } else {
87 return Err(self.stream.get().replace("Expecting `]`".to_owned()));
88 }
89 } else {
90 return Err(self.stream.get().replace("Expecting `[`".to_owned()));
91 }
92 Ok(tree)
93 }
94
95 fn parse_pt_args(&mut self) -> Result<ParseTree, ItemPosition<String>> {
96 let mut tree = ParseTree::new(TreeVariant::PTArgs, self.stream.get().0);
97 tree.nodes.push(self.parse_ptype()?);
98 if let Token::Word(_) = self.stream.get().1 {
99 tree.nodes.push(self.parse_pt_args()?);
100 }
101 Ok(tree)
102 }
103
104 fn parse_name(&mut self) -> Result<ParseTree, ItemPosition<String>> {
105 match self.stream.consume() {
106 ItemPosition(p, Token::Word(w)) => Ok(ParseTree {
107 variant: TreeVariant::Name(w.clone()),
108 position: *p,
109 nodes: vec![],
110 }),
111 p => Err(p.replace("Expecting name".to_owned())),
112 }
113 }
114
115 fn tree_to_prop_type_simple(tree: &ParseTree) -> PropTypeSimple {
116 let name_node = &tree.nodes[0];
118 let name = if let TreeVariant::Name(w) = &name_node.variant {
119 w.clone()
120 } else {
121 panic!("Incorrect parse tree");
122 };
123 let args = if let Some(t) = tree.nodes.get(1) {
124 let t = &t.nodes[0];
126 Self::tree_to_ptargs(t)
128 } else {
129 vec![]
130 };
131 PropTypeSimple {
132 name,
133 args,
134 position: tree.position,
135 }
136 }
137
138 fn tree_to_ptargs(tree: &ParseTree) -> Vec<PropTypeSimple> {
139 let mut args = vec![Self::tree_to_prop_type_simple(&tree.nodes[0])];
141 if let Some(t) = tree.nodes.get(1) {
142 args.append(&mut Self::tree_to_ptargs(t));
144 }
145 args
146 }
147}
148
149#[cfg(test)]
150mod tests {
151
152 use super::*;
153
154 #[test]
155 fn test_simple_type() {
156 let vt = ValueTypeParser::parse("int").unwrap();
157 assert!(matches!(vt, ValueType::Simple(SimpleType::Integer)));
158 }
159
160 #[test]
161 fn test_complex_type() {
162 let vt = ValueTypeParser::parse("some-class[int aaa[str]]").unwrap();
163 assert!(matches!(vt, ValueType::LeapType { .. }));
164 if let ValueType::LeapType { name, args } = vt {
165 assert_eq!(name.get(), "some-class");
166 assert_eq!(args.len(), 2);
167 }
168 }
169}