1use lang_util::position::LexerPosition;
4
5use crate::{ast, parser};
6
7use glsl_lang_lexer::{HasLexerError, LangLexer, Token};
8
9pub use glsl_lang_lexer::{ParseContext, ParseContextData, ParseOptions};
10
11mod builder;
12pub use builder::*;
13
14mod parsable;
15pub use parsable::Extractable;
16pub use parsable::Parsable;
17
18pub trait LangParser: Sized {
20 type Item;
22
23 fn new() -> Self;
25
26 fn parse<
28 L: HasLexerError + Iterator<Item = Result<(LexerPosition, Token, LexerPosition), L::Error>>,
29 >(
30 &self,
31 ctx: ParseContext,
32 input: &mut L,
33 ) -> Result<Self::Item, lalrpop_util::ParseError<LexerPosition, Token, L::Error>>;
34}
35
36pub trait HasParser: Sized {
38 type Parser: LangParser<Item = Self>;
40}
41
42#[allow(clippy::result_large_err)]
44pub trait Parse: HasParser {
45 fn parse<'i, L: LangLexer<'i>>(
47 source: L::Input,
48 ) -> Result<Self, ParseError<<L::Iter as HasLexerError>::Error>>;
49
50 fn parse_with_options<'i, L: LangLexer<'i>>(
52 source: L::Input,
53 opts: &ParseOptions,
54 ) -> ParseResult<L::Iter, <L::Iter as HasLexerError>::Error, Self>;
55
56 fn parse_with_context<'i, L: LangLexer<'i>>(
58 source: L::Input,
59 ctx: &ParseContext,
60 ) -> ParseResult<L::Iter, <L::Iter as HasLexerError>::Error, Self>;
61}
62
63impl<T: HasParser> Parse for T {
64 fn parse<'i, L: LangLexer<'i>>(
65 source: L::Input,
66 ) -> Result<Self, ParseError<<L::Iter as HasLexerError>::Error>> {
67 ParseBuilder::<L, Self>::new(source)
68 .parse()
69 .map(|(parsed, _names, _lexer)| parsed)
70 }
71
72 fn parse_with_options<'i, L: LangLexer<'i>>(
73 source: L::Input,
74 opts: &ParseOptions,
75 ) -> ParseResult<L::Iter, <L::Iter as HasLexerError>::Error, Self> {
76 ParseBuilder::<L, Self>::new(source).opts(opts).parse()
77 }
78
79 fn parse_with_context<'i, L: LangLexer<'i>>(
80 source: L::Input,
81 ctx: &ParseContext,
82 ) -> ParseResult<L::Iter, <L::Iter as HasLexerError>::Error, Self> {
83 ParseBuilder::<L, Self>::new(source).context(ctx).parse()
84 }
85}
86
87pub type ParseResult<L, E, T> = Result<(T, ParseContext, L), ParseError<E>>;
89
90pub type ParseError<E> = lang_util::error::ParseError<E>;
92
93#[cfg(not(feature = "lexer-full"))]
95pub type DefaultLexer<'i> = glsl_lang_lexer::min::str::Lexer<'i>;
96
97#[cfg(feature = "lexer-full")]
99pub type DefaultLexer<'i> = glsl_lang_lexer::full::str::Lexer<'i>;
100
101pub trait DefaultParse: Parse {
103 fn parse<'i>(
105 source: <DefaultLexer<'i> as LangLexer<'i>>::Input,
106 ) -> Result<Self, ParseError<<<DefaultLexer<'i> as LangLexer<'i>>::Iter as HasLexerError>::Error>>;
107
108 fn parse_with_options<'i>(
110 source: <DefaultLexer<'i> as LangLexer<'i>>::Input,
111 opts: &ParseOptions,
112 ) -> ParseResult<
113 <DefaultLexer<'i> as LangLexer<'i>>::Iter,
114 <<DefaultLexer<'i> as LangLexer<'i>>::Iter as HasLexerError>::Error,
115 Self,
116 >;
117
118 fn parse_with_context<'i>(
120 source: <DefaultLexer<'i> as LangLexer<'i>>::Input,
121 ctx: &ParseContext,
122 ) -> ParseResult<
123 <DefaultLexer<'i> as LangLexer<'i>>::Iter,
124 <<DefaultLexer<'i> as LangLexer<'i>>::Iter as HasLexerError>::Error,
125 Self,
126 >;
127}
128
129impl<T: Parse> DefaultParse for T {
130 fn parse<'i>(
131 source: <DefaultLexer<'i> as LangLexer<'i>>::Input,
132 ) -> Result<Self, ParseError<<<DefaultLexer<'i> as LangLexer<'i>>::Iter as HasLexerError>::Error>>
133 {
134 <T as Parse>::parse::<DefaultLexer<'i>>(source)
135 }
136
137 fn parse_with_options<'i>(
138 source: <DefaultLexer<'i> as LangLexer<'i>>::Input,
139 opts: &ParseOptions,
140 ) -> ParseResult<
141 <DefaultLexer<'i> as LangLexer<'i>>::Iter,
142 <<DefaultLexer<'i> as LangLexer<'i>>::Iter as HasLexerError>::Error,
143 Self,
144 > {
145 <T as Parse>::parse_with_options::<DefaultLexer<'i>>(source, opts)
146 }
147
148 fn parse_with_context<'i>(
149 source: <DefaultLexer<'i> as LangLexer<'i>>::Input,
150 ctx: &ParseContext,
151 ) -> ParseResult<
152 <DefaultLexer<'i> as LangLexer<'i>>::Iter,
153 <<DefaultLexer<'i> as LangLexer<'i>>::Iter as HasLexerError>::Error,
154 Self,
155 > {
156 <T as Parse>::parse_with_context::<DefaultLexer<'i>>(source, ctx)
157 }
158}
159
160macro_rules! impl_parse {
161 ($t:ty => $p:ty) => {
162 impl LangParser for $p {
163 type Item = $t;
164
165 fn new() -> Self {
166 <$p>::new()
167 }
168
169 fn parse<
170 L: HasLexerError
171 + Iterator<Item = Result<(LexerPosition, Token, LexerPosition), L::Error>>,
172 >(
173 &self,
174 ctx: ParseContext,
175 input: &mut L,
176 ) -> Result<Self::Item, lalrpop_util::ParseError<LexerPosition, Token, L::Error>> {
177 self.parse::<L, _, _>(&ctx, input)
178 }
179 }
180
181 impl HasParser for $t {
182 type Parser = $p;
183 }
184 };
185}
186
187#[cfg(feature = "parser-expr")]
188impl_parse!(ast::Expr => parser::ExprParser);
189#[cfg(feature = "parser-statement")]
190impl_parse!(ast::Statement => parser::StatementParser);
191impl_parse!(ast::TranslationUnit => parser::TranslationUnitParser);