basic/lang/
parse.rs

1use super::token::{self, Literal, Operator, Token, Word};
2use super::{ast::*, Column, Error, LineNumber, MaxValue};
3use crate::error;
4use std::collections::HashMap;
5
6type Result<T> = std::result::Result<T, Error>;
7
8const FN_RESERVED: &str = "FN RESERVED FOR FUNCTIONS";
9const ARRAY_NOT_ALLOWED: &str = "ARRAY NOT ALLOWED";
10const EXPECTED_VARIABLE: &str = "EXPECTED VARIABLE";
11
12pub fn parse(line_number: LineNumber, tokens: &[Token]) -> Result<Vec<Statement>> {
13    match BasicParser::parse(tokens) {
14        Err(e) => Err(e.in_line_number(line_number)),
15        Ok(r) => Ok(r),
16    }
17}
18
19struct BasicParser<'a> {
20    token_stream: std::slice::Iter<'a, Token>,
21    peeked: Option<&'a Token>,
22    rem: bool,
23    col: Column,
24}
25
26impl<'a> BasicParser<'a> {
27    fn parse(tokens: &'a [Token]) -> Result<Vec<Statement>> {
28        let mut parse = BasicParser {
29            token_stream: tokens.iter(),
30            peeked: None,
31            rem: false,
32            col: 0..0,
33        };
34        match parse.peek() {
35            Some(Token::Literal(Literal::Integer(_)))
36            | Some(Token::Literal(Literal::Single(_)))
37            | Some(Token::Literal(Literal::Double(_))) => {
38                return Err(error!(UndefinedLine, ..&parse.col; "INVALID LINE NUMBER"));
39            }
40            _ => {}
41        }
42        parse.expect_statements()
43    }
44
45    fn next(&mut self) -> Option<&'a Token> {
46        if self.peeked.is_some() {
47            return self.peeked.take();
48        }
49        loop {
50            self.col.start = self.col.end;
51            let token = self.token_stream.next()?;
52            if matches!(token, Token::Word(Word::Rem1) | Token::Word(Word::Rem2)) {
53                self.rem = true;
54            }
55            if self.rem {
56                continue;
57            }
58            self.col.end += token.to_string().chars().count();
59            match token {
60                Token::Whitespace(_) => continue,
61                _ => return Some(token),
62            }
63        }
64    }
65
66    fn peek(&mut self) -> Option<&&'a Token> {
67        if self.peeked.is_none() {
68            self.peeked = self.next();
69        }
70        self.peeked.as_ref()
71    }
72
73    fn expect_statements(&mut self) -> Result<Vec<Statement>> {
74        let mut statements: Vec<Statement> = vec![];
75        let mut expect_colon = false;
76        loop {
77            match self.peek() {
78                None | Some(Token::Word(Word::Else)) => return Ok(statements),
79                Some(Token::Colon) => {
80                    expect_colon = false;
81                    self.next();
82                    continue;
83                }
84                Some(_) => {
85                    if expect_colon {
86                        return Err(error!(SyntaxError, ..&self.col; "UNEXPECTED TOKEN"));
87                    }
88                    statements.push(Statement::expect(self)?);
89                    expect_colon = true;
90                }
91            }
92        }
93    }
94
95    fn expect_expression(&mut self) -> Result<Expression> {
96        self.expect_fn_expression(&HashMap::default())
97    }
98
99    fn expect_expression_list(&mut self) -> Result<Vec<Expression>> {
100        self.expect_fn_expression_list(&HashMap::default())
101    }
102
103    fn expect_fn_expression(
104        &mut self,
105        var_map: &HashMap<token::Ident, Variable>,
106    ) -> Result<Expression> {
107        Expression::expect(self, var_map)
108    }
109
110    fn expect_fn_expression_list(
111        &mut self,
112        var_map: &HashMap<token::Ident, Variable>,
113    ) -> Result<Vec<Expression>> {
114        let mut expressions: Vec<Expression> = vec![];
115        loop {
116            expressions.push(self.expect_fn_expression(var_map)?);
117            if self.maybe(Token::Comma) {
118                continue;
119            }
120            return Ok(expressions);
121        }
122    }
123
124    fn expect_print_list(&mut self) -> Result<Vec<Expression>> {
125        let mut expressions: Vec<Expression> = vec![];
126        let mut linefeed = true;
127        loop {
128            match self.peek() {
129                None | Some(Token::Colon) | Some(Token::Word(Word::Else)) => {
130                    let mut column = self.col.clone();
131                    column.start = column.end;
132                    if linefeed {
133                        expressions.push(Expression::String(column, "\n".into()));
134                    }
135                    return Ok(expressions);
136                }
137                Some(Token::Semicolon) => {
138                    linefeed = false;
139                    self.next();
140                }
141                Some(Token::Comma) => {
142                    linefeed = false;
143                    self.next();
144                    expressions.push(Expression::Variable(Variable::Array(
145                        self.col.clone(),
146                        Ident::String("TAB".into()),
147                        vec![Expression::Integer(self.col.clone(), -14)],
148                    )));
149                }
150                _ => {
151                    linefeed = true;
152                    expressions.push(self.expect_expression()?);
153                }
154            };
155        }
156    }
157
158    fn expect_ident(&mut self) -> Result<(Column, token::Ident)> {
159        let ident = if let Some(Token::Ident(ident)) = self.next() {
160            ident.clone()
161        } else {
162            return Err(error!(SyntaxError, ..&self.col; EXPECTED_VARIABLE));
163        };
164        let col = self.col.clone();
165        if ident.is_user_function() {
166            return Err(error!(SyntaxError, ..&col; FN_RESERVED));
167        }
168        if let Some(Token::LParen) = self.peek() {
169            return Err(error!(SyntaxError, ..&(col); ARRAY_NOT_ALLOWED));
170        }
171        Ok((col, ident))
172    }
173
174    fn expect_ident_list(&mut self) -> Result<Vec<(Column, token::Ident)>> {
175        let mut idents: Vec<(Column, token::Ident)> = vec![];
176        let mut expecting = false;
177        loop {
178            match self.peek() {
179                None | Some(Token::Colon) | Some(Token::Word(Word::Else)) if !expecting => break,
180                _ => idents.push(self.expect_ident()?),
181            };
182            if self.maybe(Token::Comma) {
183                expecting = true;
184            } else {
185                break;
186            }
187        }
188        Ok(idents)
189    }
190
191    fn expect_var(&mut self) -> Result<Variable> {
192        let ident = if let Some(Token::Ident(ident)) = self.next() {
193            ident.clone()
194        } else {
195            return Err(error!(SyntaxError, ..&self.col; EXPECTED_VARIABLE));
196        };
197        let col = self.col.clone();
198        if ident.is_user_function() {
199            return Err(error!(SyntaxError, ..&col; FN_RESERVED));
200        }
201        match self.peek() {
202            Some(Token::LParen) => {
203                self.expect(Token::LParen)?;
204                let vec_expr = self.expect_expression_list()?;
205                self.expect(Token::RParen)?;
206                Ok(Variable::Array(
207                    col.start..self.col.end,
208                    ident.into(),
209                    vec_expr,
210                ))
211            }
212            _ => Ok(Variable::Unary(col, ident.into())),
213        }
214    }
215
216    fn expect_var_list(&mut self) -> Result<Vec<Variable>> {
217        let mut vec_var: Vec<Variable> = vec![];
218        loop {
219            vec_var.push(self.expect_var()?);
220            if self.maybe(Token::Comma) {
221                continue;
222            }
223            break;
224        }
225        Ok(vec_var)
226    }
227
228    fn maybe_line_number(&mut self) -> Result<LineNumber> {
229        if let Some(str) = match self.peek() {
230            Some(Token::Literal(Literal::Integer(s))) => Some(s),
231            Some(Token::Literal(Literal::Single(s))) => Some(s),
232            Some(Token::Literal(Literal::Double(s))) => Some(s),
233            _ => None,
234        } {
235            self.next();
236            if let Ok(num) = str.parse::<u16>() {
237                if num <= LineNumber::max_value() {
238                    return Ok(Some(num));
239                }
240            }
241            return Err(error!(UndefinedLine, ..&self.col; "INVALID LINE NUMBER"));
242        }
243        Ok(None)
244    }
245
246    fn expect_line_number(&mut self) -> Result<Expression> {
247        match self.maybe_line_number()? {
248            Some(num) => Ok(Expression::Single(self.col.clone(), num as f32)),
249            None => Err(error!(SyntaxError, ..&self.col; "EXPECTED LINE NUMBER")),
250        }
251    }
252
253    fn expect_line_number_list(&mut self) -> Result<Vec<Expression>> {
254        let mut vars: Vec<Expression> = vec![];
255        let mut expecting = false;
256        loop {
257            match self.peek() {
258                None | Some(Token::Colon) | Some(Token::Word(Word::Else)) if !expecting => break,
259                _ => vars.push(self.expect_line_number()?),
260            };
261            if self.maybe(Token::Comma) {
262                expecting = true;
263            } else {
264                break;
265            }
266        }
267        Ok(vars)
268    }
269
270    fn expect_line_number_range(&mut self) -> Result<(Expression, Expression)> {
271        let from;
272        let from_num;
273        let to;
274        let mut to_num;
275        let col = self.col.clone();
276        if let Some(num) = self.maybe_line_number()? {
277            from_num = num as f32;
278            to_num = from_num;
279            from = Expression::Single(self.col.clone(), from_num);
280        } else {
281            from_num = 0.0;
282            to_num = LineNumber::max_value() as f32;
283            from = Expression::Single(self.col.start..self.col.start, from_num);
284        };
285        if self.maybe(Token::Operator(Operator::Minus)) {
286            if let Some(ln) = self.maybe_line_number()? {
287                to_num = ln as f32;
288                to = Expression::Single(self.col.clone(), to_num);
289            } else {
290                to_num = LineNumber::max_value() as f32;
291                to = Expression::Single(self.col.start..self.col.start, to_num);
292            }
293        } else {
294            to = Expression::Single(self.col.start..self.col.start, to_num);
295        }
296        if from_num > to_num {
297            return Err(error!(UndefinedLine, ..&(col.start..self.col.end); "INVALID RANGE"));
298        }
299        Ok((from, to))
300    }
301
302    fn expect_var_range(&mut self) -> Result<(Variable, Variable)> {
303        let (from_col, from_ident) = self.expect_ident()?;
304        let (to_col, to_ident) = if self.maybe(Token::Operator(Operator::Minus)) {
305            self.expect_ident()?
306        } else {
307            (from_col.clone(), from_ident.clone())
308        };
309        let from_char = match &from_ident {
310            token::Ident::Plain(s) if s.len() == 1 => s,
311            _ => return Err(error!(SyntaxError, ..&from_col)),
312        };
313        let to_char = match &to_ident {
314            token::Ident::Plain(s) if s.len() == 1 => s,
315            _ => return Err(error!(SyntaxError, ..&to_col)),
316        };
317        if from_char > to_char {
318            return Err(error!(SyntaxError, ..&(from_col.start..to_col.end)));
319        }
320        let from = Variable::Unary(from_col, from_ident.into());
321        let to = Variable::Unary(to_col, to_ident.into());
322        Ok((from, to))
323    }
324
325    fn maybe(&mut self, token: Token) -> bool {
326        if let Some(t) = self.peek() {
327            if **t == token {
328                self.next();
329                return true;
330            }
331        }
332        false
333    }
334
335    fn expect(&mut self, token: Token) -> Result<()> {
336        if let Some(t) = self.next() {
337            if *t == token {
338                return Ok(());
339            }
340        }
341        Err(error!(SyntaxError, ..&self.col;
342            match token {
343                Token::Unknown(_) | Token::Whitespace(_) => {"EXPECTED THE IMPOSSIBLE"}
344                Token::Literal(_) => {"EXPECTED LITERAL"}
345                Token::Word(Word::Then) => {"EXPECTED THEN"}
346                Token::Word(Word::To) => {"EXPECTED TO"}
347                Token::Word(_) => {"EXPECTED STATEMENT WORD"}
348                Token::Operator(Operator::Equal) => {"EXPECTED EQUALS SIGN"}
349                Token::Operator(_) => {"EXPECTED OPERATOR"}
350                Token::Ident(_) => {"EXPECTED IDENTIFIER"}
351                Token::LParen => {"EXPECTED LEFT PARENTHESIS"}
352                Token::RParen => {"EXPECTED RIGHT PARENTHESIS"}
353                Token::Comma => {"EXPECTED COMMA"}
354                Token::Colon => {"EXPECTED COLON"}
355                Token::Semicolon => {"EXPECTED SEMICOLON"}
356            }
357        ))
358    }
359}
360
361impl Expression {
362    fn expect(
363        parse: &mut BasicParser,
364        var_map: &HashMap<token::Ident, Variable>,
365    ) -> Result<Expression> {
366        fn descend(
367            parse: &mut BasicParser,
368            var_map: &HashMap<token::Ident, Variable>,
369            precedence: usize,
370        ) -> Result<Expression> {
371            let mut lhs = match parse.next() {
372                Some(Token::LParen) => {
373                    let expr = descend(parse, var_map, 0)?;
374                    parse.expect(Token::RParen)?;
375                    expr
376                }
377                Some(Token::Ident(tok_ident)) => {
378                    let ident = tok_ident.clone();
379                    let col = parse.col.clone();
380                    match parse.peek() {
381                        Some(&&Token::LParen) => {
382                            parse.expect(Token::LParen)?;
383                            let mut vec_expr = vec![];
384                            if !parse.maybe(Token::RParen) {
385                                vec_expr = parse.expect_fn_expression_list(var_map)?;
386                                parse.expect(Token::RParen)?;
387                            }
388                            let col = col.start..parse.col.end;
389                            Expression::Variable(Variable::Array(col, ident.into(), vec_expr))
390                        }
391                        _ => {
392                            if ident.is_user_function() {
393                                return Err(error!(SyntaxError, ..&col; FN_RESERVED));
394                            }
395                            match var_map.get(&ident) {
396                                Some(var) => Expression::Variable(var.clone()),
397                                None => Expression::Variable(Variable::Unary(col, ident.into())),
398                            }
399                        }
400                    }
401                }
402                Some(Token::Operator(Operator::Plus)) => {
403                    let op_prec = Expression::unary_op_precedence(&Operator::Plus)?;
404                    descend(parse, var_map, op_prec)?
405                }
406                Some(Token::Operator(Operator::Minus)) => {
407                    let col = parse.col.clone();
408                    let op_prec = Expression::unary_op_precedence(&Operator::Minus)?;
409                    let expr = descend(parse, var_map, op_prec)?;
410                    Expression::Negation(col, Box::new(expr))
411                }
412                Some(Token::Operator(Operator::Not)) => {
413                    let col = parse.col.clone();
414                    let op_prec = Expression::unary_op_precedence(&Operator::Not)?;
415                    let expr = descend(parse, var_map, op_prec)?;
416                    Expression::Not(col, Box::new(expr))
417                }
418                Some(Token::Literal(lit)) => Expression::literal(parse.col.clone(), lit)?,
419                _ => return Err(error!(SyntaxError, ..&parse.col; "EXPECTED EXPRESSION")),
420            };
421            let mut rhs;
422            while let Some(Token::Operator(op)) = parse.peek() {
423                let op_prec = Expression::binary_op_precedence(op)?;
424                if op_prec <= precedence {
425                    break;
426                }
427                parse.next();
428                let column = parse.col.clone();
429                rhs = descend(parse, var_map, op_prec)?;
430                lhs = Expression::binary_op(column, op, lhs, rhs)?;
431            }
432            Ok(lhs)
433        };
434        descend(parse, var_map, 0)
435    }
436
437    fn binary_op(
438        col: Column,
439        op: &Operator,
440        lhs: Expression,
441        rhs: Expression,
442    ) -> Result<Expression> {
443        use Operator::*;
444        Ok(match op {
445            Caret => Expression::Power(col, Box::new(lhs), Box::new(rhs)),
446            Multiply => Expression::Multiply(col, Box::new(lhs), Box::new(rhs)),
447            Divide => Expression::Divide(col, Box::new(lhs), Box::new(rhs)),
448            DivideInt => Expression::DivideInt(col, Box::new(lhs), Box::new(rhs)),
449            Modulo => Expression::Modulo(col, Box::new(lhs), Box::new(rhs)),
450            Plus => Expression::Add(col, Box::new(lhs), Box::new(rhs)),
451            Minus => Expression::Subtract(col, Box::new(lhs), Box::new(rhs)),
452            Equal => Expression::Equal(col, Box::new(lhs), Box::new(rhs)),
453            NotEqual => Expression::NotEqual(col, Box::new(lhs), Box::new(rhs)),
454            Less => Expression::Less(col, Box::new(lhs), Box::new(rhs)),
455            LessEqual => Expression::LessEqual(col, Box::new(lhs), Box::new(rhs)),
456            Greater => Expression::Greater(col, Box::new(lhs), Box::new(rhs)),
457            GreaterEqual => Expression::GreaterEqual(col, Box::new(lhs), Box::new(rhs)),
458            Not => return Err(error!(InternalError)),
459            And => Expression::And(col, Box::new(lhs), Box::new(rhs)),
460            Or => Expression::Or(col, Box::new(lhs), Box::new(rhs)),
461            Xor => Expression::Xor(col, Box::new(lhs), Box::new(rhs)),
462            Imp => Expression::Imp(col, Box::new(lhs), Box::new(rhs)),
463            Eqv => Expression::Eqv(col, Box::new(lhs), Box::new(rhs)),
464        })
465    }
466
467    fn unary_op_precedence(op: &Operator) -> Result<usize> {
468        use Operator::*;
469        Ok(match op {
470            Plus | Minus => 12,
471            Not => 6,
472            _ => 0,
473        })
474    }
475
476    fn binary_op_precedence(op: &Operator) -> Result<usize> {
477        use Operator::*;
478        Ok(match op {
479            Caret => 13,
480            // Unary identity and negation => 12
481            Multiply | Divide => 11,
482            DivideInt => 10,
483            Modulo => 9,
484            Plus | Minus => 8,
485            Equal | NotEqual | Less | LessEqual | Greater | GreaterEqual => 7,
486            // Unary not => 6
487            And => 5,
488            Or => 4,
489            Xor => 3,
490            Imp => 2,
491            Eqv => 1,
492            _ => 0,
493        })
494    }
495
496    fn literal(col: Column, lit: &Literal) -> Result<Expression> {
497        fn parse<T: std::str::FromStr>(col: Column, s: &str) -> Result<T> {
498            let mut s = String::from(s).replace("D", "E");
499            match s.chars().last() {
500                Some('!') | Some('#') | Some('%') => {
501                    s.pop();
502                }
503                _ => {}
504            };
505            match s.parse() {
506                Ok(num) => Ok(num),
507                Err(_) => Err(error!(TypeMismatch, ..&col)),
508            }
509        }
510        fn parse_radix(col: Column, src: &str, radix: u32) -> Result<Expression> {
511            match i16::from_str_radix(src, radix) {
512                Ok(num) => Ok(Expression::Integer(col, num)),
513                Err(_) => Err(error!(Overflow, ..&col)),
514            }
515        }
516        match lit {
517            Literal::Hex(s) => parse_radix(col, s, 16),
518            Literal::Octal(s) => parse_radix(col, s, 8),
519            Literal::Single(s) => Ok(Expression::Single(col.clone(), parse(col, s)?)),
520            Literal::Double(s) => Ok(Expression::Double(col.clone(), parse(col, s)?)),
521            Literal::Integer(s) => Ok(Expression::Integer(col.clone(), parse(col, s)?)),
522            Literal::String(s) => {
523                if s.chars().count() > 255 {
524                    Err(error!(StringTooLong, ..&col; "MAXIMUM LITERAL LENGTH IS 255"))
525                } else {
526                    Ok(Expression::String(col, s.clone().into()))
527                }
528            }
529        }
530    }
531}
532
533impl Statement {
534    #[allow(clippy::cognitive_complexity)]
535    fn expect(parse: &mut BasicParser) -> Result<Statement> {
536        match parse.peek() {
537            Some(Token::Ident(_)) => return Ok(Self::r#let(parse, true)?),
538            Some(Token::Word(word)) => {
539                parse.next();
540                use Word::*;
541                match word {
542                    Clear => return Ok(Self::r#clear(parse)?),
543                    Cls => return Ok(Self::r#cls(parse)?),
544                    Cont => return Ok(Self::r#cont(parse)?),
545                    Data => return Ok(Self::r#data(parse)?),
546                    Def => return Ok(Self::r#def(parse)?),
547                    Defdbl => return Ok(Self::r#defdbl(parse)?),
548                    Defint => return Ok(Self::r#defint(parse)?),
549                    Defsng => return Ok(Self::r#defsng(parse)?),
550                    Defstr => return Ok(Self::r#defstr(parse)?),
551                    Delete => return Ok(Self::r#delete(parse)?),
552                    Dim => return Ok(Self::r#dim(parse)?),
553                    End => return Ok(Self::r#end(parse)?),
554                    Erase => return Ok(Self::r#erase(parse)?),
555                    For => return Ok(Self::r#for(parse)?),
556                    Gosub => return Ok(Self::r#gosub(parse)?),
557                    Goto => return Ok(Self::r#goto(parse)?),
558                    If => return Ok(Self::r#if(parse)?),
559                    Input => return Ok(Self::r#input(parse)?),
560                    Let => return Ok(Self::r#let(parse, false)?),
561                    List => return Ok(Self::r#list(parse)?),
562                    Load => return Ok(Self::r#load(parse)?),
563                    New => return Ok(Self::r#new(parse)?),
564                    Next => return Ok(Self::r#next(parse)?),
565                    On => return Ok(Self::r#on(parse)?),
566                    Print => return Ok(Self::r#print(parse)?),
567                    Read => return Ok(Self::r#read(parse)?),
568                    Renum => return Ok(Self::r#renum(parse)?),
569                    Restore => return Ok(Self::r#restore(parse)?),
570                    Return => return Ok(Self::r#return(parse)?),
571                    Run => return Ok(Self::r#run(parse)?),
572                    Save => return Ok(Self::r#save(parse)?),
573                    Stop => return Ok(Self::r#stop(parse)?),
574                    Swap => return Ok(Self::r#swap(parse)?),
575                    Troff => return Ok(Self::r#troff(parse)?),
576                    Tron => return Ok(Self::r#tron(parse)?),
577                    Wend => return Ok(Self::r#wend(parse)?),
578                    While => return Ok(Self::r#while(parse)?),
579                    Else | Rem1 | Rem2 | Step | Then | To => {}
580                }
581            }
582            _ => {}
583        }
584        Err(error!(SyntaxError, ..&parse.col; "EXPECTED STATEMENT"))
585    }
586
587    fn r#clear(parse: &mut BasicParser) -> Result<Statement> {
588        let result = Ok(Statement::Clear(parse.col.clone()));
589        while match parse.peek() {
590            None | Some(Token::Colon) | Some(Token::Word(Word::Else)) => false,
591            _ => true,
592        } {
593            parse.next();
594        }
595        result
596    }
597
598    fn r#cls(parse: &mut BasicParser) -> Result<Statement> {
599        Ok(Statement::Cls(parse.col.clone()))
600    }
601
602    fn r#cont(parse: &mut BasicParser) -> Result<Statement> {
603        Ok(Statement::Cont(parse.col.clone()))
604    }
605
606    fn r#data(parse: &mut BasicParser) -> Result<Statement> {
607        let vec_expr = parse.expect_expression_list()?;
608        Ok(Statement::Data(parse.col.clone(), vec_expr))
609    }
610
611    fn r#def(parse: &mut BasicParser) -> Result<Statement> {
612        let column = parse.col.clone();
613        let fn_ident = if let Some(Token::Ident(ident)) = parse.next() {
614            ident.clone()
615        } else {
616            return Err(error!(SyntaxError, ..&parse.col; EXPECTED_VARIABLE));
617        };
618        if !fn_ident.is_user_function() {
619            return Err(error!(SyntaxError, ..&parse.col; "MUST START WITH FN"));
620        }
621        let fn_ident_col = parse.col.clone();
622        parse.expect(Token::LParen)?;
623        let mut ident_list = parse.expect_ident_list()?;
624        parse.expect(Token::RParen)?;
625        parse.expect(Token::Operator(Operator::Equal))?;
626        let mut var_map: HashMap<token::Ident, Variable> = HashMap::default();
627        let var_ident: Vec<Variable> = ident_list
628            .drain(..)
629            .map(|(tok_col, tok_ident)| {
630                let ast_ident = Ident::from((&fn_ident, &tok_ident));
631                var_map.insert(
632                    tok_ident,
633                    Variable::Unary(tok_col.clone(), ast_ident.clone()),
634                );
635                Variable::Unary(tok_col, ast_ident)
636            })
637            .collect();
638        let expr = parse.expect_fn_expression(&var_map)?;
639        let var = Variable::Unary(fn_ident_col, fn_ident.into());
640        Ok(Statement::Def(column, var, var_ident, expr))
641    }
642
643    fn r#defdbl(parse: &mut BasicParser) -> Result<Statement> {
644        let (from, to) = parse.expect_var_range()?;
645        Ok(Statement::Defdbl(parse.col.clone(), from, to))
646    }
647
648    fn r#defint(parse: &mut BasicParser) -> Result<Statement> {
649        let (from, to) = parse.expect_var_range()?;
650        Ok(Statement::Defint(parse.col.clone(), from, to))
651    }
652
653    fn r#defsng(parse: &mut BasicParser) -> Result<Statement> {
654        let (from, to) = parse.expect_var_range()?;
655        Ok(Statement::Defsng(parse.col.clone(), from, to))
656    }
657
658    fn r#defstr(parse: &mut BasicParser) -> Result<Statement> {
659        let (from, to) = parse.expect_var_range()?;
660        Ok(Statement::Defstr(parse.col.clone(), from, to))
661    }
662
663    fn r#delete(parse: &mut BasicParser) -> Result<Statement> {
664        let column = parse.col.clone();
665        let (from, to) = parse.expect_line_number_range()?;
666        Ok(Statement::Delete(column, from, to))
667    }
668
669    fn r#dim(parse: &mut BasicParser) -> Result<Statement> {
670        let column = parse.col.clone();
671        let var_list = parse.expect_var_list()?;
672        Ok(Statement::Dim(column, var_list))
673    }
674
675    fn r#end(parse: &mut BasicParser) -> Result<Statement> {
676        Ok(Statement::End(parse.col.clone()))
677    }
678
679    fn r#erase(parse: &mut BasicParser) -> Result<Statement> {
680        let column = parse.col.clone();
681        let mut idents = parse.expect_ident_list()?;
682        if idents.is_empty() {
683            return Err(error!(SyntaxError, ..&(column.start..column.start); "EXPECTED VARIABLE"));
684        }
685        let vec_var = idents
686            .drain(..)
687            .map(|(col, i)| Variable::Unary(col, i.into()))
688            .collect::<Vec<Variable>>();
689        Ok(Statement::Erase(column, vec_var))
690    }
691
692    fn r#for(parse: &mut BasicParser) -> Result<Statement> {
693        let column = parse.col.clone();
694        let (ident_col, ident) = parse.expect_ident()?;
695        let var = Variable::Unary(ident_col, ident.into());
696        parse.expect(Token::Operator(Operator::Equal))?;
697        let expr_from = parse.expect_expression()?;
698        parse.expect(Token::Word(Word::To))?;
699        let expr_to = parse.expect_expression()?;
700        let expr_step = if parse.maybe(Token::Word(Word::Step)) {
701            parse.expect_expression()?
702        } else {
703            Expression::Integer(parse.col.end..parse.col.end, 1)
704        };
705        Ok(Statement::For(column, var, expr_from, expr_to, expr_step))
706    }
707
708    fn r#gosub(parse: &mut BasicParser) -> Result<Statement> {
709        Ok(Statement::Gosub(
710            parse.col.clone(),
711            parse.expect_line_number()?,
712        ))
713    }
714
715    fn r#goto(parse: &mut BasicParser) -> Result<Statement> {
716        Ok(Statement::Goto(
717            parse.col.clone(),
718            parse.expect_line_number()?,
719        ))
720    }
721
722    fn r#if(parse: &mut BasicParser) -> Result<Statement> {
723        let column = parse.col.clone();
724        let predicate = parse.expect_expression()?;
725        let then_stmt = if parse.maybe(Token::Word(Word::Goto)) {
726            vec![Statement::Goto(
727                parse.col.clone(),
728                parse.expect_line_number()?,
729            )]
730        } else {
731            parse.expect(Token::Word(Word::Then))?;
732            match parse.maybe_line_number()? {
733                Some(n) => vec![Statement::Goto(
734                    column.clone(),
735                    Expression::Single(parse.col.clone(), n as f32),
736                )],
737                None => parse.expect_statements()?,
738            }
739        };
740        let else_stmt = if parse.maybe(Token::Word(Word::Else)) {
741            match parse.maybe_line_number()? {
742                Some(n) => vec![Statement::Goto(
743                    column.clone(),
744                    Expression::Single(parse.col.clone(), n as f32),
745                )],
746                None => parse.expect_statements()?,
747            }
748        } else {
749            vec![]
750        };
751        Ok(Statement::If(column, predicate, then_stmt, else_stmt))
752    }
753
754    fn r#input(parse: &mut BasicParser) -> Result<Statement> {
755        let column = parse.col.clone();
756        let mut prompt_col = column.end..column.end;
757        let caps = if let Some(Token::Comma) = parse.peek() {
758            parse.next();
759            Expression::Integer(parse.col.clone(), 0)
760        } else {
761            Expression::Integer(parse.col.start..parse.col.start, -1)
762        };
763        let prompt = match parse.peek() {
764            Some(Token::Literal(Literal::String(s))) => {
765                parse.next();
766                prompt_col = parse.col.clone();
767                match parse.peek() {
768                    None | Some(Token::Colon) | Some(Token::Word(Word::Else)) => {}
769                    Some(Token::Semicolon) => {
770                        parse.next();
771                    }
772                    _ => {
773                        return Err(error!(SyntaxError, ..&parse.col.clone(); "UNEXPECTED TOKEN"));
774                    }
775                }
776                s.clone()
777            }
778            _ => String::new(),
779        };
780        let var_list = parse.expect_var_list()?;
781        Ok(Statement::Input(
782            column,
783            caps,
784            Expression::String(prompt_col, prompt.into()),
785            var_list,
786        ))
787    }
788
789    fn r#let(parse: &mut BasicParser, is_shortcut: bool) -> Result<Statement> {
790        let column = parse.col.clone();
791        if let Some(Token::Ident(token::Ident::String(s))) = parse.peek() {
792            if s == "MID$" {
793                parse.next();
794                parse.expect(Token::LParen)?;
795                let var = parse.expect_var()?;
796                parse.expect(Token::Comma)?;
797                let pos = parse.expect_expression()?;
798                let len = if parse.maybe(Token::Comma) {
799                    parse.expect_expression()?
800                } else {
801                    Expression::Integer(parse.col.start..parse.col.start, i16::max_value())
802                };
803                parse.expect(Token::RParen)?;
804                parse.expect(Token::Operator(Operator::Equal))?;
805                let expr = parse.expect_expression()?;
806                return Ok(Statement::Mid(column, var, pos, len, expr));
807            }
808        }
809        let var = parse.expect_var()?;
810        match parse.next() {
811            Some(Token::Operator(Operator::Equal)) => {
812                Ok(Statement::Let(column, var, parse.expect_expression()?))
813            }
814            _ => {
815                if is_shortcut {
816                    Err(error!(SyntaxError, ..&column; "UNKNOWN STATEMENT"))
817                } else {
818                    Err(error!(SyntaxError, ..&parse.col; "EXPECTED EQUALS SIGN"))
819                }
820            }
821        }
822    }
823
824    fn r#list(parse: &mut BasicParser) -> Result<Statement> {
825        let column = parse.col.clone();
826        let (from, to) = parse.expect_line_number_range()?;
827        Ok(Statement::List(column, from, to))
828    }
829
830    fn r#load(parse: &mut BasicParser) -> Result<Statement> {
831        Ok(Statement::Load(
832            parse.col.clone(),
833            parse.expect_expression()?,
834        ))
835    }
836
837    fn r#new(parse: &mut BasicParser) -> Result<Statement> {
838        Ok(Statement::New(parse.col.clone()))
839    }
840
841    fn r#next(parse: &mut BasicParser) -> Result<Statement> {
842        let column = parse.col.clone();
843        let mut idents = parse.expect_ident_list()?;
844        if idents.is_empty() {
845            return Ok(Statement::Next(
846                column,
847                vec![Variable::Unary(0..0, Ident::Plain("".into()))],
848            ));
849        }
850        let vec_var = idents
851            .drain(..)
852            .map(|(col, i)| Variable::Unary(col, i.into()))
853            .collect::<Vec<Variable>>();
854
855        Ok(Statement::Next(column, vec_var))
856    }
857
858    fn r#on(parse: &mut BasicParser) -> Result<Statement> {
859        let column = parse.col.clone();
860        let expr = parse.expect_expression()?;
861        match parse.next() {
862            Some(Token::Word(Word::Goto)) => Ok(Statement::OnGoto(
863                column,
864                expr,
865                parse.expect_line_number_list()?,
866            )),
867            Some(Token::Word(Word::Gosub)) => Ok(Statement::OnGosub(
868                column,
869                expr,
870                parse.expect_line_number_list()?,
871            )),
872            _ => Err(error!(SyntaxError, ..&parse.col; "EXPECTED GOTO OR GOSUB")),
873        }
874    }
875
876    fn r#print(parse: &mut BasicParser) -> Result<Statement> {
877        let column = parse.col.clone();
878        let vec_expr = parse.expect_print_list()?;
879        Ok(Statement::Print(column, vec_expr))
880    }
881
882    fn r#read(parse: &mut BasicParser) -> Result<Statement> {
883        Ok(Statement::Read(parse.col.clone(), parse.expect_var_list()?))
884    }
885
886    fn r#renum(parse: &mut BasicParser) -> Result<Statement> {
887        fn parse_start(parse: &mut BasicParser, default: f32) -> Result<Expression> {
888            if parse.maybe(Token::Comma) {
889                Ok(Expression::Single(parse.col.clone(), default))
890            } else {
891                match parse.peek() {
892                    None | Some(Token::Colon) | Some(Token::Word(Word::Else)) => Ok(
893                        Expression::Single(parse.col.start..parse.col.start, default),
894                    ),
895                    _ => {
896                        let ln = parse.expect_line_number()?;
897                        parse.maybe(Token::Comma);
898                        Ok(ln)
899                    }
900                }
901            }
902        }
903        let column = parse.col.clone();
904        let new_start = parse_start(parse, 10.0)?;
905        let old_start = parse_start(parse, 0.0)?;
906        let step = match parse.peek() {
907            None | Some(Token::Colon) | Some(Token::Word(Word::Else)) => {
908                Expression::Single(parse.col.start..parse.col.start, 10.0)
909            }
910            _ => parse.expect_line_number()?,
911        };
912        Ok(Statement::Renum(column, new_start, old_start, step))
913    }
914
915    fn r#restore(parse: &mut BasicParser) -> Result<Statement> {
916        let num = if let Some(num) = parse.maybe_line_number()? {
917            num as f32
918        } else {
919            -1.0
920        };
921        Ok(Statement::Restore(
922            parse.col.clone(),
923            Expression::Single(parse.col.clone(), num as f32),
924        ))
925    }
926
927    fn r#return(parse: &mut BasicParser) -> Result<Statement> {
928        Ok(Statement::Return(parse.col.clone()))
929    }
930
931    fn r#run(parse: &mut BasicParser) -> Result<Statement> {
932        let column = parse.col.clone();
933        if let Some(Token::Literal(Literal::String(s))) = parse.peek() {
934            parse.next();
935            Ok(Statement::Run(
936                column,
937                Expression::String(parse.col.clone(), s.clone().into()),
938            ))
939        } else if let Some(num) = parse.maybe_line_number()? {
940            Ok(Statement::Run(
941                column,
942                Expression::Single(parse.col.clone(), num as f32),
943            ))
944        } else {
945            let empty = parse.col.clone();
946            let empty = empty.start..empty.start;
947            Ok(Statement::Run(column, Expression::Single(empty, -1.0)))
948        }
949    }
950
951    fn r#save(parse: &mut BasicParser) -> Result<Statement> {
952        Ok(Statement::Save(
953            parse.col.clone(),
954            parse.expect_expression()?,
955        ))
956    }
957
958    fn r#stop(parse: &mut BasicParser) -> Result<Statement> {
959        Ok(Statement::Stop(parse.col.clone()))
960    }
961
962    fn r#swap(parse: &mut BasicParser) -> Result<Statement> {
963        let col = parse.col.clone();
964        let mut var_list = parse.expect_var_list()?;
965        if var_list.len() != 2 {
966            return Err(
967                error!(SyntaxError, ..&(col.start..parse.col.end); "EXPECTED TWO VARIABLES" ),
968            );
969        }
970        Ok(Statement::Swap(
971            col,
972            var_list.pop().unwrap(),
973            var_list.pop().unwrap(),
974        ))
975    }
976
977    fn r#troff(parse: &mut BasicParser) -> Result<Statement> {
978        Ok(Statement::Troff(parse.col.clone()))
979    }
980
981    fn r#tron(parse: &mut BasicParser) -> Result<Statement> {
982        Ok(Statement::Tron(parse.col.clone()))
983    }
984
985    fn r#wend(parse: &mut BasicParser) -> Result<Statement> {
986        Ok(Statement::Wend(parse.col.clone()))
987    }
988
989    fn r#while(parse: &mut BasicParser) -> Result<Statement> {
990        Ok(Statement::While(
991            parse.col.clone(),
992            parse.expect_expression()?,
993        ))
994    }
995}
996
997impl From<token::Ident> for Ident {
998    fn from(ident: token::Ident) -> Self {
999        use token::Ident::*;
1000        match ident {
1001            Plain(s) => Ident::Plain(s.into()),
1002            String(s) => Ident::String(s.into()),
1003            Single(s) => Ident::Single(s.into()),
1004            Double(s) => Ident::Double(s.into()),
1005            Integer(s) => Ident::Integer(s.into()),
1006        }
1007    }
1008}
1009
1010impl From<(&token::Ident, &token::Ident)> for Ident {
1011    fn from(f: (&token::Ident, &token::Ident)) -> Self {
1012        let mut string = match f.0 {
1013            token::Ident::Plain(s) => s,
1014            token::Ident::String(s) => s,
1015            token::Ident::Single(s) => s,
1016            token::Ident::Double(s) => s,
1017            token::Ident::Integer(s) => s,
1018        }
1019        .to_string();
1020        string.push('.');
1021        match f.1 {
1022            token::Ident::Plain(s) => Ident::Plain({
1023                string.push_str(&s);
1024                string.into()
1025            }),
1026            token::Ident::String(s) => Ident::String({
1027                string.push_str(&s);
1028                string.into()
1029            }),
1030            token::Ident::Single(s) => Ident::Single({
1031                string.push_str(&s);
1032                string.into()
1033            }),
1034            token::Ident::Double(s) => Ident::Double({
1035                string.push_str(&s);
1036                string.into()
1037            }),
1038            token::Ident::Integer(s) => Ident::Integer({
1039                string.push_str(&s);
1040                string.into()
1041            }),
1042        }
1043    }
1044}
1045
1046impl token::Ident {
1047    fn is_user_function(&self) -> bool {
1048        use token::Ident::*;
1049        match self {
1050            Plain(s) => s,
1051            String(s) => s,
1052            Single(s) => s,
1053            Double(s) => s,
1054            Integer(s) => s,
1055        }
1056        .starts_with("FN")
1057    }
1058}