1use runmat_lexer::Token;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
5pub enum Expr {
6 Number(String),
7 String(String),
8 Ident(String),
9 EndKeyword, Unary(UnOp, Box<Expr>),
11 Binary(Box<Expr>, BinOp, Box<Expr>),
12 Tensor(Vec<Vec<Expr>>),
13 Cell(Vec<Vec<Expr>>),
14 Index(Box<Expr>, Vec<Expr>),
15 IndexCell(Box<Expr>, Vec<Expr>),
16 Range(Box<Expr>, Option<Box<Expr>>, Box<Expr>),
17 Colon,
18 FuncCall(String, Vec<Expr>),
19 Member(Box<Expr>, String),
20 MemberDynamic(Box<Expr>, Box<Expr>),
22 MethodCall(Box<Expr>, String, Vec<Expr>),
23 AnonFunc {
24 params: Vec<String>,
25 body: Box<Expr>,
26 },
27 FuncHandle(String),
28 MetaClass(String),
29}
30
31#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
32pub enum BinOp {
33 Add,
34 Sub,
35 Mul,
36 Div,
37 Pow,
38 LeftDiv,
39 Colon,
40 ElemMul, ElemDiv, ElemPow, ElemLeftDiv, AndAnd, OrOr, BitAnd, BitOr, Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual, }
58
59#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
60pub enum UnOp {
61 Plus,
62 Minus,
63 Transpose,
64 NonConjugateTranspose,
65 Not, }
67
68#[derive(Debug, PartialEq)]
69pub enum Stmt {
70 ExprStmt(Expr, bool), Assign(String, Expr, bool), MultiAssign(Vec<String>, Expr, bool),
73 AssignLValue(LValue, Expr, bool),
74 If {
75 cond: Expr,
76 then_body: Vec<Stmt>,
77 elseif_blocks: Vec<(Expr, Vec<Stmt>)>,
78 else_body: Option<Vec<Stmt>>,
79 },
80 While {
81 cond: Expr,
82 body: Vec<Stmt>,
83 },
84 For {
85 var: String,
86 expr: Expr,
87 body: Vec<Stmt>,
88 },
89 Switch {
90 expr: Expr,
91 cases: Vec<(Expr, Vec<Stmt>)>,
92 otherwise: Option<Vec<Stmt>>,
93 },
94 TryCatch {
95 try_body: Vec<Stmt>,
96 catch_var: Option<String>,
97 catch_body: Vec<Stmt>,
98 },
99 Global(Vec<String>),
100 Persistent(Vec<String>),
101 Break,
102 Continue,
103 Return,
104 Function {
105 name: String,
106 params: Vec<String>,
107 outputs: Vec<String>,
108 body: Vec<Stmt>,
109 },
110 Import {
111 path: Vec<String>,
112 wildcard: bool,
113 },
114 ClassDef {
115 name: String,
116 super_class: Option<String>,
117 members: Vec<ClassMember>,
118 },
119}
120
121#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
122pub enum LValue {
123 Var(String),
124 Member(Box<Expr>, String),
125 MemberDynamic(Box<Expr>, Box<Expr>),
126 Index(Box<Expr>, Vec<Expr>),
127 IndexCell(Box<Expr>, Vec<Expr>),
128}
129
130#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
131pub struct Attr {
132 pub name: String,
133 pub value: Option<String>,
134}
135
136#[derive(Debug, PartialEq)]
137pub enum ClassMember {
138 Properties {
139 attributes: Vec<Attr>,
140 names: Vec<String>,
141 },
142 Methods {
143 attributes: Vec<Attr>,
144 body: Vec<Stmt>,
145 },
146 Events {
147 attributes: Vec<Attr>,
148 names: Vec<String>,
149 },
150 Enumeration {
151 attributes: Vec<Attr>,
152 names: Vec<String>,
153 },
154 Arguments {
155 attributes: Vec<Attr>,
156 names: Vec<String>,
157 },
158}
159
160#[derive(Debug, PartialEq)]
161pub struct Program {
162 pub body: Vec<Stmt>,
163}
164
165#[derive(Clone)]
166struct TokenInfo {
167 token: Token,
168 lexeme: String,
169 position: usize,
170}
171
172#[derive(Debug)]
173pub struct ParseError {
174 pub message: String,
175 pub position: usize,
176 pub found_token: Option<String>,
177 pub expected: Option<String>,
178}
179
180pub fn parse(input: &str) -> Result<Program, ParseError> {
181 use runmat_lexer::tokenize_detailed;
182
183 let toks = tokenize_detailed(input);
184 let mut tokens = Vec::new();
185
186 for t in toks {
187 if matches!(t.token, Token::Error) {
188 return Err(ParseError {
189 message: format!("Invalid token: '{}'", t.lexeme),
190 position: t.start,
191 found_token: Some(t.lexeme),
192 expected: None,
193 });
194 }
195 if matches!(t.token, Token::Ellipsis | Token::Section) {
197 continue;
198 }
199 tokens.push(TokenInfo {
200 token: t.token,
201 lexeme: t.lexeme,
202 position: t.start,
203 });
204 }
205
206 let mut parser = Parser {
207 tokens,
208 pos: 0,
209 input: input.to_string(),
210 };
211 parser.parse_program()
212}
213
214pub fn parse_simple(input: &str) -> Result<Program, String> {
216 parse(input).map_err(|e| format!("{e}"))
217}
218
219impl std::fmt::Display for ParseError {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 write!(
222 f,
223 "Parse error at position {}: {}",
224 self.position, self.message
225 )?;
226 if let Some(found) = &self.found_token {
227 write!(f, " (found: '{found}')")?;
228 }
229 if let Some(expected) = &self.expected {
230 write!(f, " (expected: {expected})")?;
231 }
232 Ok(())
233 }
234}
235
236impl std::error::Error for ParseError {}
237
238impl From<String> for ParseError {
239 fn from(message: String) -> Self {
240 ParseError {
241 message,
242 position: 0,
243 found_token: None,
244 expected: None,
245 }
246 }
247}
248
249impl From<ParseError> for String {
250 fn from(error: ParseError) -> Self {
251 format!("{error}")
252 }
253}
254
255struct Parser {
256 tokens: Vec<TokenInfo>,
257 pos: usize,
258 input: String,
259}
260
261impl Parser {
262 fn parse_program(&mut self) -> Result<Program, ParseError> {
263 let mut body = Vec::new();
264 while self.pos < self.tokens.len() {
265 if self.consume(&Token::Semicolon) || self.consume(&Token::Comma) {
266 continue;
267 }
268 body.push(self.parse_stmt_with_semicolon()?);
269 }
270 Ok(Program { body })
271 }
272
273 fn error(&self, message: &str) -> ParseError {
274 let (position, found_token) = if let Some(token_info) = self.tokens.get(self.pos) {
275 (token_info.position, Some(token_info.lexeme.clone()))
276 } else {
277 (self.input.len(), None)
278 };
279
280 ParseError {
281 message: message.to_string(),
282 position,
283 found_token,
284 expected: None,
285 }
286 }
287
288 fn error_with_expected(&self, message: &str, expected: &str) -> ParseError {
289 let (position, found_token) = if let Some(token_info) = self.tokens.get(self.pos) {
290 (token_info.position, Some(token_info.lexeme.clone()))
291 } else {
292 (self.input.len(), None)
293 };
294
295 ParseError {
296 message: message.to_string(),
297 position,
298 found_token,
299 expected: Some(expected.to_string()),
300 }
301 }
302
303 fn parse_stmt_with_semicolon(&mut self) -> Result<Stmt, ParseError> {
304 let stmt = self.parse_stmt()?;
305 let is_semicolon_terminated = self.consume(&Token::Semicolon);
306
307 match stmt {
311 Stmt::ExprStmt(expr, _) => Ok(Stmt::ExprStmt(expr, is_semicolon_terminated)),
312 Stmt::Assign(name, expr, _) => {
313 let has_more_toplevel_tokens = self.pos < self.tokens.len();
314 Ok(Stmt::Assign(
315 name,
316 expr,
317 is_semicolon_terminated && has_more_toplevel_tokens,
318 ))
319 }
320 other => Ok(other),
321 }
322 }
323
324 fn parse_stmt(&mut self) -> Result<Stmt, ParseError> {
325 match self.peek_token() {
326 Some(Token::If) => self.parse_if().map_err(|e| e.into()),
327 Some(Token::For) => self.parse_for().map_err(|e| e.into()),
328 Some(Token::While) => self.parse_while().map_err(|e| e.into()),
329 Some(Token::Switch) => self.parse_switch().map_err(|e| e.into()),
330 Some(Token::Try) => self.parse_try_catch().map_err(|e| e.into()),
331 Some(Token::Import) => self.parse_import().map_err(|e| e.into()),
332 Some(Token::ClassDef) => self.parse_classdef().map_err(|e| e.into()),
333 Some(Token::Global) => self.parse_global().map_err(|e| e.into()),
334 Some(Token::Persistent) => self.parse_persistent().map_err(|e| e.into()),
335 Some(Token::Break) => {
336 self.pos += 1;
337 Ok(Stmt::Break)
338 }
339 Some(Token::Continue) => {
340 self.pos += 1;
341 Ok(Stmt::Continue)
342 }
343 Some(Token::Return) => {
344 self.pos += 1;
345 Ok(Stmt::Return)
346 }
347 Some(Token::Function) => self.parse_function().map_err(|e| e.into()),
348 Some(Token::LBracket) => {
350 let save = self.pos;
351 match self.try_parse_multi_assign() {
352 Ok(stmt) => Ok(stmt),
353 Err(_) => {
354 self.pos = save;
355 let expr = self.parse_expr()?;
356 Ok(Stmt::ExprStmt(expr, false))
357 }
358 }
359 }
360 _ => {
361 if self.peek_token() == Some(&Token::Ident)
362 && self.peek_token_at(1) == Some(&Token::Assign)
363 {
364 let name = self
365 .next()
366 .ok_or_else(|| self.error("expected identifier"))?
367 .lexeme;
368 if !self.consume(&Token::Assign) {
369 return Err(self.error_with_expected("expected assignment operator", "'='"));
370 }
371 let expr = self.parse_expr()?;
372 Ok(Stmt::Assign(name, expr, false)) } else if self.peek_token() == Some(&Token::Ident) {
374 if let Some(lv) = self.try_parse_lvalue_assign()? {
376 return Ok(lv);
377 }
378 if self.can_start_command_form() {
381 let name = self.next().unwrap().lexeme;
382 let args = self.parse_command_args();
383 Ok(Stmt::ExprStmt(Expr::FuncCall(name, args), false))
384 } else {
385 if matches!(self.peek_token_at(1), Some(Token::Ident))
388 && matches!(
389 self.peek_token_at(2),
390 Some(
391 Token::LParen
392 | Token::Dot
393 | Token::LBracket
394 | Token::LBrace
395 | Token::Transpose
396 )
397 )
398 {
399 return Err(self.error(
400 "ambiguous command-form near identifier; use function syntax foo(b(...)) or quote argument",
401 ));
402 }
403 let expr = self.parse_expr()?;
405 Ok(Stmt::ExprStmt(expr, false))
406 }
407 } else if let Some(lv) = self.try_parse_lvalue_assign()? {
408 Ok(lv)
409 } else {
410 let expr = self.parse_expr()?;
411 Ok(Stmt::ExprStmt(expr, false))
415 }
416 }
417 }
418 }
419
420 fn can_start_command_form(&self) -> bool {
421 let mut i = 1;
423 if !matches!(
425 self.peek_token_at(i),
426 Some(Token::Ident | Token::Integer | Token::Float | Token::Str | Token::End)
427 ) {
428 return false;
429 }
430 while matches!(
432 self.peek_token_at(i),
433 Some(Token::Ident | Token::Integer | Token::Float | Token::Str | Token::End)
434 ) {
435 i += 1;
436 }
437 match self.peek_token_at(i) {
439 Some(Token::LParen)
440 | Some(Token::Dot)
441 | Some(Token::LBracket)
442 | Some(Token::LBrace)
443 | Some(Token::Transpose) => false,
444 Some(Token::Assign) => false,
446 None | Some(Token::Semicolon) | Some(Token::Comma) | Some(Token::Newline) => true,
448 _ => true,
450 }
451 }
452
453 fn parse_command_args(&mut self) -> Vec<Expr> {
454 let mut args = Vec::new();
455 loop {
456 match self.peek_token() {
457 Some(Token::Ident) => {
458 let ident = self.next().unwrap().lexeme;
459 args.push(Expr::Ident(ident));
460 }
461 Some(Token::End) => {
463 self.pos += 1;
464 args.push(Expr::Ident("end".to_string()));
465 }
466 Some(Token::Integer) | Some(Token::Float) => {
467 let num = self.next().unwrap().lexeme;
468 args.push(Expr::Number(num));
469 }
470 Some(Token::Str) => {
471 let s = self.next().unwrap().lexeme;
472 args.push(Expr::String(s));
473 }
474 Some(Token::Slash)
476 | Some(Token::Star)
477 | Some(Token::Backslash)
478 | Some(Token::Plus)
479 | Some(Token::Minus)
480 | Some(Token::LParen)
481 | Some(Token::Dot)
482 | Some(Token::LBracket)
483 | Some(Token::LBrace)
484 | Some(Token::Transpose) => break,
485 _ => break,
486 }
487 }
488 args
489 }
490
491 fn try_parse_lvalue_assign(&mut self) -> Result<Option<Stmt>, ParseError> {
492 let save = self.pos;
493 let lvalue = if self.peek_token() == Some(&Token::Ident) {
495 let base_ident = self.next().unwrap().lexeme;
497 let mut base = Expr::Ident(base_ident);
498 loop {
499 if self.consume(&Token::LParen) {
500 let mut args = Vec::new();
501 if !self.consume(&Token::RParen) {
502 args.push(self.parse_expr()?);
503 while self.consume(&Token::Comma) {
504 args.push(self.parse_expr()?);
505 }
506 if !self.consume(&Token::RParen) {
507 return Err(self.error_with_expected("expected ')' after indices", ")"));
508 }
509 }
510 base = Expr::Index(Box::new(base), args);
511 } else if self.consume(&Token::LBracket) {
512 let mut idxs = Vec::new();
513 idxs.push(self.parse_expr()?);
514 while self.consume(&Token::Comma) {
515 idxs.push(self.parse_expr()?);
516 }
517 if !self.consume(&Token::RBracket) {
518 return Err(self.error_with_expected("expected ']'", "]"));
519 }
520 base = Expr::Index(Box::new(base), idxs);
521 } else if self.consume(&Token::LBrace) {
522 let mut idxs = Vec::new();
523 idxs.push(self.parse_expr()?);
524 while self.consume(&Token::Comma) {
525 idxs.push(self.parse_expr()?);
526 }
527 if !self.consume(&Token::RBrace) {
528 return Err(self.error_with_expected("expected '}'", "}"));
529 }
530 base = Expr::IndexCell(Box::new(base), idxs);
531 } else if self.peek_token() == Some(&Token::Dot) {
532 if self.peek_token_at(1) == Some(&Token::Transpose) {
534 break;
535 }
536 if self.peek_token_at(1) == Some(&Token::Plus)
538 || self.peek_token_at(1) == Some(&Token::Minus)
539 {
540 break;
541 }
542 self.pos += 1; if self.consume(&Token::LParen) {
546 let name_expr = self.parse_expr()?;
547 if !self.consume(&Token::RParen) {
548 return Err(self.error_with_expected(
549 "expected ')' after dynamic field expression",
550 ")",
551 ));
552 }
553 base = Expr::MemberDynamic(Box::new(base), Box::new(name_expr));
554 } else {
555 let name = self.expect_ident()?;
556 base = Expr::Member(Box::new(base), name);
557 }
558 } else {
559 break;
560 }
561 }
562 base
563 } else {
564 self.pos = save;
565 return Ok(None);
566 };
567 if !self.consume(&Token::Assign) {
568 self.pos = save;
569 return Ok(None);
570 }
571 let rhs = self.parse_expr()?;
572 let stmt = match lvalue {
573 Expr::Member(b, name) => Stmt::AssignLValue(LValue::Member(b, name), rhs, false),
574 Expr::MemberDynamic(b, n) => {
575 Stmt::AssignLValue(LValue::MemberDynamic(b, n), rhs, false)
576 }
577 Expr::Index(b, idxs) => Stmt::AssignLValue(LValue::Index(b, idxs), rhs, false),
578 Expr::IndexCell(b, idxs) => Stmt::AssignLValue(LValue::IndexCell(b, idxs), rhs, false),
579 Expr::Ident(v) => Stmt::Assign(v, rhs, false),
580 _ => {
581 self.pos = save;
582 return Ok(None);
583 }
584 };
585 Ok(Some(stmt))
586 }
587
588 fn parse_expr(&mut self) -> Result<Expr, ParseError> {
589 self.parse_logical_or()
590 }
591
592 fn parse_logical_or(&mut self) -> Result<Expr, ParseError> {
593 let mut node = self.parse_logical_and()?;
594 while self.consume(&Token::OrOr) {
595 let rhs = self.parse_logical_and()?;
596 node = Expr::Binary(Box::new(node), BinOp::OrOr, Box::new(rhs));
597 }
598 Ok(node)
599 }
600
601 fn parse_logical_and(&mut self) -> Result<Expr, ParseError> {
602 let mut node = self.parse_bitwise_or()?;
603 while self.consume(&Token::AndAnd) {
604 let rhs = self.parse_bitwise_or()?;
605 node = Expr::Binary(Box::new(node), BinOp::AndAnd, Box::new(rhs));
606 }
607 Ok(node)
608 }
609
610 fn parse_bitwise_or(&mut self) -> Result<Expr, ParseError> {
611 let mut node = self.parse_bitwise_and()?;
612 while self.consume(&Token::Or) {
613 let rhs = self.parse_bitwise_and()?;
614 node = Expr::Binary(Box::new(node), BinOp::BitOr, Box::new(rhs));
615 }
616 Ok(node)
617 }
618
619 fn parse_bitwise_and(&mut self) -> Result<Expr, ParseError> {
620 let mut node = self.parse_range()?;
621 while self.consume(&Token::And) {
622 let rhs = self.parse_range()?;
623 node = Expr::Binary(Box::new(node), BinOp::BitAnd, Box::new(rhs));
624 }
625 Ok(node)
626 }
627
628 fn parse_range(&mut self) -> Result<Expr, ParseError> {
629 let mut node = self.parse_comparison()?;
630 if self.consume(&Token::Colon) {
631 let mid = self.parse_comparison()?;
632 if self.consume(&Token::Colon) {
633 let end = self.parse_comparison()?;
634 node = Expr::Range(Box::new(node), Some(Box::new(mid)), Box::new(end));
635 } else {
636 node = Expr::Range(Box::new(node), None, Box::new(mid));
637 }
638 }
639 Ok(node)
640 }
641
642 fn parse_comparison(&mut self) -> Result<Expr, ParseError> {
643 let mut node = self.parse_add_sub()?;
644 loop {
645 let op = match self.peek_token() {
646 Some(Token::Equal) => BinOp::Equal,
647 Some(Token::NotEqual) => BinOp::NotEqual,
648 Some(Token::Less) => BinOp::Less,
649 Some(Token::LessEqual) => BinOp::LessEqual,
650 Some(Token::Greater) => BinOp::Greater,
651 Some(Token::GreaterEqual) => BinOp::GreaterEqual,
652 _ => break,
653 };
654 self.pos += 1; let rhs = self.parse_add_sub()?;
656 node = Expr::Binary(Box::new(node), op, Box::new(rhs));
657 }
658 Ok(node)
659 }
660
661 fn parse_add_sub(&mut self) -> Result<Expr, String> {
662 let mut node = self.parse_mul_div()?;
663 loop {
664 let op = if self.consume(&Token::Plus) {
665 Some(BinOp::Add)
666 } else if self.consume(&Token::Minus) {
667 Some(BinOp::Sub)
668 } else if self.peek_token() == Some(&Token::Dot)
669 && (self.peek_token_at(1) == Some(&Token::Plus)
670 || self.peek_token_at(1) == Some(&Token::Minus))
671 {
672 self.pos += 2;
675 if self.tokens[self.pos - 1].token == Token::Plus {
676 Some(BinOp::Add)
677 } else {
678 Some(BinOp::Sub)
679 }
680 } else {
681 None
682 };
683 let Some(op) = op else { break };
684 let rhs = self.parse_mul_div()?;
685 node = Expr::Binary(Box::new(node), op, Box::new(rhs));
686 }
687 Ok(node)
688 }
689
690 fn parse_mul_div(&mut self) -> Result<Expr, String> {
691 let mut node = self.parse_unary()?;
692 loop {
693 let op = match self.peek_token() {
694 Some(Token::Star) => BinOp::Mul,
695 Some(Token::DotStar) => BinOp::ElemMul,
696 Some(Token::Slash) => BinOp::Div,
697 Some(Token::DotSlash) => BinOp::ElemDiv,
698 Some(Token::Backslash) => BinOp::LeftDiv,
699 Some(Token::DotBackslash) => BinOp::ElemLeftDiv,
700 _ => break,
701 };
702 self.pos += 1; let rhs = self.parse_unary()?;
704 node = Expr::Binary(Box::new(node), op, Box::new(rhs));
705 }
706 Ok(node)
707 }
708
709 fn parse_pow(&mut self) -> Result<Expr, String> {
710 let node = self.parse_postfix()?;
711 if let Some(token) = self.peek_token() {
712 let op = match token {
713 Token::Caret => BinOp::Pow,
714 Token::DotCaret => BinOp::ElemPow,
715 _ => return Ok(node),
716 };
717 self.pos += 1; let rhs = self.parse_pow()?; Ok(Expr::Binary(Box::new(node), op, Box::new(rhs)))
720 } else {
721 Ok(node)
722 }
723 }
724
725 fn parse_postfix_with_base(&mut self, mut expr: Expr) -> Result<Expr, String> {
726 loop {
727 if self.consume(&Token::LParen) {
728 let mut args = Vec::new();
729 if !self.consume(&Token::RParen) {
730 args.push(self.parse_expr()?);
731 while self.consume(&Token::Comma) {
732 args.push(self.parse_expr()?);
733 }
734 if !self.consume(&Token::RParen) {
735 return Err("expected ')' after arguments".into());
736 }
737 }
738 let has_index_hint = args.iter().any(|a| self.expr_suggests_indexing(a));
741 if has_index_hint {
742 expr = Expr::Index(Box::new(expr), args);
743 } else {
744 match expr {
745 Expr::Ident(ref name) => expr = Expr::FuncCall(name.clone(), args),
746 _ => expr = Expr::Index(Box::new(expr), args),
747 }
748 }
749 } else if self.consume(&Token::LBracket) {
750 let mut indices = Vec::new();
752 indices.push(self.parse_expr()?);
753 while self.consume(&Token::Comma) {
754 indices.push(self.parse_expr()?);
755 }
756 if !self.consume(&Token::RBracket) {
757 return Err("expected ']'".into());
758 }
759 expr = Expr::Index(Box::new(expr), indices);
760 } else if self.consume(&Token::LBrace) {
761 let mut indices = Vec::new();
763 indices.push(self.parse_expr()?);
764 while self.consume(&Token::Comma) {
765 indices.push(self.parse_expr()?);
766 }
767 if !self.consume(&Token::RBrace) {
768 return Err("expected '}'".into());
769 }
770 expr = Expr::IndexCell(Box::new(expr), indices);
771 } else if self.peek_token() == Some(&Token::Dot) {
772 if self.peek_token_at(1) == Some(&Token::Transpose) {
774 self.pos += 2; expr = Expr::Unary(UnOp::NonConjugateTranspose, Box::new(expr));
776 continue;
777 }
778 if self.peek_token_at(1) == Some(&Token::Plus)
779 || self.peek_token_at(1) == Some(&Token::Minus)
780 {
781 break;
783 }
784 self.pos += 1; let name = match self.next() {
787 Some(TokenInfo {
788 token: Token::Ident,
789 lexeme,
790 ..
791 }) => lexeme,
792 _ => return Err("expected member name after '.'".into()),
793 };
794 if self.consume(&Token::LParen) {
795 let mut args = Vec::new();
796 if !self.consume(&Token::RParen) {
797 args.push(self.parse_expr()?);
798 while self.consume(&Token::Comma) {
799 args.push(self.parse_expr()?);
800 }
801 if !self.consume(&Token::RParen) {
802 return Err("expected ')' after method arguments".into());
803 }
804 }
805 expr = Expr::MethodCall(Box::new(expr), name, args);
806 } else {
807 expr = Expr::Member(Box::new(expr), name);
808 }
809 } else if self.consume(&Token::Transpose) {
810 expr = Expr::Unary(UnOp::Transpose, Box::new(expr));
812 } else {
813 break;
814 }
815 }
816 Ok(expr)
817 }
818
819 fn parse_postfix(&mut self) -> Result<Expr, String> {
820 let expr = self.parse_primary()?;
821 self.parse_postfix_with_base(expr)
822 }
823
824 fn expr_suggests_indexing(&self, e: &Expr) -> bool {
825 match e {
826 Expr::Colon | Expr::EndKeyword | Expr::Range(_, _, _) => true,
827 Expr::Binary(_, op, _) => matches!(
828 op,
829 BinOp::Colon
830 | BinOp::Equal
831 | BinOp::NotEqual
832 | BinOp::Less
833 | BinOp::LessEqual
834 | BinOp::Greater
835 | BinOp::GreaterEqual
836 | BinOp::AndAnd
837 | BinOp::OrOr
838 | BinOp::BitAnd
839 | BinOp::BitOr
840 ),
841 _ => false,
842 }
843 }
844
845 fn parse_unary(&mut self) -> Result<Expr, String> {
846 if self.consume(&Token::Plus) {
847 Ok(Expr::Unary(UnOp::Plus, Box::new(self.parse_unary()?)))
848 } else if self.consume(&Token::Minus) {
849 Ok(Expr::Unary(UnOp::Minus, Box::new(self.parse_unary()?)))
850 } else if self.consume(&Token::Tilde) {
851 Ok(Expr::Unary(UnOp::Not, Box::new(self.parse_unary()?)))
852 } else if self.consume(&Token::Question) {
853 let mut parts: Vec<String> = Vec::new();
856 let first = self.expect_ident()?;
857 let class_consumed = first
858 .chars()
859 .next()
860 .map(|c| c.is_uppercase())
861 .unwrap_or(false);
862 parts.push(first);
863 while self.peek_token() == Some(&Token::Dot)
864 && matches!(self.peek_token_at(1), Some(Token::Ident))
865 {
866 let next_lex = if let Some(ti) = self.tokens.get(self.pos + 1) {
868 ti.lexeme.clone()
869 } else {
870 String::new()
871 };
872 let is_upper = next_lex
873 .chars()
874 .next()
875 .map(|c| c.is_uppercase())
876 .unwrap_or(false);
877 if class_consumed {
878 break;
879 }
880 self.pos += 1; let seg = self.expect_ident()?;
883 parts.push(seg);
884 if is_upper {
885 break;
886 }
887 }
888 let base = Expr::MetaClass(parts.join("."));
889 self.parse_postfix_with_base(base)
890 } else {
891 self.parse_pow()
892 }
893 }
894
895 fn parse_primary(&mut self) -> Result<Expr, String> {
896 match self.next() {
897 Some(info) => match info.token {
898 Token::Integer | Token::Float => Ok(Expr::Number(info.lexeme)),
899 Token::Str => Ok(Expr::String(info.lexeme)),
900 Token::True => Ok(Expr::Ident("true".into())),
901 Token::False => Ok(Expr::Ident("false".into())),
902 Token::Ident => Ok(Expr::Ident(info.lexeme)),
903 Token::End => Ok(Expr::EndKeyword),
905 Token::At => {
906 if self.consume(&Token::LParen) {
908 let mut params = Vec::new();
909 if !self.consume(&Token::RParen) {
910 params.push(self.expect_ident()?);
911 while self.consume(&Token::Comma) {
912 params.push(self.expect_ident()?);
913 }
914 if !self.consume(&Token::RParen) {
915 return Err(
916 "expected ')' after anonymous function parameters".into()
917 );
918 }
919 }
920 let body = self.parse_expr().map_err(|e| e.message)?;
921 Ok(Expr::AnonFunc {
922 params,
923 body: Box::new(body),
924 })
925 } else {
926 let name = self.expect_ident()?;
928 Ok(Expr::FuncHandle(name))
929 }
930 }
931 Token::LParen => {
932 let expr = self.parse_expr()?;
933 if !self.consume(&Token::RParen) {
934 return Err("expected ')' to close parentheses".into());
935 }
936 Ok(expr)
937 }
938 Token::LBracket => {
939 let matrix = self.parse_matrix()?;
940 if !self.consume(&Token::RBracket) {
941 return Err("expected ']' to close matrix literal".into());
942 }
943 Ok(matrix)
944 }
945 Token::LBrace => {
946 let cell = self.parse_cell()?;
947 if !self.consume(&Token::RBrace) {
948 return Err("expected '}' to close cell literal".into());
949 }
950 Ok(cell)
951 }
952 Token::Colon => Ok(Expr::Colon),
953 Token::ClassDef => {
954 self.pos -= 1;
956 Err("classdef in expression context".into())
957 }
958 _ => {
959 let token_desc = match info.token {
961 Token::Semicolon => "semicolon ';' (statement separator)",
962 Token::Comma => "comma ',' (list separator)",
963 Token::RParen => {
964 "closing parenthesis ')' (no matching opening parenthesis)"
965 }
966 Token::RBracket => "closing bracket ']' (no matching opening bracket)",
967 Token::If => "keyword 'if' (expected in statement context)",
968 Token::For => "keyword 'for' (expected in statement context)",
969 Token::While => "keyword 'while' (expected in statement context)",
970 Token::Function => "keyword 'function' (expected in statement context)",
971 Token::End => "keyword 'end' (no matching control structure)",
972 Token::Equal => "equality operator '==' (expected in comparison context)",
973 Token::Assign => "assignment operator '=' (expected in assignment context)",
974 Token::Error => "invalid character or symbol",
975 _ => {
976 return Err(format!(
977 "unexpected token '{}' in expression context",
978 info.lexeme
979 ))
980 }
981 };
982 Err(format!("unexpected {token_desc} in expression context"))
983 }
984 },
985 None => Err("unexpected end of input, expected expression".into()),
986 }
987 }
988
989 fn parse_matrix(&mut self) -> Result<Expr, String> {
990 let mut rows = Vec::new();
991 if self.peek_token() == Some(&Token::RBracket) {
992 return Ok(Expr::Tensor(rows));
993 }
994 loop {
995 let mut row = Vec::new();
996 row.push(self.parse_expr()?);
998 loop {
1000 if self.consume(&Token::Comma) {
1001 row.push(self.parse_expr()?);
1002 continue;
1003 }
1004 if matches!(
1006 self.peek_token(),
1007 Some(Token::Semicolon) | Some(Token::RBracket)
1008 ) {
1009 break;
1010 }
1011 match self.peek_token() {
1014 Some(
1015 Token::Ident
1016 | Token::Integer
1017 | Token::Float
1018 | Token::Str
1019 | Token::LParen
1020 | Token::LBracket
1021 | Token::LBrace
1022 | Token::At
1023 | Token::Plus
1024 | Token::Minus
1025 | Token::Colon
1026 | Token::True
1027 | Token::False,
1028 ) => {
1029 row.push(self.parse_expr()?);
1030 }
1031 _ => {
1032 break;
1033 }
1034 }
1035 }
1036 rows.push(row);
1037 if self.consume(&Token::Semicolon) {
1038 continue;
1039 } else {
1040 break;
1041 }
1042 }
1043 Ok(Expr::Tensor(rows))
1044 }
1045
1046 fn parse_if(&mut self) -> Result<Stmt, String> {
1047 self.consume(&Token::If);
1048 let cond = self.parse_expr()?;
1049 let then_body =
1050 self.parse_block(|t| matches!(t, Token::Else | Token::ElseIf | Token::End))?;
1051 let mut elseif_blocks = Vec::new();
1052 while self.consume(&Token::ElseIf) {
1053 let c = self.parse_expr()?;
1054 let body =
1055 self.parse_block(|t| matches!(t, Token::Else | Token::ElseIf | Token::End))?;
1056 elseif_blocks.push((c, body));
1057 }
1058 let else_body = if self.consume(&Token::Else) {
1059 Some(self.parse_block(|t| matches!(t, Token::End))?)
1060 } else {
1061 None
1062 };
1063 if !self.consume(&Token::End) {
1064 return Err("expected 'end'".into());
1065 }
1066 Ok(Stmt::If {
1067 cond,
1068 then_body,
1069 elseif_blocks,
1070 else_body,
1071 })
1072 }
1073
1074 fn parse_while(&mut self) -> Result<Stmt, String> {
1075 self.consume(&Token::While);
1076 let cond = self.parse_expr()?;
1077 let body = self.parse_block(|t| matches!(t, Token::End))?;
1078 if !self.consume(&Token::End) {
1079 return Err("expected 'end'".into());
1080 }
1081 Ok(Stmt::While { cond, body })
1082 }
1083
1084 fn parse_for(&mut self) -> Result<Stmt, String> {
1085 self.consume(&Token::For);
1086 let var = self.expect_ident()?;
1087 if !self.consume(&Token::Assign) {
1088 return Err("expected '='".into());
1089 }
1090 let expr = self.parse_expr()?;
1091 let body = self.parse_block(|t| matches!(t, Token::End))?;
1092 if !self.consume(&Token::End) {
1093 return Err("expected 'end'".into());
1094 }
1095 Ok(Stmt::For { var, expr, body })
1096 }
1097
1098 fn parse_function(&mut self) -> Result<Stmt, String> {
1099 self.consume(&Token::Function);
1100 let mut outputs = Vec::new();
1101 if self.consume(&Token::LBracket) {
1102 outputs.push(self.expect_ident_or_tilde()?);
1103 while self.consume(&Token::Comma) {
1104 outputs.push(self.expect_ident_or_tilde()?);
1105 }
1106 if !self.consume(&Token::RBracket) {
1107 return Err("expected ']'".into());
1108 }
1109 if !self.consume(&Token::Assign) {
1110 return Err("expected '='".into());
1111 }
1112 } else if self.peek_token() == Some(&Token::Ident)
1113 && self.peek_token_at(1) == Some(&Token::Assign)
1114 {
1115 outputs.push(self.next().unwrap().lexeme);
1116 self.consume(&Token::Assign);
1117 }
1118 let name = self.expect_ident()?;
1119 if !self.consume(&Token::LParen) {
1120 return Err("expected '('".into());
1121 }
1122 let mut params = Vec::new();
1123 if !self.consume(&Token::RParen) {
1124 params.push(self.expect_ident()?);
1125 while self.consume(&Token::Comma) {
1126 params.push(self.expect_ident()?);
1127 }
1128 if !self.consume(&Token::RParen) {
1129 return Err("expected ')'".into());
1130 }
1131 }
1132
1133 if let Some(idx) = params.iter().position(|p| p == "varargin") {
1136 if idx != params.len() - 1 {
1137 return Err("'varargin' must be the last input parameter".into());
1138 }
1139 if params.iter().filter(|p| p.as_str() == "varargin").count() > 1 {
1140 return Err("'varargin' cannot appear more than once".into());
1141 }
1142 }
1143 if let Some(idx) = outputs.iter().position(|o| o == "varargout") {
1145 if idx != outputs.len() - 1 {
1146 return Err("'varargout' must be the last output parameter".into());
1147 }
1148 if outputs.iter().filter(|o| o.as_str() == "varargout").count() > 1 {
1149 return Err("'varargout' cannot appear more than once".into());
1150 }
1151 }
1152
1153 if self.peek_token() == Some(&Token::Arguments) {
1156 self.pos += 1; loop {
1159 if self.consume(&Token::End) {
1160 break;
1161 }
1162 if self.consume(&Token::Semicolon) || self.consume(&Token::Comma) {
1163 continue;
1164 }
1165 if matches!(self.peek_token(), Some(Token::Ident)) {
1166 let _ = self.expect_ident()?;
1167 continue;
1168 }
1169 if self.peek_token().is_none() {
1171 break;
1172 }
1173 break;
1174 }
1175 }
1176
1177 let body = self.parse_block(|t| matches!(t, Token::End))?;
1178 if !self.consume(&Token::End) {
1179 return Err("expected 'end'".into());
1180 }
1181 Ok(Stmt::Function {
1182 name,
1183 params,
1184 outputs,
1185 body,
1186 })
1187 }
1188
1189 fn parse_block<F>(&mut self, term: F) -> Result<Vec<Stmt>, String>
1190 where
1191 F: Fn(&Token) -> bool,
1192 {
1193 let mut body = Vec::new();
1194 while let Some(tok) = self.peek_token() {
1195 if term(tok) {
1196 break;
1197 }
1198 if self.consume(&Token::Semicolon) || self.consume(&Token::Comma) {
1199 continue;
1200 }
1201 let stmt = self.parse_stmt().map_err(|e| e.message)?;
1202 let is_semicolon_terminated = self.consume(&Token::Semicolon);
1203
1204 let final_stmt = match stmt {
1206 Stmt::ExprStmt(expr, _) => Stmt::ExprStmt(expr, is_semicolon_terminated),
1207 Stmt::Assign(name, expr, _) => Stmt::Assign(name, expr, false),
1208 other => other,
1209 };
1210 body.push(final_stmt);
1211 }
1212 Ok(body)
1213 }
1214
1215 fn parse_cell(&mut self) -> Result<Expr, String> {
1216 let mut rows = Vec::new();
1217 if self.peek_token() == Some(&Token::RBrace) {
1218 return Ok(Expr::Cell(rows));
1219 }
1220 loop {
1221 let mut row = Vec::new();
1222 row.push(self.parse_expr()?);
1223 while self.consume(&Token::Comma) {
1224 row.push(self.parse_expr()?);
1225 }
1226 rows.push(row);
1227 if self.consume(&Token::Semicolon) {
1228 continue;
1229 } else {
1230 break;
1231 }
1232 }
1233 Ok(Expr::Cell(rows))
1234 }
1235
1236 fn parse_switch(&mut self) -> Result<Stmt, String> {
1237 self.consume(&Token::Switch);
1238 let control = self.parse_expr()?;
1239 let mut cases = Vec::new();
1240 let mut otherwise: Option<Vec<Stmt>> = None;
1241 loop {
1242 if self.consume(&Token::Case) {
1243 let val = self.parse_expr()?;
1244 let body =
1245 self.parse_block(|t| matches!(t, Token::Case | Token::Otherwise | Token::End))?;
1246 cases.push((val, body));
1247 } else if self.consume(&Token::Otherwise) {
1248 let body = self.parse_block(|t| matches!(t, Token::End))?;
1249 otherwise = Some(body);
1250 } else {
1251 break;
1252 }
1253 }
1254 if !self.consume(&Token::End) {
1255 return Err("expected 'end' for switch".into());
1256 }
1257 Ok(Stmt::Switch {
1258 expr: control,
1259 cases,
1260 otherwise,
1261 })
1262 }
1263
1264 fn parse_try_catch(&mut self) -> Result<Stmt, String> {
1265 self.consume(&Token::Try);
1266 let try_body = self.parse_block(|t| matches!(t, Token::Catch | Token::End))?;
1267 let (catch_var, catch_body) = if self.consume(&Token::Catch) {
1268 let maybe_ident = if let Some(Token::Ident) = self.peek_token() {
1269 Some(self.expect_ident()?)
1270 } else {
1271 None
1272 };
1273 let body = self.parse_block(|t| matches!(t, Token::End))?;
1274 (maybe_ident, body)
1275 } else {
1276 (None, Vec::new())
1277 };
1278 if !self.consume(&Token::End) {
1279 return Err("expected 'end' after try/catch".into());
1280 }
1281 Ok(Stmt::TryCatch {
1282 try_body,
1283 catch_var,
1284 catch_body,
1285 })
1286 }
1287
1288 fn parse_import(&mut self) -> Result<Stmt, String> {
1289 self.consume(&Token::Import);
1290 let mut path = Vec::new();
1292 path.push(self.expect_ident()?);
1293 let mut wildcard = false;
1294 loop {
1295 if self.consume(&Token::DotStar) {
1296 wildcard = true;
1297 break;
1298 }
1299 if self.consume(&Token::Dot) {
1300 if self.consume(&Token::Star) {
1301 wildcard = true;
1302 break;
1303 } else {
1304 path.push(self.expect_ident()?);
1305 continue;
1306 }
1307 }
1308 break;
1309 }
1310 Ok(Stmt::Import { path, wildcard })
1311 }
1312
1313 fn parse_classdef(&mut self) -> Result<Stmt, String> {
1314 self.consume(&Token::ClassDef);
1315 let name = self.parse_qualified_name()?;
1316 let mut super_class = None;
1317 if self.consume(&Token::Less) {
1318 super_class = Some(self.parse_qualified_name()?);
1319 }
1320 let mut members: Vec<ClassMember> = Vec::new();
1321 loop {
1322 if self.consume(&Token::Semicolon) || self.consume(&Token::Comma) {
1324 continue;
1325 }
1326 match self.peek_token() {
1327 Some(Token::Properties) => {
1328 self.pos += 1;
1329 let attrs = self.parse_optional_attr_list();
1330 let props = self.parse_properties_names_block()?;
1331 if !self.consume(&Token::End) {
1332 return Err("expected 'end' after properties".into());
1333 }
1334 members.push(ClassMember::Properties {
1335 attributes: attrs,
1336 names: props,
1337 });
1338 }
1339 Some(Token::Methods) => {
1340 self.pos += 1;
1341 let attrs = self.parse_optional_attr_list();
1342 let body = self.parse_block(|t| matches!(t, Token::End))?;
1343 if !self.consume(&Token::End) {
1344 return Err("expected 'end' after methods".into());
1345 }
1346 members.push(ClassMember::Methods {
1347 attributes: attrs,
1348 body,
1349 });
1350 }
1351 Some(Token::Events) => {
1352 self.pos += 1;
1353 let attrs = self.parse_optional_attr_list();
1354 let names = self.parse_name_block()?;
1355 if !self.consume(&Token::End) {
1356 return Err("expected 'end' after events".into());
1357 }
1358 members.push(ClassMember::Events {
1359 attributes: attrs,
1360 names,
1361 });
1362 }
1363 Some(Token::Enumeration) => {
1364 self.pos += 1;
1365 let attrs = self.parse_optional_attr_list();
1366 let names = self.parse_name_block()?;
1367 if !self.consume(&Token::End) {
1368 return Err("expected 'end' after enumeration".into());
1369 }
1370 members.push(ClassMember::Enumeration {
1371 attributes: attrs,
1372 names,
1373 });
1374 }
1375 Some(Token::Arguments) => {
1376 self.pos += 1;
1377 let attrs = self.parse_optional_attr_list();
1378 let names = self.parse_name_block()?;
1379 if !self.consume(&Token::End) {
1380 return Err("expected 'end' after arguments".into());
1381 }
1382 members.push(ClassMember::Arguments {
1383 attributes: attrs,
1384 names,
1385 });
1386 }
1387 Some(Token::End) => {
1388 self.pos += 1;
1389 break;
1390 }
1391 _ => break,
1392 }
1393 }
1394 Ok(Stmt::ClassDef {
1395 name,
1396 super_class,
1397 members,
1398 })
1399 }
1400
1401 fn parse_name_block(&mut self) -> Result<Vec<String>, String> {
1402 let mut names = Vec::new();
1403 while let Some(tok) = self.peek_token() {
1404 if matches!(tok, Token::End) {
1405 break;
1406 }
1407 if self.consume(&Token::Semicolon) || self.consume(&Token::Comma) {
1408 continue;
1409 }
1410 if let Some(Token::Ident) = self.peek_token() {
1411 names.push(self.expect_ident()?);
1412 } else {
1413 break;
1414 }
1415 }
1416 Ok(names)
1417 }
1418
1419 fn parse_properties_names_block(&mut self) -> Result<Vec<String>, String> {
1420 let mut names = Vec::new();
1422 while let Some(tok) = self.peek_token() {
1423 if matches!(tok, Token::End) {
1424 break;
1425 }
1426 if self.consume(&Token::Semicolon) || self.consume(&Token::Comma) {
1427 continue;
1428 }
1429 if let Some(Token::Ident) = self.peek_token() {
1430 names.push(self.expect_ident()?);
1431 if self.consume(&Token::Assign) {
1433 let _ = self.parse_expr().map_err(|e| e.message)?;
1435 }
1436 } else {
1437 break;
1438 }
1439 }
1440 Ok(names)
1441 }
1442
1443 fn parse_optional_attr_list(&mut self) -> Vec<Attr> {
1444 let mut attrs: Vec<Attr> = Vec::new();
1446 if !self.consume(&Token::LParen) {
1447 return attrs;
1448 }
1449 loop {
1450 if self.consume(&Token::RParen) {
1451 break;
1452 }
1453 match self.peek_token() {
1454 Some(Token::Ident) => {
1455 let name = self.expect_ident().unwrap_or_else(|_| "".to_string());
1456 let mut value: Option<String> = None;
1457 if self.consume(&Token::Assign) {
1458 if let Some(tok) = self.next() {
1460 value = Some(tok.lexeme);
1461 }
1462 }
1463 attrs.push(Attr { name, value });
1464 let _ = self.consume(&Token::Comma);
1465 }
1466 Some(Token::Comma) => {
1467 self.pos += 1;
1468 }
1469 Some(Token::RParen) => {
1470 self.pos += 1;
1471 break;
1472 }
1473 Some(_) => {
1474 self.pos += 1;
1475 }
1476 None => {
1477 break;
1478 }
1479 }
1480 }
1481 attrs
1482 }
1483
1484 fn parse_global(&mut self) -> Result<Stmt, String> {
1485 self.consume(&Token::Global);
1486 let mut names = Vec::new();
1487 names.push(self.expect_ident()?);
1488 loop {
1489 if self.consume(&Token::Comma) {
1490 names.push(self.expect_ident()?);
1491 continue;
1492 }
1493 if self.peek_token() == Some(&Token::Ident) {
1494 names.push(self.expect_ident()?);
1495 continue;
1496 }
1497 break;
1498 }
1499 Ok(Stmt::Global(names))
1500 }
1501
1502 fn parse_persistent(&mut self) -> Result<Stmt, String> {
1503 self.consume(&Token::Persistent);
1504 let mut names = Vec::new();
1505 names.push(self.expect_ident()?);
1506 loop {
1507 if self.consume(&Token::Comma) {
1508 names.push(self.expect_ident()?);
1509 continue;
1510 }
1511 if self.peek_token() == Some(&Token::Ident) {
1512 names.push(self.expect_ident()?);
1513 continue;
1514 }
1515 break;
1516 }
1517 Ok(Stmt::Persistent(names))
1518 }
1519
1520 fn try_parse_multi_assign(&mut self) -> Result<Stmt, String> {
1521 if !self.consume(&Token::LBracket) {
1522 return Err("not a multi-assign".into());
1523 }
1524 let mut names = Vec::new();
1525 names.push(self.expect_ident_or_tilde()?);
1526 while self.consume(&Token::Comma) {
1527 names.push(self.expect_ident_or_tilde()?);
1528 }
1529 if !self.consume(&Token::RBracket) {
1530 return Err("expected ']'".into());
1531 }
1532 if !self.consume(&Token::Assign) {
1533 return Err("expected '='".into());
1534 }
1535 let rhs = self.parse_expr().map_err(|e| e.message)?;
1536 Ok(Stmt::MultiAssign(names, rhs, false))
1537 }
1538
1539 fn parse_qualified_name(&mut self) -> Result<String, String> {
1540 let mut parts = Vec::new();
1541 parts.push(self.expect_ident()?);
1542 while self.consume(&Token::Dot) {
1543 parts.push(self.expect_ident()?);
1544 }
1545 Ok(parts.join("."))
1546 }
1547
1548 fn expect_ident(&mut self) -> Result<String, String> {
1549 match self.next() {
1550 Some(TokenInfo {
1551 token: Token::Ident,
1552 lexeme,
1553 ..
1554 }) => Ok(lexeme),
1555 _ => Err("expected identifier".into()),
1556 }
1557 }
1558
1559 fn expect_ident_or_tilde(&mut self) -> Result<String, String> {
1560 match self.next() {
1561 Some(TokenInfo {
1562 token: Token::Ident,
1563 lexeme,
1564 ..
1565 }) => Ok(lexeme),
1566 Some(TokenInfo {
1567 token: Token::Tilde,
1568 ..
1569 }) => Ok("~".to_string()),
1570 _ => Err("expected identifier or '~'".into()),
1571 }
1572 }
1573
1574 fn peek_token(&self) -> Option<&Token> {
1575 self.tokens.get(self.pos).map(|t| &t.token)
1576 }
1577
1578 fn peek_token_at(&self, offset: usize) -> Option<&Token> {
1579 self.tokens.get(self.pos + offset).map(|t| &t.token)
1580 }
1581
1582 fn next(&mut self) -> Option<TokenInfo> {
1583 if self.pos < self.tokens.len() {
1584 let info = self.tokens[self.pos].clone();
1585 self.pos += 1;
1586 Some(info)
1587 } else {
1588 None
1589 }
1590 }
1591
1592 fn consume(&mut self, t: &Token) -> bool {
1593 if self.peek_token() == Some(t) {
1594 self.pos += 1;
1595 true
1596 } else {
1597 false
1598 }
1599 }
1600}