1use crate::{Token, TokenId};
2use std::fmt;
3
4pub type Prec = u16;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum Fixity {
16 Nilfix,
17 Prefix,
18 Suffix,
19 Infix,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum Assoc {
34 Left,
35 Right,
36}
37
38#[derive(Debug, Clone)]
39pub(crate) struct Op<T: Token> {
40 pub(crate) token: T,
41 pub(crate) fixity: Fixity,
42 pub(crate) assoc: Assoc,
43 pub(crate) prec: Prec,
44 pub(crate) arity: usize,
46 pub(crate) left_prec: Option<Prec>,
47 pub(crate) right_prec: Option<Prec>,
48}
49
50impl<T: Token> Op<T> {
51 pub(crate) fn new(
52 token: T,
53 fixity: Fixity,
54 assoc: Assoc,
55 prec: Prec,
56 num_tokens: usize,
57 ) -> Op<T> {
58 assert_ne!(token, T::LEX_ERROR);
59 assert_ne!(token, T::BLANK);
60 assert_ne!(token, T::JUXTAPOSE);
61 Op::new_unchecked(token, fixity, assoc, prec, num_tokens)
62 }
63
64 pub(crate) fn new_atom(token: T, _token_id: TokenId) -> Op<T> {
65 Op::new_unchecked(token, Fixity::Nilfix, Assoc::Left, 0, 1)
66 }
67
68 pub(crate) fn new_error() -> Op<T> {
69 Op::new_unchecked(T::LEX_ERROR, Fixity::Nilfix, Assoc::Left, 0, 1)
70 }
71
72 pub(crate) fn new_blank() -> Op<T> {
73 Op::new_unchecked(T::BLANK, Fixity::Nilfix, Assoc::Left, 0, 1)
74 }
75
76 pub(crate) fn new_juxtapose(assoc: Assoc, prec: Prec) -> Op<T> {
77 Op::new_unchecked(T::JUXTAPOSE, Fixity::Infix, assoc, prec, 1)
78 }
79
80 fn new_unchecked(
81 token: T,
82 fixity: Fixity,
83 assoc: Assoc,
84 prec: Prec,
85 num_tokens: usize,
86 ) -> Op<T> {
87 use Assoc::{Left, Right};
88 use Fixity::{Infix, Nilfix, Prefix, Suffix};
89
90 let (left_prec, right_prec) = match (fixity, assoc) {
91 (Nilfix, _) => (None, None),
92 (Prefix, Left) => (None, Some(prec)),
93 (Prefix, Right) => (None, Some(prec + 1)),
94 (Suffix, Left) => (Some(prec + 1), None),
95 (Suffix, Right) => (Some(prec), None),
96 (Infix, Left) => (Some(prec + 1), Some(prec)),
97 (Infix, Right) => (Some(prec), Some(prec + 1)),
98 };
99 let arity = match fixity {
100 Nilfix => num_tokens - 1,
101 Prefix | Suffix => num_tokens,
102 Infix => num_tokens + 1,
103 };
104 Op {
105 token,
106 fixity,
107 assoc,
108 prec,
109 arity,
110 left_prec,
111 right_prec,
112 }
113 }
114}
115
116impl<T: Token> fmt::Display for Op<T> {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 write!(f, "{}", self.token)
119 }
120}