linkrs_query/parser/parsing/
parser.rs1use std::sync::Arc;
2
3use crate::parser::ast::stmt::{Ast, Stmt};
4use crate::parser::core::error::{ParseError, ParseErrorKind};
5use crate::parser::parsing::expr_parser::parse_expression_with_context;
6use crate::parser::parsing::parse_context::{ParseContext, RecoveryScope};
7use crate::parser::parsing::stmt_parser::StmtParser;
8use crate::parser::TokenKind;
9use linkrs_core::types::expr::contextual::ContextualExpression;
10use linkrs_core::types::expr::expression_context::ExpressionAnalysisContext;
11
12#[derive(Debug, Clone)]
14pub struct ParserResult {
15 pub ast: Arc<Ast>,
17}
18
19pub struct Parser<'a> {
20 ctx: ParseContext<'a>,
21 expr_context: Arc<ExpressionAnalysisContext>,
22}
23
24impl<'a> Parser<'a> {
25 pub fn new(input: &'a str) -> Self {
26 let expr_context = Arc::new(ExpressionAnalysisContext::new());
27 let mut ctx = ParseContext::new(input);
28 ctx.set_expression_context(expr_context.clone());
29
30 Self { ctx, expr_context }
31 }
32
33 pub fn with_type_alias_manager(
37 mut self,
38 manager: Arc<linkrs_core::metadata::TypeAliasManager>,
39 ) -> Self {
40 self.ctx.set_type_alias_manager(manager);
41 self
42 }
43
44 pub fn from_string(input: String) -> Self {
45 let expr_context = Arc::new(ExpressionAnalysisContext::new());
46 let mut ctx = ParseContext::from_string(input);
47 ctx.set_expression_context(expr_context.clone());
48
49 Self { ctx, expr_context }
50 }
51
52 pub fn set_compat_mode(&mut self, enabled: bool) {
53 self.ctx.set_compat_mode(enabled);
54 }
55
56 pub fn parse(&mut self) -> Result<ParserResult, ParseError> {
57 let expr_context = Arc::new(ExpressionAnalysisContext::new());
58 self.ctx.set_expression_context(expr_context.clone());
59 self.expr_context = expr_context;
60 self.ctx.reset_recovery_count();
61
62 let stmt = match self.parse_statement() {
63 Ok(stmt) => stmt,
64 Err(e) => {
65 let recorded = self.ctx.errors();
69 if !recorded.is_empty() {
70 let first = &recorded.errors[0];
71 return Err(ParseError {
72 kind: first.kind.clone(),
73 message: Box::from(first.message.as_ref()),
74 position: first.position,
75 offset: first.offset,
76 unexpected_token: first
77 .unexpected_token
78 .as_ref()
79 .map(|t| Box::from(t.as_ref())),
80 expected_tokens: first.expected_tokens.clone(),
81 context: None,
82 hints: first.hints.clone(),
83 recovered: first.recovered,
84 });
85 }
86 return Err(e);
87 }
88 };
89
90 if self.ctx.match_token(TokenKind::Semicolon) {
95 }
97 if self.ctx.current_token().kind != TokenKind::Eof {
98 self.ctx.add_error(ParseError::new(
99 ParseErrorKind::UnexpectedToken,
100 format!(
101 "Unexpected token after end of statement: {:?}",
102 self.ctx.current_token().kind
103 ),
104 self.ctx.current_position(),
105 ));
106 }
107
108 let ast = Ast::new(stmt, self.expr_context.clone());
109 Ok(ParserResult { ast: Arc::new(ast) })
110 }
111
112 pub fn parse_statement(&mut self) -> Result<Stmt, ParseError> {
113 if self.ctx.is_recovery_exhausted() {
114 return Err(ParseError::new(
115 crate::parser::core::error::ParseErrorKind::SyntaxError,
116 "Too many parse errors, aborting".to_string(),
117 self.ctx.current_position(),
118 ));
119 }
120
121 match StmtParser::parse_statement(&mut self.ctx) {
122 Ok(stmt) => Ok(stmt),
123 Err(e) => {
124 if self.ctx.is_recovery_exhausted() {
125 Err(e)
126 } else {
127 self.ctx.try_recover(e, RecoveryScope::Statement)?;
128 self.parse_statement()
129 }
130 }
131 }
132 }
133
134 pub fn parse_expression_contextual(&mut self) -> Result<ContextualExpression, ParseError> {
135 match parse_expression_with_context(&mut self.ctx, self.expr_context.clone()) {
136 Ok(expr) => Ok(expr),
137 Err(e) => {
138 if self.ctx.is_recovery_exhausted() {
139 Err(e)
140 } else {
141 self.ctx.try_recover(e, RecoveryScope::Expression)?;
142 self.parse_expression_contextual()
143 }
144 }
145 }
146 }
147
148 pub fn expression_context(&self) -> &Arc<ExpressionAnalysisContext> {
149 &self.expr_context
150 }
151
152 pub fn expression_context_clone(&self) -> Arc<ExpressionAnalysisContext> {
153 self.expr_context.clone()
154 }
155
156 pub fn has_errors(&self) -> bool {
157 self.ctx.has_errors()
158 }
159
160 pub fn errors(&self) -> &crate::parser::ParseErrors {
161 self.ctx.errors()
162 }
163
164 pub fn take_errors(&mut self) -> crate::parser::ParseErrors {
165 self.ctx.take_errors()
166 }
167}