1use pretty::RcDoc;
4use winnow::{
5 LocatingSlice, ModalResult, Parser,
6 ascii::{float, multispace0},
7 combinator::{alt, delimited},
8};
9
10use crate::text::{HasParser, ToDoc};
11
12#[derive(Clone, Copy, Debug, PartialEq)]
14pub enum Phase {
15 Angle(f64),
17 MinusOne,
19 Imag,
21 MinusImag,
23}
24
25impl Phase {
26 pub fn from_angle(f: f64) -> Self {
29 if f == 0.5 {
30 Phase::Imag
31 } else if f == 1.0 {
32 Phase::MinusOne
33 } else if f == 1.5 {
34 Phase::MinusImag
35 } else {
36 Phase::Angle(f)
37 }
38 }
39
40 pub fn eval(&self) -> f64 {
43 match self {
44 Phase::Angle(a) => *a,
45 Phase::MinusOne => 1.0,
46 Phase::Imag => 0.5,
47 Phase::MinusImag => 1.5,
48 }
49 }
50}
51
52impl ToDoc for Phase {
53 fn to_doc(&self) -> RcDoc<'_> {
54 match self {
55 Phase::Angle(a) => RcDoc::text(format!("ph({a}pi)")),
56 Phase::MinusOne => RcDoc::text("-1"),
57 Phase::Imag => RcDoc::text("i"),
58 Phase::MinusImag => RcDoc::text("-i"),
59 }
60 }
61}
62
63impl HasParser for Phase {
64 fn parser(input: &mut LocatingSlice<&str>) -> ModalResult<Self> {
65 alt((
66 "-1".value(Phase::MinusOne),
67 "i".value(Phase::Imag),
68 "-i".value(Phase::MinusImag),
69 delimited(
70 ("ph(", multispace0),
71 float,
72 (multispace0, "pi", multispace0, ")"),
73 )
74 .map(Phase::Angle),
75 ))
76 .parse_next(input)
77 }
78}