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