1use crate::{ValkyrieLanguage, kind::ValkyrieSyntaxKind};
2use oak_core::{
3 GreenNode,
4 parser::{Associativity, ParserState, Pratt, binary, unary},
5 source::Source,
6};
7
8#[allow(dead_code)]
9type State<'a, S> = ParserState<'a, ValkyrieLanguage, S>;
10
11mod parse;
12
13#[derive(Clone)]
15pub struct ValkyrieParser<'config> {
16 config: &'config ValkyrieLanguage,
18}
19
20impl<'config> ValkyrieParser<'config> {}
21
22impl<'config> ValkyrieParser<'config> {
23 pub fn new(config: &'config ValkyrieLanguage) -> Self {
25 Self { config }
26 }
27}
28
29impl<'config> Pratt<ValkyrieLanguage> for ValkyrieParser<'config> {
30 fn primary<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, ValkyrieLanguage, S>) -> &'a GreenNode<'a, ValkyrieLanguage> {
31 let cp = state.checkpoint();
32 self.parse_primary(state).unwrap_or_else(|_| {
33 state.restore(cp);
34 state.bump();
35 state.finish_at(cp, ValkyrieSyntaxKind::Error)
36 })
37 }
38
39 fn infix<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, ValkyrieLanguage, S>, left: &'a GreenNode<'a, ValkyrieLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, ValkyrieLanguage>> {
40 self.skip_trivia(state);
41 let t = state.current()?;
42 let kind = t.kind;
43
44 let (prec, assoc, result_kind) = match kind {
45 ValkyrieSyntaxKind::Eq
47 | ValkyrieSyntaxKind::PlusEq
48 | ValkyrieSyntaxKind::MinusEq
49 | ValkyrieSyntaxKind::StarEq
50 | ValkyrieSyntaxKind::SlashEq
51 | ValkyrieSyntaxKind::PercentEq
52 | ValkyrieSyntaxKind::CaretEq
53 | ValkyrieSyntaxKind::AndEq
54 | ValkyrieSyntaxKind::OrEq
55 | ValkyrieSyntaxKind::ShlEq
56 | ValkyrieSyntaxKind::ShrEq => (10, Associativity::Right, ValkyrieSyntaxKind::BinaryExpression),
57
58 ValkyrieSyntaxKind::OrOr => (14, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
60 ValkyrieSyntaxKind::AndAnd => (15, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
61
62 ValkyrieSyntaxKind::Or => (20, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
64 ValkyrieSyntaxKind::Caret => (21, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
65 ValkyrieSyntaxKind::And => (22, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
66
67 ValkyrieSyntaxKind::EqEq | ValkyrieSyntaxKind::Ne => (25, Associativity::None, ValkyrieSyntaxKind::BinaryExpression),
69 ValkyrieSyntaxKind::Lt | ValkyrieSyntaxKind::Gt | ValkyrieSyntaxKind::Le | ValkyrieSyntaxKind::Ge => (30, Associativity::None, ValkyrieSyntaxKind::BinaryExpression),
70
71 ValkyrieSyntaxKind::Shl | ValkyrieSyntaxKind::Shr => (35, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
73
74 ValkyrieSyntaxKind::Plus | ValkyrieSyntaxKind::Minus => (40, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
76
77 ValkyrieSyntaxKind::Star | ValkyrieSyntaxKind::Slash | ValkyrieSyntaxKind::Percent => (50, Associativity::Left, ValkyrieSyntaxKind::BinaryExpression),
79
80 ValkyrieSyntaxKind::LeftParen => (70, Associativity::Left, ValkyrieSyntaxKind::CallExpression),
82 ValkyrieSyntaxKind::Dot => (70, Associativity::Left, ValkyrieSyntaxKind::FieldExpression),
83 ValkyrieSyntaxKind::LeftBracket => (70, Associativity::Left, ValkyrieSyntaxKind::IndexExpression),
84 ValkyrieSyntaxKind::LeftBrace => (70, Associativity::Left, ValkyrieSyntaxKind::ApplyBlock),
85
86 _ => return None,
87 };
88
89 if prec < min_precedence {
90 return None;
91 }
92
93 let cp = state.checkpoint();
94 let node = match kind {
95 ValkyrieSyntaxKind::LeftParen => {
96 let cp_inner = state.checkpoint();
97 state.push_child(left);
98 state.expect(ValkyrieSyntaxKind::LeftParen).ok();
99 while let Some(t) = state.current() {
100 if t.kind == ValkyrieSyntaxKind::RightParen {
101 break;
102 }
103 let arg = self.parse_expression_internal(state, 0);
104 state.push_child(arg);
105 if state.at(ValkyrieSyntaxKind::Comma) {
106 state.expect(ValkyrieSyntaxKind::Comma).ok();
107 }
108 }
109 state.expect(ValkyrieSyntaxKind::RightParen).ok();
110 state.finish_at(cp_inner, ValkyrieSyntaxKind::CallExpression)
111 }
112 ValkyrieSyntaxKind::LeftBracket => {
113 let cp_inner = state.checkpoint();
114 state.push_child(left);
115 state.expect(ValkyrieSyntaxKind::LeftBracket).ok();
116 let index = self.parse_expression_internal(state, 0);
117 state.push_child(index);
118 state.expect(ValkyrieSyntaxKind::RightBracket).ok();
119 state.finish_at(cp_inner, ValkyrieSyntaxKind::IndexExpression)
120 }
121 ValkyrieSyntaxKind::LeftBrace => {
122 let cp_inner = state.checkpoint();
123 state.push_child(left);
124 self.parse_block_expr_node(state).ok();
125 state.finish_at(cp_inner, ValkyrieSyntaxKind::ApplyBlock)
126 }
127 _ => binary(state, left, kind, prec, assoc, result_kind, |s, p| self.parse_expression_internal(s, p)),
128 };
129 Some(node)
130 }
131
132 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut ParserState<'a, ValkyrieLanguage, S>) -> &'a GreenNode<'a, ValkyrieLanguage> {
133 self.skip_trivia(state);
134 let t = match state.current() {
135 Some(t) => t,
136 None => return self.primary(state),
137 };
138
139 let kind = t.kind;
140 let (prec, result_kind) = match kind {
141 ValkyrieSyntaxKind::Not | ValkyrieSyntaxKind::Minus | ValkyrieSyntaxKind::Plus | ValkyrieSyntaxKind::Star | ValkyrieSyntaxKind::And => (60, ValkyrieSyntaxKind::UnaryExpression),
142 _ => return self.primary(state),
143 };
144
145 let cp = state.checkpoint();
146 unary(state, kind, prec, result_kind, |s, p| self.parse_expression_internal(s, p))
147 }
148}
149
150impl<'config> oak_core::parser::Parser<ValkyrieLanguage> for ValkyrieParser<'config> {
151 fn parse<'a, S: Source + ?Sized>(&self, source: &'a S, edits: &[oak_core::TextEdit], cache: &'a mut impl oak_core::parser::ParseCache<ValkyrieLanguage>) -> oak_core::ParseOutput<'a, ValkyrieLanguage> {
152 let lexer = crate::lexer::ValkyrieLexer::new(self.config);
153 oak_core::parser::parse_with_lexer(&lexer, source, edits, cache, |state| Ok(self.parse_root_internal(state)))
154 }
155}