1pub mod builder;
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8pub struct TokenType(pub u32);
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
12pub struct AstNodeType(pub u32);
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub enum GrammarItem {
17 Token(TokenType),
19 AstNode(AstNodeType),
21}
22
23impl From<TokenType> for GrammarItem {
24 fn from(token: TokenType) -> Self {
25 Self::Token(token)
26 }
27}
28
29impl From<AstNodeType> for GrammarItem {
30 fn from(node: AstNodeType) -> Self {
31 Self::AstNode(node)
32 }
33}
34
35#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
37pub struct TokenId(pub usize);
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
41pub struct AstNodeId(pub usize);
42
43#[derive(Debug, Copy, Clone, PartialEq, Eq)]
45pub enum Index {
46 Token(TokenId),
48 AstNode(AstNodeId),
50}
51
52impl Index {
53 #[must_use]
59 pub fn as_token_id(&self) -> TokenId {
60 let &Self::Token(id) = self else {
61 panic!("Expected `Token`, found `AstNode`")
62 };
63 id
64 }
65
66 #[must_use]
72 pub fn as_ast_node_id(&self) -> AstNodeId {
73 let &Self::AstNode(id) = self else {
74 panic!("Expected `AstNode`, found `Token`")
75 };
76 id
77 }
78}
79
80#[derive(Debug, Clone)]
82pub enum ReductionResult<A> {
83 NewNode(A),
85 Forward(AstNodeId),
87}
88
89pub trait HasTokenType {
91 fn token_type(&self) -> TokenType;
93}
94
95pub type ReductionFn<T, A> = fn(&[Index], &[T], &[A]) -> ReductionResult<A>;
97
98#[derive(Debug, Clone)]
100pub struct GrammarRule<T, A> {
101 pub result: AstNodeType,
103 pub components: Vec<GrammarItem>,
105 pub reduction: ReductionFn<T, A>,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
113pub struct GrammarRuleId(pub usize);
114
115#[derive(Clone)]
117pub struct Grammar<T, A> {
118 pub root_ast_node: AstNodeType,
120 pub rules: Vec<GrammarRule<T, A>>,
122}
123
124impl<T, A> Grammar<T, A> {
125 #[must_use]
127 pub fn new(root_ast_node: AstNodeType) -> Self {
128 Self {
129 rules: vec![GrammarRule {
130 result: root_ast_node,
131 components: vec![root_ast_node.into()],
132 reduction: |indices, _, _| ReductionResult::Forward(indices[0].as_ast_node_id()),
133 }],
134 root_ast_node,
135 }
136 }
137
138 pub fn add_rule(
140 &mut self,
141 result: AstNodeType,
142 components: &[GrammarItem],
143 reduction: ReductionFn<T, A>,
144 ) {
145 self.rules.push(GrammarRule {
146 result,
147 components: components.to_vec(),
148 reduction,
149 });
150 }
151
152 #[must_use]
154 pub fn get_rule(&self, id: GrammarRuleId) -> &GrammarRule<T, A> {
155 &self.rules[id.0]
156 }
157}