1use std::error::Error;
9use std::fmt::{Display, Formatter};
10use std::option::Option;
11
12use crate::lexer::canonical_keyword_spelling;
13use crate::parse::{Lookahead, SignificantToken};
14use crate::{
15 AngleBarList, AnyCell, Array, Assignment, AssignmentExpr, BinaryAssignment, BinaryExpression,
16 BinaryInstallation, BinaryOperator, BindingPack, BreakStatement, CatchStatement, CellStream,
17 Collection, Component, ContinueStatement, DebugClause, DebugKeyword, DelimiterKind, ElseClause,
18 EmptyComponent, EvaluatedAssignment, ExceptClause, Expr, ExpressionCell, FloatLiteral, ForLoop,
19 IfStatement, IntegerLiteral, IterationRange, LambdaExpression, LambdaParameters, LexError,
20 List, LiteralKind, LocalAssignment, LocalStructuredBinding, LoopBody, MutedCell, MutedGroup,
21 NakedSequence, NewStatement, OperatorExpr, OptionExpression, PREC_APPLICATION,
22 PREC_APPLICATION_RIGHT, PREC_CLOSER, PREC_COLLECTION, PREC_COMMA, PREC_CONTROL,
23 PREC_LOOP_CLAUSE, PREC_QUOTE, PREC_SEMICOLON, ParenthesizedExpression, Parse, ParseStream,
24 Parser, PostfixAssignment, PostfixExpression, PostfixInstallation, PostfixOperator,
25 PrefixAssignment, PrefixExpression, PrefixInstallation, PrefixOperator, Punctuated,
26 QuoteExpression, QuoteSpecifier, RawStringContent, RawStringElement, RawStringLiteral,
27 ReturnStatement, Sequence, SequenceCell, SourceFile, SourceId, Span, Spanned, StringContent,
28 StringElement, StringLiteral, StructuredBinding, Symbol, ThenClause, ThrowStatement,
29 TokenParseError, TokenStream, TokenTree, TrapStatement, TryFallback, TryStatement, WhileLoop,
30 lex_str,
31};
32
33macro_rules! is_token {
34 ($token:expr, $($pattern:tt)*) => {
35 <Token![$($pattern)*] as crate::Token>::matches_token_tree($token)
36 };
37}
38
39#[derive(Debug, Default)]
41pub struct NativeParser;
42
43impl NativeParser {
44 pub fn new() -> Self {
45 Self
46 }
47}
48
49impl Parser for NativeParser {
50 type Error = NativeParseError;
51
52 fn parse_cells(&mut self, tokens: CellStream) -> Result<SourceFile, Self::Error> {
53 parse_cells(tokens)
54 }
55}
56
57pub fn parse_native(source: &str, source_id: SourceId) -> Result<SourceFile, NativeParseError> {
58 let tokens = lex_str(source, source_id).map_err(NativeParseError::Lex)?;
59 NativeParser.parse_cells(tokens)
60}
61
62#[derive(Debug, Spanned)]
63pub enum NativeParseError {
64 Lex(LexError),
65 Unexpected {
66 found: String,
67 expected: &'static str,
68 span: Span,
69 },
70 MissingOperand {
71 operator: String,
72 span: Span,
73 },
74 NewlineInApplication {
75 span: Span,
76 },
77 InvalidAssignmentTarget {
78 span: Span,
79 },
80 InvalidLambdaParameters {
81 span: Span,
82 },
83 Unsupported {
84 syntax: String,
85 span: Span,
86 },
87}
88
89impl Display for NativeParseError {
90 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
91 match self {
92 Self::Lex(error) => error.fmt(formatter),
93 Self::Unexpected {
94 found, expected, ..
95 } => write!(formatter, "expected {expected}, found `{found}`"),
96 Self::MissingOperand { operator, .. } => {
97 write!(formatter, "operator `{operator}` requires an operand")
98 }
99 Self::NewlineInApplication { .. } => {
100 formatter.write_str("implicit application cannot cross a line break")
101 }
102 Self::InvalidAssignmentTarget { .. } => {
103 formatter.write_str("invalid assignment target")
104 }
105 Self::InvalidLambdaParameters { .. } => {
106 formatter.write_str("invalid lambda parameter list")
107 }
108 Self::Unsupported { syntax, .. } => {
109 write!(
110 formatter,
111 "native parsing of `{syntax}` is not implemented yet"
112 )
113 }
114 }
115 }
116}
117
118impl Error for NativeParseError {
119 fn source(&self) -> Option<&(dyn Error + 'static)> {
120 match self {
121 Self::Lex(error) => Some(error),
122 _ => None,
123 }
124 }
125}
126
127#[derive(Debug, Clone, Copy)]
128enum UnaryAction {
134 Atom,
135 Prefix,
136 Statement,
137 Control,
138 Debug,
139 Delimiter,
140 Quote,
141 Error,
142}
143
144#[derive(Debug, Clone, Copy)]
145struct ParseInfo {
146 precedence: u8,
147 binary_strength: Option<u8>,
148 unary_strength: Option<u8>,
149 unary: UnaryAction,
150 postfix: bool,
151}
152
153impl ParseInfo {
154 const fn atom(precedence: u8) -> Self {
155 Self {
156 precedence,
157 binary_strength: None,
158 unary_strength: None,
159 unary: UnaryAction::Atom,
160 postfix: false,
161 }
162 }
163
164 const fn binary(precedence: u8, strength: u8) -> Self {
165 Self {
166 precedence,
167 binary_strength: Some(strength),
168 unary_strength: None,
169 unary: UnaryAction::Error,
170 postfix: false,
171 }
172 }
173
174 const fn prefix_binary(precedence: u8, binary_strength: u8, unary_strength: u8) -> Self {
175 Self {
176 precedence,
177 binary_strength: Some(binary_strength),
178 unary_strength: Some(unary_strength),
179 unary: UnaryAction::Prefix,
180 postfix: false,
181 }
182 }
183
184 const fn prefix(precedence: u8, unary_strength: u8) -> Self {
185 Self {
186 precedence,
187 binary_strength: None,
188 unary_strength: Some(unary_strength),
189 unary: UnaryAction::Prefix,
190 postfix: false,
191 }
192 }
193
194 const fn statement() -> Self {
195 Self {
196 precedence: PREC_APPLICATION,
197 binary_strength: None,
198 unary_strength: Some(PREC_CONTROL),
199 unary: UnaryAction::Statement,
200 postfix: false,
201 }
202 }
203
204 const fn control(unary_strength: u8) -> Self {
205 Self {
206 precedence: PREC_APPLICATION,
207 binary_strength: None,
208 unary_strength: Some(unary_strength),
209 unary: UnaryAction::Control,
210 postfix: false,
211 }
212 }
213
214 const fn debug() -> Self {
215 Self {
216 precedence: PREC_APPLICATION,
217 binary_strength: None,
218 unary_strength: Some(PREC_CONTROL),
219 unary: UnaryAction::Debug,
220 postfix: false,
221 }
222 }
223
224 const fn postfix(precedence: u8) -> Self {
225 Self {
226 precedence,
227 binary_strength: None,
228 unary_strength: None,
229 unary: UnaryAction::Error,
230 postfix: true,
231 }
232 }
233
234 const fn delimiter(precedence: u8) -> Self {
235 Self {
236 precedence,
237 binary_strength: None,
238 unary_strength: Some(PREC_CLOSER),
239 unary: UnaryAction::Delimiter,
240 postfix: false,
241 }
242 }
243
244 const fn stop(precedence: u8) -> Self {
245 Self {
246 precedence,
247 binary_strength: None,
248 unary_strength: None,
249 unary: UnaryAction::Error,
250 postfix: false,
251 }
252 }
253
254 const fn quote(precedence: u8, unary_strength: u8) -> Self {
255 Self {
256 precedence,
257 binary_strength: None,
258 unary_strength: Some(unary_strength),
259 unary: UnaryAction::Quote,
260 postfix: false,
261 }
262 }
263}
264
265struct Engine {
266 input: ParseStream,
267}
268
269impl Engine {
270 fn new(tokens: TokenStream) -> Self {
271 Self {
272 input: ParseStream::new(tokens),
273 }
274 }
275
276 fn parse_cell(
277 mut self,
278 delimiter: crate::Delimiter,
279 ) -> Result<Option<AnyCell>, NativeParseError> {
280 self.skip_trivia();
281 if matches!(self.peek(), Lookahead::End(_)) {
282 return match delimiter.kind {
283 DelimiterKind::Empty => Ok(None),
284 DelimiterKind::Semicolon => Err(NativeParseError::Unexpected {
285 found: ";".into(),
286 expected: "a statement before `;`",
287 span: delimiter.closing_span(),
288 }),
289 _ => Err(NativeParseError::Unexpected {
290 found: delimiter.kind.to_string(),
291 expected: "an empty or semicolon cell delimiter",
292 span: delimiter.span(),
293 }),
294 };
295 }
296
297 let (components, comma) = self.parse_components()?;
298
299 if let Lookahead::Token(token) = self.peek() {
300 return Err(self.unexpected(token.token, "the end of the cell"));
301 }
302
303 let cell = match delimiter.kind {
304 DelimiterKind::Semicolon => AnyCell::MutedCell(MutedCell::new(
305 components,
306 Token),
307 )),
308 DelimiterKind::Empty if comma => {
309 AnyCell::SequenceCell(SequenceCell::new(NakedSequence::new(components)))
310 }
311 DelimiterKind::Empty => {
312 let value = self.only_expression(components)?;
313 AnyCell::ExpressionCell(ExpressionCell::new(value))
314 }
315 _ => {
316 return Err(NativeParseError::Unexpected {
317 found: delimiter.kind.to_string(),
318 expected: "an empty or semicolon cell delimiter",
319 span: delimiter.span(),
320 });
321 }
322 };
323 Ok(Some(cell))
324 }
325
326 fn parse_components(&mut self) -> Result<(Punctuated<Component>, bool), NativeParseError> {
327 if self.at_end() || self.at_punctuation(";") {
328 return Ok((Punctuated::new(), false));
329 }
330
331 let first = if self.at_punctuation(",") {
332 Component::EmptyComponent(EmptyComponent::new("", self.peek().span()))
333 } else {
334 Component::Expr(self.parse_required(PREC_COMMA)?)
335 };
336 let mut elements = Punctuated::from_value(first);
337 let mut has_comma = false;
338
339 while let Some(comma) = self.take_punctuation(",") {
340 has_comma = true;
341 let next = if self.at_end() || self.at_punctuation(";") || self.at_punctuation(",") {
342 Component::EmptyComponent(EmptyComponent::new("", self.peek().span()))
343 } else {
344 Component::Expr(self.parse_required(PREC_COMMA)?)
345 };
346 elements.push(typed_token(comma), next);
347 }
348
349 Ok((elements, has_comma))
350 }
351
352 fn parse_required(&mut self, level: u8) -> Result<Expr, NativeParseError> {
353 let token = match self.consume() {
354 Lookahead::Token(token) => token,
355 Lookahead::End(span) => {
356 return Err(NativeParseError::MissingOperand {
357 operator: "end of input".into(),
358 span,
359 });
360 }
361 };
362 self.parse_consumed(token, level)
363 }
364
365 fn parse_nullable(&mut self, level: u8) -> Result<Option<Expr>, NativeParseError> {
366 let lookahead = self.peek();
367 let Lookahead::Token(token) = lookahead else {
368 return Ok(None);
369 };
370 if parse_info(&token.token).precedence <= level {
371 return Ok(None);
372 }
373 let Lookahead::Token(token) = self.consume() else {
374 unreachable!("the token just peeked is consumable")
375 };
376 self.parse_consumed(token, level).map(Some)
377 }
378
379 fn parse_consumed(
380 &mut self,
381 token: SignificantToken,
382 level: u8,
383 ) -> Result<Expr, NativeParseError> {
384 let info = parse_info(&token.token);
385 let result = match info.unary {
386 UnaryAction::Atom => self.lower_atom(token.token)?,
387 UnaryAction::Prefix => {
388 let strength = info.unary_strength.expect("prefix operators have U");
389 let operand = self.parse_required(level.max(strength))?;
390 let span = token.token.span();
391 let spelling = token_description(&token.token);
392 let operator = PrefixOperator::from_token_tree(token.token).ok_or({
393 NativeParseError::Unsupported {
394 syntax: spelling,
395 span,
396 }
397 })?;
398 PrefixExpression::new(operator, operand).into()
399 }
400 UnaryAction::Statement => {
401 let strength = info
402 .unary_strength
403 .expect("prefix statements have a unary binding strength");
404 let operand = if is_token!(&token.token, break)
405 || is_token!(&token.token, continue)
406 || is_token!(&token.token, return)
407 {
408 self.parse_nullable(level.max(strength))?
409 } else {
410 self.parse_required(level.max(strength))
411 .map_err(|error| {
412 if matches!(error, NativeParseError::MissingOperand { .. }) {
413 NativeParseError::MissingOperand {
414 operator: token_description(&token.token),
415 span: token.token.span(),
416 }
417 } else {
418 error
419 }
420 })?
421 .into()
422 };
423 self.lower_prefix_statement(token.token, operand)
424 }
425 UnaryAction::Control => {
426 if is_token!(&token.token, if) {
427 self.parse_if_statement(token.token)?
428 } else if is_token!(&token.token, for) {
429 self.parse_for_loop(token.token)?
430 } else if is_token!(&token.token, while) {
431 self.parse_while_loop(token.token)?
432 } else if is_token!(&token.token, try) {
433 self.parse_try_statement(token.token)?
434 } else if is_token!(&token.token, new) {
435 self.parse_new_statement(token.token)?
436 } else {
437 unreachable!("control actions are assigned only to control keywords")
438 }
439 }
440 UnaryAction::Debug => self.parse_debug_clause(token.token)?,
441 UnaryAction::Delimiter => self.parse_delimited(token.token)?,
442 UnaryAction::Quote => {
443 let operator = token_description(&token.token);
444 let quoted = match self.consume() {
445 Lookahead::Token(quoted) => quoted.token,
446 Lookahead::End(span) => {
447 return Err(NativeParseError::MissingOperand { operator, span });
448 }
449 };
450 let specifier = if is_token!(&token.token, symbol) {
451 QuoteSpecifier::Symbol(typed_token(token.token))
452 } else if is_token!(&token.token, local) {
453 QuoteSpecifier::Local(typed_token(token.token))
454 } else if is_token!(&token.token, global) {
455 QuoteSpecifier::Global(typed_token(token.token))
456 } else if is_token!(&token.token, threadVariable) {
457 QuoteSpecifier::ThreadVariable(typed_token(token.token))
458 } else if is_token!(&token.token, threadLocal) {
459 QuoteSpecifier::ThreadLocal(typed_token(token.token))
460 } else {
461 unreachable!("quote actions are assigned only to quote specifiers")
462 };
463 let quoted_span = quoted.span();
464 let Some(quoted_text) = token_spelling("ed).map(str::to_owned) else {
465 return Err(self.unexpected(quoted, "a quoted token"));
466 };
467 let quoted = Symbol::new(quoted_text, quoted_span);
468 QuoteExpression::new(specifier, quoted).into()
469 }
470 UnaryAction::Error => return Err(self.unexpected(token.token, "an expression")),
471 };
472 self.accumulate(result, level)
473 }
474
475 fn lower_prefix_statement(&self, keyword: TokenTree, value: Option<Expr>) -> Expr {
476 if is_token!(&keyword, break) {
477 BreakStatement::new(typed_token(keyword), value).into()
478 } else if is_token!(&keyword, continue) {
479 ContinueStatement::new(typed_token(keyword), value).into()
480 } else if is_token!(&keyword, return) {
481 ReturnStatement::new(typed_token(keyword), value).into()
482 } else if is_token!(&keyword, catch) {
483 CatchStatement::new(
484 typed_token(keyword),
485 value.expect("catch statements require a value"),
486 )
487 .into()
488 } else if is_token!(&keyword, throw) {
489 ThrowStatement::new(
490 typed_token(keyword),
491 value.expect("throw statements require a value"),
492 )
493 .into()
494 } else if is_token!(&keyword, trap) {
495 TrapStatement::new(
496 typed_token(keyword),
497 value.expect("trap statements require a value"),
498 )
499 .into()
500 } else {
501 unreachable!("statement actions are assigned only to statement keywords")
502 }
503 }
504
505 fn parse_if_statement(&mut self, keyword: TokenTree) -> Result<Expr, NativeParseError> {
506 let condition = self.required_clause_expression(PREC_CONTROL, &keyword)?;
507 let then_keyword = self.consume_exact("then")?;
508 let then_value = self.required_clause_expression(PREC_CONTROL, &then_keyword)?;
509 let then_clause = ThenClause::new(typed_token(then_keyword), then_value);
510 let else_clause = self
511 .take_exact("else")
512 .map(|else_keyword| {
513 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword)?;
514 Ok::<_, NativeParseError>(ElseClause::new(typed_token(else_keyword), value))
515 })
516 .transpose()?;
517 Ok(IfStatement::new(typed_token(keyword), condition, then_clause, else_clause).into())
518 }
519
520 fn parse_for_loop(&mut self, keyword: TokenTree) -> Result<Expr, NativeParseError> {
521 let variable = self.consume_symbol("a loop variable")?;
522
523 let mut in_keyword = None;
524 let mut iterated_collection = None;
525 let mut from_keyword = None;
526 let mut range_start = None;
527 let mut to_keyword = None;
528 let mut range_end = None;
529
530 if let Some(token) = self.take_exact("in") {
531 iterated_collection = Some(self.required_clause_expression(PREC_LOOP_CLAUSE, &token)?);
532 in_keyword = Some(typed_token(token));
533 } else {
534 if let Some(token) = self.take_exact("from") {
535 range_start = Some(self.required_clause_expression(PREC_LOOP_CLAUSE, &token)?);
536 from_keyword = Some(typed_token(token));
537 }
538 if let Some(token) = self.take_exact("to") {
539 range_end = Some(self.required_clause_expression(PREC_LOOP_CLAUSE, &token)?);
540 to_keyword = Some(typed_token(token));
541 }
542 }
543
544 let range =
545 (in_keyword.is_some() || from_keyword.is_some() || to_keyword.is_some()).then(|| {
546 IterationRange::new(
547 in_keyword,
548 iterated_collection,
549 from_keyword,
550 range_start,
551 to_keyword,
552 range_end,
553 )
554 });
555
556 let (when_keyword, filter) = if let Some(token) = self.take_exact("when") {
557 let filter = self.required_clause_expression(PREC_LOOP_CLAUSE, &token)?;
558 (Some(typed_token(token)), Some(filter))
559 } else {
560 (None, None)
561 };
562 let body = self.parse_loop_body()?;
563
564 Ok(ForLoop::new(
565 typed_token(keyword),
566 variable,
567 range,
568 when_keyword,
569 filter,
570 body,
571 )
572 .into())
573 }
574
575 fn parse_while_loop(&mut self, keyword: TokenTree) -> Result<Expr, NativeParseError> {
576 let condition = self.required_clause_expression(PREC_CONTROL, &keyword)?;
577 let body = self.parse_loop_body()?;
578 Ok(WhileLoop::new(typed_token(keyword), condition, body).into())
579 }
580
581 fn parse_loop_body(&mut self) -> Result<LoopBody, NativeParseError> {
582 let mut list_keyword = None;
583 let mut listed_value = None;
584 let mut do_keyword = None;
585 let mut ignored_value = None;
586
587 if let Some(token) = self.take_exact("list") {
588 listed_value = Some(self.required_clause_expression(PREC_CONTROL, &token)?);
589 list_keyword = Some(typed_token(token));
590 if let Some(token) = self.take_exact("do") {
591 ignored_value = Some(self.required_clause_expression(PREC_CONTROL, &token)?);
592 do_keyword = Some(typed_token(token));
593 }
594 } else if let Some(token) = self.take_exact("do") {
595 ignored_value = Some(self.required_clause_expression(PREC_CONTROL, &token)?);
596 do_keyword = Some(typed_token(token));
597 } else {
598 return Err(self.expected_at_lookahead("`list` or `do`"));
599 }
600
601 Ok(LoopBody::new(
602 list_keyword,
603 listed_value,
604 do_keyword,
605 ignored_value,
606 ))
607 }
608
609 fn parse_try_statement(&mut self, keyword: TokenTree) -> Result<Expr, NativeParseError> {
610 let value = self.required_clause_expression(PREC_CONTROL, &keyword)?;
611 let then_clause = self
612 .take_exact("then")
613 .map(|then_keyword| {
614 let value = self.required_clause_expression(PREC_CONTROL, &then_keyword)?;
615 Ok::<_, NativeParseError>(ThenClause::new(typed_token(then_keyword), value))
616 })
617 .transpose()?;
618
619 let fallback = if let Some(else_keyword) = self.take_exact("else") {
620 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword)?;
621 Some(TryFallback::ElseClause(ElseClause::new(
622 typed_token(else_keyword),
623 value,
624 )))
625 } else if let Some(except_keyword) = self.take_exact("except") {
626 let exception = self.consume_symbol("an exception symbol")?;
627 let do_keyword = self.consume_exact("do")?;
628 let value = self.required_clause_expression(PREC_CONTROL, &do_keyword)?;
629 Some(TryFallback::ExceptClause(ExceptClause::new(
630 typed_token(except_keyword),
631 exception,
632 typed_token(do_keyword),
633 value,
634 )))
635 } else {
636 None
637 };
638
639 Ok(TryStatement::new(typed_token(keyword), value, then_clause, fallback).into())
640 }
641
642 fn parse_new_statement(&mut self, keyword: TokenTree) -> Result<Expr, NativeParseError> {
643 let class = self.required_clause_expression(PREC_LOOP_CLAUSE, &keyword)?;
644 let (of_keyword, parent) = if let Some(token) = self.take_exact("of") {
645 let parent = self.required_clause_expression(PREC_LOOP_CLAUSE, &token)?;
646 (Some(typed_token(token)), Some(parent))
647 } else {
648 (None, None)
649 };
650 let (from_keyword, instance) = if let Some(token) = self.take_exact("from") {
651 let instance = self.required_clause_expression(PREC_LOOP_CLAUSE, &token)?;
652 (Some(typed_token(token)), Some(instance))
653 } else {
654 (None, None)
655 };
656
657 Ok(NewStatement::new(
658 typed_token(keyword),
659 class,
660 of_keyword,
661 parent,
662 from_keyword,
663 instance,
664 )
665 .into())
666 }
667
668 fn parse_debug_clause(&mut self, keyword: TokenTree) -> Result<Expr, NativeParseError> {
669 let span = keyword.span();
670 let spelling = parsing_spelling(&keyword).to_owned();
671 let value_is_optional = matches!(spelling.as_str(), "step" | "finish");
672 let value = if value_is_optional {
673 self.parse_nullable(PREC_CONTROL)?
674 } else {
675 Some(self.parse_required(PREC_CONTROL).map_err(|error| {
676 if matches!(error, NativeParseError::MissingOperand { .. }) {
677 NativeParseError::MissingOperand {
678 operator: token_description(&keyword),
679 span,
680 }
681 } else {
682 error
683 }
684 })?)
685 };
686 let keyword = match spelling.as_str() {
687 "step" => DebugKeyword::Step(typed_token(keyword)),
688 "finish" => DebugKeyword::Finish(typed_token(keyword)),
689 "shield" => DebugKeyword::Shield(typed_token(keyword)),
690 "TEST" => DebugKeyword::Test(typed_token(keyword)),
691 "time" => DebugKeyword::Time(typed_token(keyword)),
692 "timing" => DebugKeyword::Timing(typed_token(keyword)),
693 "breakpoint" => DebugKeyword::Breakpoint(typed_token(keyword)),
694 "elapsedTime" => DebugKeyword::ElapsedTime(typed_token(keyword)),
695 "elapsedTiming" => DebugKeyword::ElapsedTiming(typed_token(keyword)),
696 "profile" => DebugKeyword::Profile(typed_token(keyword)),
697 _ => unreachable!("debug actions are assigned only to debug keywords"),
698 };
699 Ok(DebugClause::new(keyword, value).into())
700 }
701
702 fn required_clause_expression(
703 &mut self,
704 level: u8,
705 keyword: &TokenTree,
706 ) -> Result<Expr, NativeParseError> {
707 match self.parse_nullable(level)? {
708 None => Err(NativeParseError::MissingOperand {
709 operator: token_description(keyword),
710 span: keyword.span(),
711 }),
712 Some(expression) => Ok(expression),
713 }
714 }
715
716 fn consume_symbol(&mut self, expected: &'static str) -> Result<Symbol, NativeParseError> {
717 match self.consume() {
718 Lookahead::Token(token)
719 if matches!(token.token, TokenTree::Ident(_))
720 && matches!(parse_info(&token.token).unary, UnaryAction::Atom) =>
721 {
722 let span = token.token.span();
723 let text = token_description(&token.token);
724 Ok(Symbol::new(text, span))
725 }
726 Lookahead::Token(token) => Err(self.unexpected(token.token, expected)),
727 Lookahead::End(span) => Err(NativeParseError::Unexpected {
728 found: "end of input".into(),
729 expected,
730 span,
731 }),
732 }
733 }
734
735 fn consume_exact(&mut self, spelling: &'static str) -> Result<TokenTree, NativeParseError> {
736 match self.consume() {
737 Lookahead::Token(token) if parsing_spelling(&token.token) == spelling => {
738 Ok(token.token)
739 }
740 Lookahead::Token(token) => Err(self.unexpected(token.token, spelling)),
741 Lookahead::End(span) => Err(NativeParseError::Unexpected {
742 found: "end of input".into(),
743 expected: spelling,
744 span,
745 }),
746 }
747 }
748
749 fn take_exact(&mut self, spelling: &'static str) -> Option<TokenTree> {
750 if matches!(
751 self.peek(),
752 Lookahead::Token(token)
753 if parsing_spelling(&token.token) == spelling
754 ) {
755 let Lookahead::Token(token) = self.consume() else {
756 unreachable!("the token just peeked is consumable")
757 };
758 Some(token.token)
759 } else {
760 None
761 }
762 }
763
764 fn expected_at_lookahead(&self, expected: &'static str) -> NativeParseError {
765 match self.peek() {
766 Lookahead::Token(token) => self.unexpected(token.token, expected),
767 Lookahead::End(span) => NativeParseError::Unexpected {
768 found: "end of input".into(),
769 expected,
770 span,
771 },
772 }
773 }
774
775 fn accumulate(&mut self, mut left: Expr, level: u8) -> Result<Expr, NativeParseError> {
776 loop {
777 let Lookahead::Token(next) = self.peek() else {
778 return Ok(left);
779 };
780 let info = parse_info(&next.token);
781 if info.precedence <= level {
782 return Ok(left);
783 }
784 let Lookahead::Token(operator) = self.consume() else {
785 unreachable!("the token just peeked is consumable")
786 };
787 left = if let Some(strength) = info.binary_strength {
788 let right = self.parse_required(strength).map_err(|error| {
789 if matches!(error, NativeParseError::MissingOperand { .. }) {
790 NativeParseError::MissingOperand {
791 operator: token_description(&operator.token),
792 span: operator.token.span(),
793 }
794 } else {
795 error
796 }
797 })?;
798 self.lower_binary(left, operator.token, right)?
799 } else if info.postfix {
800 let span = operator.token.span();
801 let spelling = token_description(&operator.token);
802 let operator = PostfixOperator::from_token_tree(operator.token).ok_or(
803 NativeParseError::Unsupported {
804 syntax: spelling,
805 span,
806 },
807 )?;
808 PostfixExpression::new(left, operator).into()
809 } else if !matches!(info.unary, UnaryAction::Error) {
810 if operator.crossed_newline {
811 return Err(NativeParseError::NewlineInApplication {
812 span: operator.token.span(),
813 });
814 }
815 let adjacency_span = operator.leading_span;
816 let right = self.parse_consumed(operator, PREC_APPLICATION_RIGHT)?;
817 BinaryExpression::new(
818 left,
819 BinaryOperator::from(Token),
820 right,
821 )
822 .into()
823 } else {
824 return Err(self.unexpected(operator.token, "an operator"));
825 };
826 }
827 }
828
829 fn parse_delimited(&mut self, token: TokenTree) -> Result<Expr, NativeParseError> {
830 let TokenTree::Group(group) = token else {
831 return Err(self.unexpected(token, "a delimited group"));
832 };
833 let kind = group.delim_kind();
834 let delimiter_span = group.span();
835 let mut contents = Self::new(group.into_stream());
836 let mut muted = Vec::new();
837 let (elements, comma) = loop {
838 let (elements, comma) = contents.parse_components()?;
839 let Some(separator) = contents.take_punctuation(";") else {
840 break (elements, comma);
841 };
842 if elements.is_empty() {
843 return Err(contents.unexpected(separator, "a statement before `;`"));
844 }
845 muted.push(MutedGroup::new(elements, typed_token(separator)));
846 };
847 if let Lookahead::Token(token) = contents.peek() {
848 return Err(contents.unexpected(token.token, "the end of the group"));
849 }
850
851 let expression: Expr = match kind {
852 DelimiterKind::Empty | DelimiterKind::Semicolon => {
853 return Err(NativeParseError::Unsupported {
854 syntax: format!("{} cell delimiter in expression position", kind),
855 span: delimiter_span.span(),
856 });
857 }
858 DelimiterKind::Bracket => {
859 let mut value = Array::new(muted, elements);
860 value.delimiter = <Delimiter![[]] as crate::DelimiterToken>::new(delimiter_span);
861 value.into()
862 }
863 DelimiterKind::Brace => {
864 let mut value = List::new(muted, elements);
865 value.delimiter = <Delimiter![{}] as crate::DelimiterToken>::new(delimiter_span);
866 value.into()
867 }
868 DelimiterKind::AngleBar => {
869 let mut value = AngleBarList::new(muted, elements);
870 value.delimiter =
871 <Delimiter![< | | >] as crate::DelimiterToken>::new(delimiter_span);
872 value.into()
873 }
874 DelimiterKind::Parenthesis if !muted.is_empty() || comma => {
875 let mut value = Sequence::new(muted, elements);
876 value.delimiter = <Delimiter![()] as crate::DelimiterToken>::new(delimiter_span);
877 value.into()
878 }
879 DelimiterKind::Parenthesis => {
880 let value = match elements.len() {
881 0 => None,
882 1 => Some(contents.only_expression(elements)?),
883 _ => unreachable!("multiple components imply a comma"),
884 };
885 let mut value = ParenthesizedExpression::new(Vec::new(), value);
886 value.delimiter = <Delimiter![()] as crate::DelimiterToken>::new(delimiter_span);
887 value.into()
888 }
889 };
890 Ok(expression)
891 }
892
893 fn lower_atom(&mut self, token: TokenTree) -> Result<Expr, NativeParseError> {
894 match token {
895 TokenTree::Ident(token) => {
896 let span = token.span();
897 Ok(Symbol::new(token.text(), span).into())
898 }
899 TokenTree::Literal(token) => {
900 let span = token.span();
901 let text = token.text().to_owned();
902 Ok(match token.kind {
903 LiteralKind::Integer => IntegerLiteral::new(text, span).into(),
904 LiteralKind::Float => FloatLiteral::new(text, span).into(),
905 LiteralKind::String => lower_string_literal(text, span),
906 LiteralKind::RawString => lower_raw_string_literal(text, span),
907 })
908 }
909 token => Err(self.unexpected(token, "an expression")),
910 }
911 }
912
913 fn lower_binary(
914 &mut self,
915 left: Expr,
916 operator: TokenTree,
917 right: Expr,
918 ) -> Result<Expr, NativeParseError> {
919 let span = operator.span();
920 let spelling = token_spelling(&operator)
921 .expect("binary actions are assigned only to spelled tokens")
922 .to_owned();
923 match spelling.as_str() {
924 "=" => self.lower_assignment(left, operator, right, false),
925 ":=" => self.lower_assignment(left, operator, right, true),
926 "<-" => Ok(EvaluatedAssignment::new(left, typed_token(operator), right).into()),
927 "=>" => Ok(OptionExpression::new(left, typed_token(operator), right).into()),
928 "->" => {
929 let parameters = lambda_parameters(left)
930 .ok_or(NativeParseError::InvalidLambdaParameters { span })?;
931 Ok(LambdaExpression::new(parameters, typed_token(operator), right).into())
932 }
933 _ => {
934 let operator = BinaryOperator::from_token_tree(operator).ok_or({
935 NativeParseError::Unsupported {
936 syntax: spelling,
937 span,
938 }
939 })?;
940 Ok(BinaryExpression::new(left, operator, right).into())
941 }
942 }
943 }
944
945 fn lower_assignment(
946 &mut self,
947 left: Expr,
948 operator: TokenTree,
949 right: Expr,
950 local: bool,
951 ) -> Result<Expr, NativeParseError> {
952 let span = operator.span();
953 let result =
954 match (local, left) {
955 (false, Expr::Symbol(left)) => {
956 AssignmentExpr::Assignment(Assignment::new(left, typed_token(operator), right))
957 }
958 (true, Expr::Symbol(left)) => AssignmentExpr::LocalAssignment(
959 LocalAssignment::new(left, typed_token(operator), right),
960 ),
961 (false, Expr::Collection(left)) => AssignmentExpr::StructuredBinding(
962 StructuredBinding::new(binding_pack(left), typed_token(operator), right),
963 ),
964 (true, Expr::Collection(left)) => AssignmentExpr::LocalStructuredBinding(
965 LocalStructuredBinding::new(binding_pack(left), typed_token(operator), right),
966 ),
967 (false, Expr::OperatorExpr(OperatorExpr::BinaryExpression(left))) => {
968 AssignmentExpr::BinaryAssignment(BinaryAssignment::new(
969 left,
970 typed_token(operator),
971 right,
972 ))
973 }
974 (true, Expr::OperatorExpr(OperatorExpr::BinaryExpression(left))) => {
975 AssignmentExpr::BinaryInstallation(BinaryInstallation::new(
976 left,
977 typed_token(operator),
978 right,
979 ))
980 }
981 (false, Expr::OperatorExpr(OperatorExpr::PrefixExpression(left))) => {
982 AssignmentExpr::PrefixAssignment(PrefixAssignment::new(
983 left,
984 typed_token(operator),
985 right,
986 ))
987 }
988 (true, Expr::OperatorExpr(OperatorExpr::PrefixExpression(left))) => {
989 AssignmentExpr::PrefixInstallation(PrefixInstallation::new(
990 left,
991 typed_token(operator),
992 right,
993 ))
994 }
995 (false, Expr::OperatorExpr(OperatorExpr::PostfixExpression(left))) => {
996 AssignmentExpr::PostfixAssignment(PostfixAssignment::new(
997 left,
998 typed_token(operator),
999 right,
1000 ))
1001 }
1002 (true, Expr::OperatorExpr(OperatorExpr::PostfixExpression(left))) => {
1003 AssignmentExpr::PostfixInstallation(PostfixInstallation::new(
1004 left,
1005 typed_token(operator),
1006 right,
1007 ))
1008 }
1009 _ => return Err(NativeParseError::InvalidAssignmentTarget { span }),
1010 };
1011 Ok(Expr::AssignmentExpr(result))
1012 }
1013
1014 fn only_expression(&self, components: Punctuated<Component>) -> Result<Expr, NativeParseError> {
1015 let mut components = components.into_iter();
1016 match (components.next(), components.next()) {
1017 (Some(Component::Expr(value)), None) => Ok(value),
1018 (Some(value), _) => Err(NativeParseError::Unexpected {
1019 found: "a sequence".into(),
1020 expected: "one expression",
1021 span: value.span(),
1022 }),
1023 (None, _) => Err(NativeParseError::MissingOperand {
1024 operator: "empty expression".into(),
1025 span: self.input.eof_span(),
1026 }),
1027 }
1028 }
1029
1030 fn peek(&self) -> Lookahead {
1031 self.input.lookahead()
1032 }
1033
1034 fn consume(&mut self) -> Lookahead {
1035 self.input.consume_lookahead()
1036 }
1037
1038 fn skip_trivia(&mut self) {
1039 self.input.skip_trivia();
1040 }
1041
1042 fn at_end(&self) -> bool {
1043 matches!(self.peek(), Lookahead::End(_))
1044 }
1045
1046 fn at_punctuation(&self, spelling: &str) -> bool {
1047 matches!(
1048 self.peek(),
1049 Lookahead::Token(token)
1050 if token.token.spelling() == Some(spelling)
1051 )
1052 }
1053
1054 fn take_punctuation(&mut self, spelling: &str) -> Option<TokenTree> {
1055 if !self.at_punctuation(spelling) {
1056 return None;
1057 }
1058 let Lookahead::Token(token) = self.consume() else {
1059 unreachable!("the punctuation just peeked is consumable")
1060 };
1061 Some(token.token)
1062 }
1063
1064 fn unexpected(&self, token: TokenTree, expected: &'static str) -> NativeParseError {
1065 let span = token.span();
1066 NativeParseError::Unexpected {
1067 found: token_description(&token),
1068 expected,
1069 span,
1070 }
1071 }
1072}
1073
1074fn parse_cells(cells: CellStream) -> Result<SourceFile, NativeParseError> {
1075 let mut elements = Vec::new();
1076 for cell in cells {
1077 let delimiter = *cell.delimiter();
1078 if let Some(element) = Engine::new(cell.into_stream()).parse_cell(delimiter)? {
1079 elements.push(element);
1080 }
1081 }
1082 Ok(SourceFile::new(elements))
1083}
1084
1085impl Parse for Expr {
1086 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1087 let tokens = input.by_ref().collect::<TokenStream>();
1088 let mut engine = Engine::new(tokens);
1089 engine.skip_trivia();
1090 let value = engine
1091 .parse_required(PREC_CLOSER)
1092 .map_err(token_parse_error)?;
1093 engine.skip_trivia();
1094 match engine.peek() {
1095 Lookahead::End(_) => Ok(value),
1096 Lookahead::Token(token) => Err(TokenParseError::TrailingToken {
1097 found: token_description(&token.token),
1098 span: token.token.span(),
1099 }),
1100 }
1101 }
1102}
1103
1104impl Parse for SourceFile {
1105 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1106 let source_id = input
1107 .peek()
1108 .and_then(|token| token.span().source().ok())
1109 .unwrap_or_else(SourceId::fresh);
1110 let source = input.by_ref().collect::<TokenStream>().to_string();
1111 parse_native(&source, source_id).map_err(token_parse_error)
1112 }
1113}
1114
1115fn token_parse_error(error: NativeParseError) -> TokenParseError {
1116 let span = error.span();
1117 TokenParseError::Syntax {
1118 message: error.to_string(),
1119 span,
1120 }
1121}
1122
1123fn token_spelling(token: &TokenTree) -> Option<&str> {
1124 token.spelling()
1125}
1126
1127fn parsing_spelling(token: &TokenTree) -> &str {
1128 token_spelling(token)
1129 .map(canonical_keyword_spelling)
1130 .unwrap_or("")
1131}
1132
1133fn token_description(token: &TokenTree) -> String {
1134 match token {
1135 TokenTree::Group(group) => group.delim_kind().to_string(),
1136 TokenTree::Trivia(token) => token.text().to_owned(),
1137 _ => token_spelling(token).unwrap_or("").to_owned(),
1138 }
1139}
1140
1141fn typed_token<T: crate::cst::Token>(token: TokenTree) -> T {
1142 let spelling = token_description(&token);
1143 T::from_token_tree(token)
1144 .unwrap_or_else(|| panic!("`{spelling}` cannot be lowered to `{}`", T::SPELLING))
1145}
1146
1147fn lower_string_literal(text: String, span: Span) -> Expr {
1148 let body = &text[1..text.len() - 1];
1149 let elements = (!body.is_empty())
1150 .then(|| StringElement::StringContent(StringContent::new(body, span)))
1151 .into_iter()
1152 .collect();
1153 StringLiteral::new(elements).into()
1154}
1155
1156fn lower_raw_string_literal(text: String, span: Span) -> Expr {
1157 let body = &text[3..text.len() - 3];
1158 let elements = (!body.is_empty())
1159 .then(|| RawStringElement::RawStringContent(RawStringContent::new(body, span)))
1160 .into_iter()
1161 .collect();
1162 RawStringLiteral::new(elements).into()
1163}
1164
1165fn binding_pack(collection: Collection) -> BindingPack {
1166 match collection {
1167 Collection::ParenthesizedExpression(value) => BindingPack::ParenthesizedExpression(value),
1168 Collection::Sequence(value) => BindingPack::Sequence(value),
1169 Collection::List(value) => BindingPack::List(value),
1170 Collection::Array(value) => BindingPack::Array(value),
1171 Collection::AngleBarList(value) => BindingPack::AngleBarList(value),
1172 }
1173}
1174
1175fn lambda_parameters(expression: Expr) -> Option<LambdaParameters> {
1176 match expression {
1177 Expr::Symbol(value) => Some(LambdaParameters::Symbol(value)),
1178 Expr::Collection(Collection::ParenthesizedExpression(value)) => {
1179 Some(LambdaParameters::ParenthesizedExpression(value))
1180 }
1181 Expr::Collection(Collection::Sequence(value)) => Some(LambdaParameters::Sequence(value)),
1182 Expr::Collection(Collection::List(value)) => Some(LambdaParameters::List(value)),
1183 Expr::Collection(Collection::Array(value)) => Some(LambdaParameters::Array(value)),
1184 Expr::Collection(Collection::AngleBarList(value)) => {
1185 Some(LambdaParameters::AngleBarList(value))
1186 }
1187 _ => None,
1188 }
1189}
1190
1191fn parse_info(token: &TokenTree) -> ParseInfo {
1192 if let TokenTree::Group(group) = token {
1193 return match group.delim_kind() {
1194 DelimiterKind::Empty | DelimiterKind::Semicolon => ParseInfo::stop(PREC_CLOSER),
1195 DelimiterKind::Bracket | DelimiterKind::AngleBar => {
1196 ParseInfo::delimiter(PREC_COLLECTION)
1197 }
1198 DelimiterKind::Parenthesis | DelimiterKind::Brace => {
1199 ParseInfo::delimiter(PREC_APPLICATION)
1200 }
1201 };
1202 }
1203
1204 let text = parsing_spelling(token);
1205 if let Some(info) = __m2_syn_parse_info!(text, ParseInfo) {
1206 return info;
1207 }
1208
1209 if is_token!(token, ;) {
1210 return ParseInfo::stop(PREC_SEMICOLON);
1211 }
1212 if is_token!(token, ,) {
1213 return ParseInfo::stop(PREC_COMMA);
1214 }
1215 if is_token!(token, else)
1216 || is_token!(token, then)
1217 || is_token!(token, do)
1218 || is_token!(token, list)
1219 || is_token!(token, except)
1220 {
1221 return ParseInfo::stop(PREC_CONTROL);
1222 }
1223 if is_token!(token, when)
1224 || is_token!(token, of)
1225 || is_token!(token, in)
1226 || is_token!(token, from)
1227 || is_token!(token, to)
1228 {
1229 return ParseInfo::stop(PREC_LOOP_CLAUSE);
1230 }
1231
1232 if is_token!(token, break)
1233 || is_token!(token, continue)
1234 || is_token!(token, return)
1235 || is_token!(token, catch)
1236 || is_token!(token, throw)
1237 || is_token!(token, trap)
1238 {
1239 return ParseInfo::statement();
1240 }
1241
1242 let control_strength = if is_token!(token, for) || is_token!(token, new) {
1243 Some(PREC_LOOP_CLAUSE)
1244 } else if is_token!(token, if) || is_token!(token, while) || is_token!(token, try) {
1245 Some(PREC_CONTROL)
1246 } else {
1247 None
1248 };
1249 if let Some(strength) = control_strength {
1250 return ParseInfo::control(strength);
1251 }
1252
1253 if is_token!(token, TEST)
1254 || is_token!(token, time)
1255 || is_token!(token, timing)
1256 || is_token!(token, elapsedTime)
1257 || is_token!(token, elapsedTiming)
1258 || is_token!(token, breakpoint)
1259 || is_token!(token, profile)
1260 || is_token!(token, shield)
1261 || is_token!(token, step)
1262 || is_token!(token, finish)
1263 {
1264 return ParseInfo::debug();
1265 }
1266
1267 if is_token!(token, symbol)
1268 || is_token!(token, global)
1269 || is_token!(token, threadVariable)
1270 || is_token!(token, threadLocal)
1271 || is_token!(token, local)
1272 {
1273 return ParseInfo::quote(PREC_APPLICATION, PREC_QUOTE);
1274 }
1275
1276 match token {
1277 TokenTree::Ident(_) | TokenTree::Literal(_) => ParseInfo::atom(PREC_APPLICATION),
1278 _ => ParseInfo::stop(PREC_APPLICATION),
1279 }
1280}