Skip to main content

sim_codec_algol/pratt/parser/
core.rs

1//! Algol compatibility wrapper over the shared Pratt parser substrate.
2
3use crate::parse::tokenize_algol_spanned_with_budget;
4use sim_codec::{DecodeBudget, DecodeLimits};
5use sim_codec_pratt::{PrattCodecParser, PrattTokenSource, SpannedPrattToken};
6use sim_kernel::{CodecId, LocatedExprTree, PrattTable, Result};
7
8/// Token source that adapts the Algol lexer to the shared Pratt driver.
9#[derive(Clone, Copy, Debug, Default)]
10pub struct AlgolTokenSource;
11
12impl PrattTokenSource for AlgolTokenSource {
13    fn tokenize_pratt(
14        &self,
15        _codec: CodecId,
16        source: &str,
17        budget: &mut DecodeBudget,
18    ) -> Result<Vec<SpannedPrattToken>> {
19        tokenize_algol_spanned_with_budget(source, budget).map(|tokens| {
20            tokens
21                .into_iter()
22                .map(|token| {
23                    SpannedPrattToken::with_leading_trivia(
24                        token.token,
25                        token.start,
26                        token.end,
27                        token.leading_trivia,
28                    )
29                })
30                .collect()
31        })
32    }
33}
34
35/// Precedence-climbing parser for the Algol surface.
36///
37/// This wrapper preserves the public Algol parser API while delegating the
38/// language-neutral driver work to [`PrattCodecParser`].
39pub struct PrattParser {
40    inner: PrattCodecParser<AlgolTokenSource>,
41}
42
43impl PrattParser {
44    /// Creates a parser driven by the given operator table. Use
45    /// [`crate::default_pratt_table`] for the standard arithmetic operators.
46    pub fn new(operators: PrattTable) -> Self {
47        Self {
48            inner: PrattCodecParser::new(operators, AlgolTokenSource).with_surface_name("algol"),
49        }
50    }
51
52    /// Returns the parser's operator table.
53    pub fn operators(&self) -> &PrattTable {
54        self.inner.operators()
55    }
56
57    /// Parses `source` into a located expression tree under a default decode
58    /// budget. `source_id` names the input for origin tracking.
59    pub fn parse_text_tree(
60        &self,
61        codec: CodecId,
62        source_id: impl Into<String>,
63        source: &str,
64    ) -> Result<LocatedExprTree> {
65        let mut budget = DecodeBudget::new(DecodeLimits::default());
66        self.parse_text_tree_with_budget(codec, source_id, source, &mut budget)
67    }
68
69    /// Parses `source` into a located expression tree under an explicit
70    /// `budget`, erroring if any tokens remain after a complete expression.
71    pub fn parse_text_tree_with_budget(
72        &self,
73        codec: CodecId,
74        source_id: impl Into<String>,
75        source: &str,
76        budget: &mut DecodeBudget,
77    ) -> Result<LocatedExprTree> {
78        self.inner.parse_tree_with_source_and_budget(
79            codec,
80            sim_kernel::SourceId(source_id.into()),
81            source,
82            budget,
83        )
84    }
85}