1#![allow(missing_docs)]
7
8#[derive(pest_derive::Parser)]
10#[grammar = "grammar.pest"]
11pub struct Parser;
12
13use crate::parse::{self, ParseResult};
14use crate::src_ref::{SrcRef, SrcReferrer};
15
16#[derive(Debug, Clone)]
17pub struct Pair<'i>(pest::iterators::Pair<'i, Rule>, u64);
18
19impl<'i> Pair<'i> {
20 pub fn new(pest_pair: pest::iterators::Pair<'i, Rule>, source_hash: u64) -> Self {
21 Self(pest_pair, source_hash)
22 }
23
24 pub fn source_hash(&self) -> u64 {
25 self.1
26 }
27
28 pub fn set_source_hash(&mut self, hash: u64) {
29 self.1 = hash
30 }
31
32 pub fn pest_pair(&self) -> &pest::iterators::Pair<'i, Rule> {
33 &self.0
34 }
35
36 pub fn inner(&'i self) -> impl Iterator<Item = Self> {
37 self.0.clone().into_inner().map(|p| Self(p, self.1))
38 }
39
40 pub fn find<T: Parse>(&'i self, rule: Rule) -> Option<T> {
42 match self
43 .inner()
44 .find(|pair| pair.as_rule() == rule)
45 .map(T::parse)
46 {
47 Some(Err(_)) | None => None,
48 Some(Ok(x)) => Some(x),
49 }
50 }
51}
52
53impl SrcReferrer for Pair<'_> {
54 fn src_ref(&self) -> SrcRef {
55 let pair = &self.0;
56 let (line, col) = pair.line_col();
57 SrcRef::new(
58 pair.as_span().start()..pair.as_span().end(),
59 line,
60 col,
61 self.1,
62 )
63 }
64}
65
66impl<'i> std::ops::Deref for Pair<'i> {
67 type Target = pest::iterators::Pair<'i, Rule>;
68
69 fn deref(&self) -> &Self::Target {
70 &self.0
71 }
72}
73
74pub type Pairs<'i> = pest::iterators::Pairs<'i, Rule>;
75
76pub trait Parse: Sized {
77 fn parse(pair: Pair) -> ParseResult<Self>;
78}
79
80impl Parser {
81 pub fn vec<'a, T>(pair: Pair<'a>, f: impl Fn(Pair<'a>) -> ParseResult<T>) -> ParseResult<Vec<T>>
90 where
91 T: Clone,
92 {
93 pair.0.into_inner().map(|p| f(Pair(p, pair.1))).collect()
94 }
95
96 pub fn parse_rule<T>(rule: Rule, input: &str, src_hash: u64) -> ParseResult<T>
98 where
99 T: Parse + Clone,
100 {
101 use pest::Parser as _;
102
103 match Parser::parse(rule, input.trim()).map_err(Box::new)?.next() {
104 Some(pair) => Ok(T::parse(Pair(pair, src_hash))?),
105 None => Err(parse::ParseError::RuleError(Box::new(rule))),
106 }
107 }
108
109 pub fn ensure_rule(pair: &Pair, expected: Rule) {
110 let rule = pair.as_rule();
111 assert_eq!(rule, expected, "Unexpected rule: {rule:?}");
112 }
113
114 pub fn ensure_rules(pair: &Pair, rules: &[Rule]) {
115 for rule in rules {
116 if *rule == pair.as_rule() {
117 return;
118 }
119 }
120
121 panic!(
122 "Unexpected rules: expected {rules:?}, got {rule:?}",
123 rule = pair.as_rule()
124 );
125 }
126}