1use itertools::Itertools;
2use pest::iterators::Pair;
3
4use crate::{
5 galloc::AllocForStr, utils::TryRetain, value::{ConstValue, Type}
6};
7
8use super::{problem::{new_custom_error_span, Error, Rule}, config::Config};
9
10#[derive(PartialEq, Eq, Hash, Clone)]
11pub enum ProdRule {
21 Var(String, Config),
22 Const(ConstValue, Config),
23 Op1(String, String, Config),
24 Op2(String, String, String, Config),
25 Op3(String, String, String, String, Config),
26}
27
28impl ConstValue {
29 pub fn parse(pair: Pair<'_, Rule>) -> Result<Self, Error> {
32 let [value]: [_; 1] = pair.into_inner().collect_vec().try_into().unwrap();
33 match value.as_rule() {
34 Rule::numeral => {
35 if value.as_str().contains(".") {
36 let f = value.as_str().parse::<f64>().map_err(|_| new_custom_error_span("Can not parse float".into(), value.as_span()))?;
37 Ok(Self::Float(f.into()))
38 } else {
39 let f = value.as_str().parse::<i64>().map_err(|_| new_custom_error_span("Can not parse int".into(), value.as_span()))?;
40 Ok(Self::Int(f))
41 }
42 }
43 Rule::hexnum => {
44 let s = value.as_str().trim_start_matches("#x");
45 let f = u64::from_str_radix(s, 16)
46 .map_err(|_| new_custom_error_span("Can not parse hex".into(), value.as_span()))?;
47 Ok(Self::BitVector(s.len() * 4, f))
48 }
49 Rule::binnum => {
50 let s = value.as_str().trim_start_matches("#b");
51 let f = u64::from_str_radix(s, 2)
52 .map_err(|_| new_custom_error_span("Can not parse binary".into(), value.as_span()))?;
53 Ok(Self::BitVector(s.len(), f))
54 }
55 Rule::strlit => Ok(Self::Str(value.as_str()[1..(value.as_str().len() - 1)].galloc_str())),
56 Rule::boollit => match value.as_str() {
57 "true" => Ok(Self::Bool(true)),
58 "false" => Ok(Self::Bool(false)),
59 "null" => Ok(Self::Null),
60 _ => Err(new_custom_error_span("Can not parse the Boolean".into(), value.as_span())),
61 },
62 _ => panic!("should not reach here"),
63 }
64 }
65}
66
67impl ProdRule {
68 pub fn const_value(&self) -> Option<&ConstValue> {
71 match self {
72 ProdRule::Const(i, _) => Some(i),
73 _ => None,
74 }
75 }
76 pub fn parse(pair: Pair<'_, Rule>) -> Result<Self, Error> {
79 let mut vec = pair.into_inner().collect_vec();
80 let mut config = Config::new();
81 vec.try_retain(|x| {
82 if x.as_rule() == Rule::config {
83 config.merge(Config::parse(x.clone())?);
84 Ok(false)
85 } else { Ok(true) }
86 })?;
87 if vec.len() == 1 {
88 let [value]: [_; 1] = vec.try_into().unwrap();
89 match value.as_rule() {
90 Rule::value => Ok(Self::Const(ConstValue::parse(value)?, config)),
91 Rule::symbol => Ok(Self::Var(value.as_str().into(), config)),
92 _ => panic!("should not reach here"),
93 }
94 } else {
95 match vec.as_slice() {
96 [op, a1] => Ok(Self::Op1(op.as_str().into(), a1.as_str().into(), config)),
97 [op, a1, a2] => Ok(Self::Op2(op.as_str().into(), a1.as_str().into(), a2.as_str().into(), config)),
98 [op, a1, a2, a3] => Ok(Self::Op3(op.as_str().into(), a1.as_str().into(), a2.as_str().into(), a3.as_str().into(), config)),
99 _ => panic!("should not reach here"),
100 }
101 }
102 }
103}
104
105impl std::fmt::Debug for ProdRule {
106
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 match self {
109 Self::Var(arg0, _) => write!(f, "{}", arg0),
110 Self::Const(arg0, _) => write!(f, "{}", arg0),
111 Self::Op1(arg0, arg1, c) => write!(f, "({} {}{:?})", arg0, arg1, c),
112 Self::Op2(arg0, arg1, arg2, c) => write!(f, "({} {} {}{:?})", arg0, arg1, arg2, c),
113 Self::Op3(arg0, arg1, arg2, arg3, c) => write!(f, "({} {} {} {}{:?})", arg0, arg1, arg2, arg3, c),
114 }
115 }
116}