1use crate::{Language, ParserState, source::Source, tree::GreenNode};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Associativity {
6 Left,
8 Right,
10 None,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct OperatorInfo {
17 pub precedence: u8,
19 pub associativity: Associativity,
21}
22
23impl OperatorInfo {
24 pub fn left(precedence: u8) -> Self {
26 Self { precedence, associativity: Associativity::Left }
27 }
28
29 pub fn right(precedence: u8) -> Self {
31 Self { precedence, associativity: Associativity::Right }
32 }
33
34 pub fn none(precedence: u8) -> Self {
36 Self { precedence, associativity: Associativity::None }
37 }
38}
39
40pub trait Pratt<L: Language> {
45 fn primary<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, L, S>) -> &'a GreenNode<'a, L>;
47
48 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, L, S>) -> &'a GreenNode<'a, L> {
52 self.primary(state)
53 }
54
55 fn infix<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, L, S>, left: &'a GreenNode<'a, L>, min_precedence: u8) -> Option<&'a GreenNode<'a, L>>;
60}
61
62#[inline(always)]
64pub fn binary<'a, L, S, F>(state: &mut ParserState<'a, L, S>, left: &'a GreenNode<'a, L>, op_kind: L::TokenType, op_precedence: u8, assoc: Associativity, result_kind: L::ElementType, mut parse_expr: F) -> &'a GreenNode<'a, L>
65where
66 L: Language,
67 S: Source + ?Sized,
68 F: FnMut(&mut ParserState<'a, L, S>, u8) -> &'a GreenNode<'a, L>,
69 L::ElementType: From<L::TokenType>,
70{
71 let cp = state.checkpoint();
72 state.push_child(left);
73 state.expect(op_kind).ok();
74
75 let next_prec = match assoc {
76 Associativity::Left => op_precedence + 1,
77 Associativity::Right => op_precedence,
78 Associativity::None => op_precedence + 1,
79 };
80
81 let right = parse_expr(state, next_prec);
82 state.push_child(right);
83 state.finish_at(cp, result_kind)
84}
85
86#[inline(always)]
88pub fn unary<'a, L, S, F>(state: &mut ParserState<'a, L, S>, op_kind: L::TokenType, op_precedence: u8, result_kind: L::ElementType, mut parse_expr: F) -> &'a GreenNode<'a, L>
89where
90 L: Language,
91 S: Source + ?Sized,
92 F: FnMut(&mut ParserState<'a, L, S>, u8) -> &'a GreenNode<'a, L>,
93 L::ElementType: From<L::TokenType>,
94{
95 let cp = state.checkpoint();
96 state.expect(op_kind).ok();
97 let right = parse_expr(state, op_precedence);
98 state.push_child(right);
99 state.finish_at(cp, result_kind)
100}
101
102#[inline(always)]
104pub fn postfix<'a, L, S>(state: &mut ParserState<'a, L, S>, left: &'a GreenNode<'a, L>, op_kind: L::TokenType, result_kind: L::ElementType) -> &'a GreenNode<'a, L>
105where
106 L: Language,
107 S: Source + ?Sized,
108 L::ElementType: From<L::TokenType>,
109{
110 let cp = state.checkpoint();
111 state.push_child(left);
112 state.expect(op_kind).ok();
113 state.finish_at(cp, result_kind)
114}
115
116pub struct PrattParser<L: Language, T: Pratt<L>> {
118 spec: T,
119 _marker: core::marker::PhantomData<L>,
120}
121
122impl<L: Language, T: Pratt<L>> PrattParser<L, T> {
123 pub const fn new(spec: T) -> Self {
125 Self { spec, _marker: core::marker::PhantomData }
126 }
127
128 pub fn parse_expr<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, L, S>, min_precedence: u8) -> &'a GreenNode<'a, L> {
130 Self::parse(state, min_precedence, &self.spec)
131 }
132
133 pub fn parse<'a, S: Source + ?Sized>(state: &mut ParserState<'a, L, S>, min_precedence: u8, spec: &T) -> &'a GreenNode<'a, L> {
135 let mut left = spec.prefix(state);
136
137 while let Some(node) = spec.infix(state, left, min_precedence) {
138 left = node;
139 }
140
141 left
142 }
143}