b2c2_parser/
lib.rs

1// b2c2-parser crate
2// author: Leonardone @ NEETSDKASU
3
4use b2c2_casl2::IndexRegister;
5use b2c2_common::*;
6use b2c2_compiler_common::*;
7use b2c2_tokenizer::*;
8use std::collections::HashMap;
9use std::convert::TryFrom;
10use std::io::{self, BufRead};
11
12#[cfg(test)]
13mod test;
14
15pub fn parse<R: BufRead>(reader: R) -> io::Result<Result<Vec<Statement>, SyntaxError>> {
16    let mut parser = Parser::new();
17
18    for line in Tokenizer::new(reader) {
19        let (line_number, pos_and_tokens) = match line? {
20            Ok(values) => values,
21            Err(error) => return Ok(Err(error)),
22        };
23        parser.line_number = line_number;
24
25        match pos_and_tokens.first() {
26            None => continue,
27            Some((pos, Token::Name(name))) => {
28                // bind (assign) statement
29                parser.line_start_position = *pos;
30                if let Err(error) = parser.parse_assign(name, &pos_and_tokens[1..]) {
31                    return Ok(Err(error));
32                }
33            }
34            Some((pos, Token::Keyword(keyword))) if keyword.is_toplevel_token() => {
35                // command statement
36                parser.line_start_position = *pos;
37                if let Err(error) = parser.parse_command(keyword, &pos_and_tokens[1..]) {
38                    return Ok(Err(error));
39                }
40            }
41            Some((pos, token)) => {
42                return Ok(Err(SyntaxError::new(
43                    line_number,
44                    *pos,
45                    format!("不適切なトークンです: {:?}", token),
46                )))
47            }
48        }
49    }
50
51    if !parser.is_valid_allocation() {
52        return Ok(Err(SyntaxError::new(
53            parser.line_number + 1,
54            0,
55            format!(
56                "指定のアロケーションサイズが小さすぎます: {} / {}",
57                parser.variable_area_size + parser.maximum_allocate_temporary_area_size,
58                parser.maximum_variable_area_size
59            ),
60        )));
61    }
62
63    if !parser.is_valid() {
64        return Ok(Err(SyntaxError::new(
65            parser.line_number + 1,
66            0,
67            "不完全なソースコードのため正しく解釈できませんでした".into(),
68        )));
69    }
70
71    Ok(Ok(parser.statements.pop().unwrap()))
72}
73
74#[derive(PartialEq, Eq, Clone, Copy, Debug)]
75enum EndProgramState {
76    Unnecessary,
77    Required,
78    Satisfied,
79}
80
81#[derive(PartialEq, Eq, Clone, Copy, Debug)]
82enum HeaderState {
83    Option,
84    ExternSub,
85    InExternSub,
86    Argument,
87    InArgument,
88    Dim,
89    NotHeader,
90}
91
92impl HeaderState {
93    fn in_header(self) -> bool {
94        !matches!(self, HeaderState::NotHeader)
95    }
96
97    fn in_defininition(self) -> bool {
98        self.in_extern_sub() || self.in_argument()
99    }
100
101    fn in_extern_sub(self) -> bool {
102        matches!(self, HeaderState::InExternSub)
103    }
104
105    fn in_argument(self) -> bool {
106        matches!(self, HeaderState::InArgument)
107    }
108
109    fn can_option(self) -> bool {
110        matches!(self, HeaderState::Option)
111    }
112
113    fn can_extern_sub(self) -> bool {
114        use HeaderState::*;
115        matches!(self, Option | ExternSub)
116    }
117
118    fn can_program_name(self) -> bool {
119        use HeaderState::*;
120        matches!(self, Option | ExternSub)
121    }
122
123    fn can_argument(self) -> bool {
124        use HeaderState::*;
125        matches!(self, Option | ExternSub | Argument)
126    }
127
128    fn can_dim(self) -> bool {
129        use HeaderState::*;
130        matches!(self, Option | ExternSub | Argument | Dim)
131    }
132
133    fn can_command(self) -> bool {
134        use HeaderState::*;
135        matches!(self, Option | ExternSub | Argument | Dim | NotHeader)
136    }
137}
138
139struct Parser {
140    line_number: usize,
141    line_start_position: usize,
142    variables: HashMap<String, VarType>,
143    statements: Vec<Vec<Statement>>,
144    nest_of_do: Vec<usize>,
145    nest_of_for: Vec<(usize, String)>,
146    nest_of_select: Vec<usize>,
147    provisionals: Vec<Statement>,
148    exit_id: usize,
149    is_select_head: bool,
150    header_state: HeaderState,
151    temp_argumets: Vec<ArgumentInfo>,
152    temp_progam_name: Option<String>,
153    callables: HashMap<String, Vec<ArgumentInfo>>,
154    end_program_state: EndProgramState,
155    in_call_with: bool,
156    temp_call_with_arguments: Vec<(String, Expr)>,
157    declare_array_with_length: Option<bool>,
158    use_bound_for_array_function: bool,
159    maximum_variable_area_size: usize,
160    variable_area_size: usize,
161    maximum_allocate_temporary_area_size: usize,
162    allocate_temporary_area_size: usize,
163}
164
165impl Parser {
166    fn new() -> Self {
167        Self {
168            line_number: 0,
169            line_start_position: 0,
170            variables: HashMap::new(),
171            statements: vec![vec![]; 1],
172            nest_of_do: Vec::new(),
173            nest_of_for: Vec::new(),
174            nest_of_select: Vec::new(),
175            provisionals: Vec::new(),
176            exit_id: 0,
177            is_select_head: false,
178            header_state: HeaderState::Option,
179            temp_argumets: Vec::new(),
180            temp_progam_name: None,
181            callables: HashMap::new(),
182            end_program_state: EndProgramState::Unnecessary,
183            in_call_with: false,
184            temp_call_with_arguments: Vec::new(),
185            declare_array_with_length: None,
186            use_bound_for_array_function: false,
187            maximum_variable_area_size: MAX_ALLOCATION_SIZE,
188            variable_area_size: 0,
189            maximum_allocate_temporary_area_size: 0,
190            allocate_temporary_area_size: 0,
191        }
192    }
193
194    fn is_valid_allocation(&self) -> bool {
195        self.variable_area_size + self.maximum_allocate_temporary_area_size
196            <= self.maximum_variable_area_size
197    }
198
199    fn parse_size_for_array_function(&self, size: usize, value: i32) -> Option<usize> {
200        if self.use_bound_for_array_function {
201            if (0..size as i32).contains(&value) {
202                Some(value as usize + 1)
203            } else {
204                None
205            }
206        } else if (1..=size as i32).contains(&value) {
207            Some(value as usize)
208        } else {
209            None
210        }
211    }
212
213    fn parse_declare_array_size(&self, value: i32) -> Option<usize> {
214        if let Some(true) = self.declare_array_with_length {
215            if (1..=MAX_ARRAY_SIZE as i32).contains(&value) {
216                Some(value as usize)
217            } else {
218                None
219            }
220        } else if (0..MAX_ARRAY_SIZE as i32).contains(&value) {
221            Some(value as usize + 1)
222        } else {
223            None
224        }
225    }
226
227    fn is_valid(&self) -> bool {
228        self.statements.len() == 1
229            && self.nest_of_do.is_empty()
230            && self.nest_of_for.is_empty()
231            && self.nest_of_select.is_empty()
232            && self.provisionals.is_empty()
233            && !self.is_select_head
234            && self.header_state.can_command()
235            && !matches!(self.end_program_state, EndProgramState::Required)
236            && !self.in_call_with
237    }
238
239    fn can_end_program(&self) -> bool {
240        self.statements.len() == 1
241            && self.nest_of_do.is_empty()
242            && self.nest_of_for.is_empty()
243            && self.nest_of_select.is_empty()
244            && self.provisionals.is_empty()
245            && !self.is_select_head
246            && self.header_state.can_command()
247            && matches!(self.end_program_state, EndProgramState::Required)
248            && !self.in_call_with
249    }
250
251    fn get_new_exit_id(&mut self) -> usize {
252        let id = self.exit_id;
253        self.exit_id += 1;
254        id
255    }
256
257    fn syntax_error_pos(&self, position: usize, message: String) -> SyntaxError {
258        SyntaxError::new(self.line_number, position, message)
259    }
260
261    fn syntax_error(&self, message: String) -> SyntaxError {
262        SyntaxError::new(self.line_number, self.line_start_position, message)
263    }
264
265    fn add_statement(&mut self, statement: Statement) {
266        self.statements.last_mut().unwrap().push(statement);
267    }
268
269    // Assign Variable
270    fn parse_assign(
271        &mut self,
272        name: &str,
273        pos_and_tokens: &[(usize, Token)],
274    ) -> Result<(), SyntaxError> {
275        if matches!(self.end_program_state, EndProgramState::Satisfied) {
276            return Err(self.syntax_error("この位置に代入のステートメントは置けません".into()));
277        }
278
279        if self.in_call_with {
280            return self.parse_assign_argument(name, pos_and_tokens);
281        }
282
283        if self.is_select_head {
284            return Err(self.syntax_error("この位置に代入のステートメントは置けません".into()));
285        }
286
287        if !self.header_state.can_command() {
288            return Err(self.syntax_error("この位置に代入のステートメントは置けません".into()));
289        } else if self.header_state.in_header() {
290            if let Some(name) = self.temp_progam_name.take() {
291                self.callables.insert(name, Vec::new());
292            }
293            self.header_state = HeaderState::NotHeader;
294        }
295
296        let var_type =
297            self.variables.get(name).cloned().ok_or_else(|| {
298                self.syntax_error(format!("宣言されていない変数名です: {}", name))
299            })?;
300
301        // var = expr
302        // var += expr
303        // var -= expr
304        // array(expr) = expr
305        // array(expr) += expr
306        // array(expr) -= expr
307        // string(expr) = expr
308
309        match pos_and_tokens {
310            // 代入
311            [(_, Token::Operator(Operator::Equal)), rest @ ..]
312                if matches!(
313                    var_type,
314                    VarType::Boolean
315                        | VarType::Integer
316                        | VarType::String
317                        | VarType::RefBoolean
318                        | VarType::RefInteger
319                        | VarType::RefString
320                        | VarType::ArrayOfBoolean(..)
321                        | VarType::ArrayOfInteger(..)
322                        | VarType::RefArrayOfBoolean(..)
323                        | VarType::RefArrayOfInteger(..)
324                ) =>
325            {
326                let expr = self.parse_expr(rest)?;
327                match expr.return_type() {
328                    ExprType::Boolean if matches!(var_type, VarType::Boolean) => {
329                        self.add_statement(Statement::AssignBoolean {
330                            var_name: name.into(),
331                            value: expr,
332                        });
333                    }
334                    ExprType::Boolean if matches!(var_type, VarType::RefBoolean) => {
335                        self.add_statement(Statement::AssignRefBoolean {
336                            var_name: name.into(),
337                            value: expr,
338                        });
339                    }
340                    ExprType::Integer if matches!(var_type, VarType::Integer) => {
341                        self.add_statement(Statement::AssignInteger {
342                            var_name: name.into(),
343                            value: expr,
344                        });
345                    }
346                    ExprType::Integer if matches!(var_type, VarType::RefInteger) => {
347                        self.add_statement(Statement::AssignRefInteger {
348                            var_name: name.into(),
349                            value: expr,
350                        });
351                    }
352                    ExprType::String if matches!(var_type, VarType::String) => {
353                        self.add_statement(Statement::AssignString {
354                            var_name: name.into(),
355                            value: expr,
356                        });
357                    }
358                    ExprType::String if matches!(var_type, VarType::RefString) => {
359                        self.add_statement(Statement::AssignRefString {
360                            var_name: name.into(),
361                            value: expr,
362                        });
363                    }
364                    ExprType::ReferenceOfVar(VarType::ArrayOfBoolean(size1))
365                    | ExprType::ReferenceOfVar(VarType::RefArrayOfBoolean(size1))
366                        if matches!(var_type, VarType::ArrayOfBoolean(size2) if size1 == size2) =>
367                    {
368                        self.add_statement(Statement::AssignBooleanArray {
369                            var_name: name.into(),
370                            value: expr,
371                        });
372                    }
373                    ExprType::ReferenceOfVar(VarType::ArrayOfBoolean(size1))
374                    | ExprType::ReferenceOfVar(VarType::RefArrayOfBoolean(size1))
375                        if matches!(var_type, VarType::RefArrayOfBoolean(size2) if size1 == size2) =>
376                    {
377                        self.add_statement(Statement::AssignRefBooleanArray {
378                            var_name: name.into(),
379                            value: expr,
380                        });
381                    }
382                    ExprType::ReferenceOfVar(VarType::ArrayOfInteger(size1))
383                    | ExprType::ReferenceOfVar(VarType::RefArrayOfInteger(size1))
384                        if matches!(var_type, VarType::ArrayOfInteger(size2) if size1 == size2) =>
385                    {
386                        self.add_statement(Statement::AssignIntegerArray {
387                            var_name: name.into(),
388                            value: expr,
389                        });
390                    }
391                    ExprType::ReferenceOfVar(VarType::ArrayOfInteger(size1))
392                    | ExprType::ReferenceOfVar(VarType::RefArrayOfInteger(size1))
393                        if matches!(var_type, VarType::RefArrayOfInteger(size2) if size1 == size2) =>
394                    {
395                        self.add_statement(Statement::AssignRefIntegerArray {
396                            var_name: name.into(),
397                            value: expr,
398                        });
399                    }
400                    _ => return Err(self.syntax_error("代入の変数と値の型が一致しません".into())),
401                }
402            }
403            // 加算代入
404            [(_, Token::Operator(Operator::AddInto)), rest @ ..]
405                if matches!(var_type, VarType::Integer) =>
406            {
407                let expr = self.parse_expr(rest)?;
408                if matches!(expr.return_type(), ExprType::Integer) {
409                    self.add_statement(Statement::AssignAddInto {
410                        var_name: name.into(),
411                        value: expr,
412                    });
413                } else {
414                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
415                }
416            }
417            // 加算代入(左辺参照型)
418            [(_, Token::Operator(Operator::AddInto)), rest @ ..]
419                if matches!(var_type, VarType::RefInteger) =>
420            {
421                let expr = self.parse_expr(rest)?;
422                if matches!(expr.return_type(), ExprType::Integer) {
423                    self.add_statement(Statement::AssignRefAddInto {
424                        var_name: name.into(),
425                        value: expr,
426                    });
427                } else {
428                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
429                }
430            }
431            // 減算代入
432            [(_, Token::Operator(Operator::SubInto)), rest @ ..]
433                if matches!(var_type, VarType::Integer) =>
434            {
435                let expr = self.parse_expr(rest)?;
436                if matches!(expr.return_type(), ExprType::Integer) {
437                    self.add_statement(Statement::AssignSubInto {
438                        var_name: name.into(),
439                        value: expr,
440                    });
441                } else {
442                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
443                }
444            }
445            // 減算代入(左辺参照型)
446            [(_, Token::Operator(Operator::SubInto)), rest @ ..]
447                if matches!(var_type, VarType::RefInteger) =>
448            {
449                let expr = self.parse_expr(rest)?;
450                if matches!(expr.return_type(), ExprType::Integer) {
451                    self.add_statement(Statement::AssignRefSubInto {
452                        var_name: name.into(),
453                        value: expr,
454                    });
455                } else {
456                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
457                }
458            }
459            // 配列要素または文字列要素に代入
460            [(_, Token::Operator(Operator::OpenBracket)), ..]
461                if matches!(
462                    var_type,
463                    VarType::String
464                        | VarType::ArrayOfBoolean(_)
465                        | VarType::ArrayOfInteger(_)
466                        | VarType::RefString
467                        | VarType::RefArrayOfBoolean(_)
468                        | VarType::RefArrayOfInteger(_)
469                ) =>
470            {
471                return self.parse_assign_element(name, var_type, pos_and_tokens);
472            }
473            _ => {
474                return Err(self.syntax_error("不正な代入のステートメントです".into()));
475            }
476        }
477
478        Ok(())
479    }
480
481    // Assign Elment of Array
482    fn parse_assign_element(
483        &mut self,
484        name: &str,
485        var_type: VarType,
486        pos_and_tokens: &[(usize, Token)],
487    ) -> Result<(), SyntaxError> {
488        // array(expr) = expr
489        // array(expr) += expr
490        // array(expr) -= expr
491        // string(expr) = expr
492
493        let mut close_pos: Option<usize> = None;
494        let mut bracket_count = 1;
495        for (i, (_, token)) in pos_and_tokens.iter().enumerate().skip(1) {
496            match token {
497                Token::Operator(Operator::OpenBracket) => bracket_count += 1,
498                Token::Operator(Operator::CloseBracket) => bracket_count -= 1,
499                _ => {}
500            }
501            if bracket_count == 0 {
502                close_pos = Some(i);
503                break;
504            }
505        }
506        let close_pos = close_pos
507            .take()
508            .ok_or_else(|| self.syntax_error("閉じ括弧が不足しています".into()))?;
509
510        let (param, value) = pos_and_tokens.split_at(close_pos + 1);
511
512        let param = if let [_, inner @ .., _] = param {
513            self.parse_expr(inner)?
514        } else {
515            return Err(self.syntax_error("不正なインデックスの指定です".into()));
516        };
517        if !matches!(param.return_type(), ExprType::Integer) {
518            return Err(self.syntax_error("インデックスの型が不正です".into()));
519        }
520
521        match value {
522            // 要素への代入
523            [(_, Token::Operator(Operator::Equal)), rest @ ..] => {
524                let expr = self.parse_expr(rest)?;
525                match expr.return_type() {
526                    ExprType::Boolean if matches!(var_type, VarType::ArrayOfBoolean(_)) => {
527                        self.add_statement(Statement::AssignBooleanElement {
528                            var_name: name.into(),
529                            index: param,
530                            value: expr,
531                        });
532                    }
533                    ExprType::Boolean if matches!(var_type, VarType::RefArrayOfBoolean(_)) => {
534                        self.add_statement(Statement::AssignRefBooleanElement {
535                            var_name: name.into(),
536                            index: param,
537                            value: expr,
538                        });
539                    }
540                    ExprType::Integer if matches!(var_type, VarType::ArrayOfInteger(_)) => {
541                        self.add_statement(Statement::AssignIntegerElement {
542                            var_name: name.into(),
543                            index: param,
544                            value: expr,
545                        });
546                    }
547                    ExprType::Integer if matches!(var_type, VarType::RefArrayOfInteger(_)) => {
548                        self.add_statement(Statement::AssignRefIntegerElement {
549                            var_name: name.into(),
550                            index: param,
551                            value: expr,
552                        });
553                    }
554                    ExprType::Integer if matches!(var_type, VarType::String) => {
555                        self.add_statement(Statement::AssignCharacterElement {
556                            var_name: name.into(),
557                            index: param,
558                            value: expr,
559                        });
560                    }
561                    ExprType::Integer if matches!(var_type, VarType::RefString) => {
562                        self.add_statement(Statement::AssignRefCharacterElement {
563                            var_name: name.into(),
564                            index: param,
565                            value: expr,
566                        });
567                    }
568                    _ => return Err(self.syntax_error("代入の変数と値の型が一致しません".into())),
569                }
570            }
571            // 要素への加算代入
572            [(_, Token::Operator(Operator::AddInto)), rest @ ..]
573                if matches!(var_type, VarType::ArrayOfInteger(_)) =>
574            {
575                let expr = self.parse_expr(rest)?;
576                if matches!(expr.return_type(), ExprType::Integer) {
577                    self.add_statement(Statement::AssignAddIntoElement {
578                        var_name: name.into(),
579                        index: param,
580                        value: expr,
581                    });
582                } else {
583                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
584                }
585            }
586            // 要素への加算代入(左辺参照型)
587            [(_, Token::Operator(Operator::AddInto)), rest @ ..]
588                if matches!(var_type, VarType::RefArrayOfInteger(_)) =>
589            {
590                let expr = self.parse_expr(rest)?;
591                if matches!(expr.return_type(), ExprType::Integer) {
592                    self.add_statement(Statement::AssignRefAddIntoElement {
593                        var_name: name.into(),
594                        index: param,
595                        value: expr,
596                    });
597                } else {
598                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
599                }
600            }
601            // 要素への減算代入
602            [(_, Token::Operator(Operator::SubInto)), rest @ ..]
603                if matches!(var_type, VarType::ArrayOfInteger(_)) =>
604            {
605                let expr = self.parse_expr(rest)?;
606                if matches!(expr.return_type(), ExprType::Integer) {
607                    self.add_statement(Statement::AssignSubIntoElement {
608                        var_name: name.into(),
609                        index: param,
610                        value: expr,
611                    });
612                } else {
613                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
614                }
615            }
616            // 要素への減算代入(左辺参照型)
617            [(_, Token::Operator(Operator::SubInto)), rest @ ..]
618                if matches!(var_type, VarType::RefArrayOfInteger(_)) =>
619            {
620                let expr = self.parse_expr(rest)?;
621                if matches!(expr.return_type(), ExprType::Integer) {
622                    self.add_statement(Statement::AssignRefSubIntoElement {
623                        var_name: name.into(),
624                        index: param,
625                        value: expr,
626                    });
627                } else {
628                    return Err(self.syntax_error("代入の変数と値の型が一致しません".into()));
629                }
630            }
631            _ => return Err(self.syntax_error("不正な代入のステートメントです".into())),
632        }
633
634        Ok(())
635    }
636
637    // Assign Argument
638    fn parse_assign_argument(
639        &mut self,
640        name: &str,
641        pos_and_tokens: &[(usize, Token)],
642    ) -> Result<(), SyntaxError> {
643        assert!(self.in_call_with);
644
645        for (arg_name, _) in self.temp_call_with_arguments.iter() {
646            if arg_name == name {
647                return Err(self.syntax_error(format!("引数名が重複しています: {}", name)));
648            }
649        }
650
651        let value = if let [(_, Token::Operator(Operator::Equal)), rest @ ..] = pos_and_tokens {
652            self.parse_expr(rest)?
653        } else {
654            return Err(self.syntax_error("引数への値の割り当てのステートメントが不正です".into()));
655        };
656
657        let temp_area: usize;
658
659        if let Some(arg) = self
660            .callables
661            .get(self.temp_progam_name.as_ref().unwrap())
662            .unwrap()
663            .iter()
664            .find(|arg| arg.var_name == name)
665        {
666            if !arg.is_valid_type(&value) {
667                return Err(self.syntax_error(format!(
668                    "引数への値の割り当ての型が一致しません: {} {}",
669                    name, value
670                )));
671            }
672            if !value.can_access_variable() && arg.var_type.is_reference() {
673                if let Some(size) = arg.var_type.get_array_size() {
674                    temp_area = size;
675                } else if arg.var_type.is_string() {
676                    temp_area = 257;
677                } else if arg.var_type.is_boolean() || arg.var_type.is_integer() {
678                    temp_area = 1;
679                } else {
680                    unreachable!("BUG");
681                }
682            } else {
683                temp_area = 0;
684            }
685        } else {
686            return Err(self.syntax_error(format!("引数名に誤りがあります: {}", name)));
687        }
688
689        self.allocate_temporary_area_size += temp_area;
690
691        self.temp_call_with_arguments
692            .push((name.to_string(), value));
693
694        Ok(())
695    }
696
697    // Command
698    fn parse_command(
699        &mut self,
700        command: &Keyword,
701        pos_and_tokens: &[(usize, Token)],
702    ) -> Result<(), SyntaxError> {
703        if matches!(self.end_program_state, EndProgramState::Satisfied) {
704            return Err(self.syntax_error("この位置にステートメントを置くことはできません".into()));
705        }
706
707        if self.header_state.in_header() {
708            match command {
709                Keyword::Argument => return self.parse_command_argument(pos_and_tokens),
710                Keyword::Dim => return self.parse_command_dim(pos_and_tokens),
711                Keyword::Extern => return self.parse_command_extern_sub(pos_and_tokens),
712                Keyword::Option => return self.parse_option(pos_and_tokens),
713                Keyword::Sub => return self.parse_command_program_name(pos_and_tokens),
714                _ => {}
715            }
716        }
717
718        if self.header_state.in_defininition() {
719            return match command {
720                Keyword::ByRef => self.parse_command_byref(pos_and_tokens),
721                Keyword::ByVal => self.parse_command_byval(pos_and_tokens),
722                Keyword::End => self.parse_command_end(pos_and_tokens),
723                _ => Err(self.syntax_error(format!(
724                    "この位置に{:?}ステートメントを置くことはできません",
725                    command
726                ))),
727            };
728        }
729
730        if !self.header_state.can_command() {
731            return Err(self.syntax_error(format!(
732                "この位置に{:?}ステートメントを置くことはできません",
733                command
734            )));
735        } else if self.header_state.in_header() {
736            if let Some(name) = self.temp_progam_name.take() {
737                self.callables.insert(name, Vec::new());
738            }
739            self.header_state = HeaderState::NotHeader;
740        }
741
742        if self.in_call_with {
743            return if let Keyword::End = command {
744                self.parse_command_end(pos_and_tokens)
745            } else {
746                Err(self.syntax_error(format!(
747                    "この位置に{:?}ステートメントを置くことはできません",
748                    command
749                )))
750            };
751        }
752
753        if self.is_select_head {
754            return match command {
755                Keyword::Case => self.parse_command_case(pos_and_tokens),
756                Keyword::End => self.parse_command_end(pos_and_tokens),
757                _ => Err(self.syntax_error(format!(
758                    "この位置に{:?}ステートメントを置くことはできません",
759                    command
760                ))),
761            };
762        }
763
764        match command {
765            Keyword::Call => self.parse_command_call_extern_sub(pos_and_tokens),
766            Keyword::Case => self.parse_command_case(pos_and_tokens),
767            Keyword::Continue => self.parse_command_continue(pos_and_tokens),
768            Keyword::Do => self.parse_command_do(pos_and_tokens),
769            Keyword::Else => self.parse_command_else(pos_and_tokens),
770            Keyword::ElseIf => self.parse_command_elseif(pos_and_tokens),
771            Keyword::End => self.parse_command_end(pos_and_tokens),
772            Keyword::Exit => self.parse_command_exit(pos_and_tokens),
773            Keyword::Fill => self.parse_command_fill(pos_and_tokens),
774            Keyword::For => self.parse_command_for(pos_and_tokens),
775            Keyword::If => self.parse_command_if(pos_and_tokens),
776            Keyword::Input => self.parse_command_input(pos_and_tokens),
777            Keyword::Loop => self.parse_command_loop(pos_and_tokens),
778            Keyword::Mid => self.parse_command_mid(pos_and_tokens),
779            Keyword::Next => self.parse_command_next(pos_and_tokens),
780            Keyword::Print => self.parse_command_print(pos_and_tokens),
781            Keyword::Select => self.parse_command_select(pos_and_tokens),
782
783            Keyword::Argument
784            | Keyword::ByRef
785            | Keyword::ByVal
786            | Keyword::Dim
787            | Keyword::Extern
788            | Keyword::Option
789            | Keyword::Sub => Err(self.syntax_error(format!(
790                "この位置に{:?}ステートメントを置くことはできません",
791                command
792            ))),
793
794            Keyword::As
795            | Keyword::From
796            | Keyword::Rem
797            | Keyword::Step
798            | Keyword::Then
799            | Keyword::To
800            | Keyword::Until
801            | Keyword::With
802            | Keyword::While => unreachable!("BUG"),
803        }
804    }
805
806    // Option Array { UBound / Length } [ { All / Declare / Function } ]
807    // Option EOF { Special / Common }
808    // Option Allocator { Disabled / Enabled / Special }
809    // Option Register { Restore / Dirty }
810    // Option Variable { Initialize / Uninitialize }
811    fn parse_option(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
812        if !self.header_state.can_option() {
813            return Err(
814                self.syntax_error("この位置にOptionステートメントを置くことはできません".into())
815            );
816        }
817        let ((pt, target), (pv, value), extra) = match pos_and_tokens {
818            [target, value] => (target, value, None),
819            [target, value, extra] => (target, value, Some(extra)),
820            _ => return Err(self.syntax_error("Optionの指定が不正です".into())),
821        };
822
823        match target {
824            Token::Function(Function::Array) => {
825                if self.declare_array_with_length.is_some() {
826                    return Err(
827                        self.syntax_error_pos(*pv, "Option Arrayは既に指定されています".into())
828                    );
829                }
830                // value
831                //   UBound .... 最大インデックス(境界値・上限値)でサイズ指定 (Bound,Bounds,Indexでも可)
832                //   Length .... 配列長でサイズ指定 (Sizeでも可)
833                // extra
834                //   Declare ... Dim,ByRef,ByValだけ設定変更、CArray,SubArrayはデフォルトの設定
835                //   Function .. CArray,SubArrayだけ設定変更、Dim,ByRef,ByValはデフォルトの設定
836                //   All ....... Dim,ByRef,ByVal,CArray,SubArrayの全部の設定変更
837                //  extraを省略した場合はAllがデフォルト
838                let mut length = false;
839                let mut all = true;
840                match value {
841                    Token::Name(value) if "Default".eq_ignore_ascii_case(value) => {
842                        all = false;
843                        if extra.is_some() {
844                            return Err(
845                                self.syntax_error_pos(*pv, "Option Arrayの指定が不正です".into())
846                            );
847                        }
848                    }
849                    Token::Name(value)
850                        if "Bound".eq_ignore_ascii_case(value)
851                            || "Bounds".eq_ignore_ascii_case(value)
852                            || "Index".eq_ignore_ascii_case(value)
853                            || "UBound".eq_ignore_ascii_case(value) =>
854                    {
855                        if let Some((pa, Token::Name(extra))) = extra {
856                            if "Declare".eq_ignore_ascii_case(extra) {
857                                all = false;
858                            } else if !"Function".eq_ignore_ascii_case(extra)
859                                && !"All".eq_ignore_ascii_case(extra)
860                            {
861                                return Err(self
862                                    .syntax_error_pos(*pa, "Option Arrayの指定が不正です".into()));
863                            }
864                        }
865                    }
866                    Token::Name(value)
867                        if "Length".eq_ignore_ascii_case(value)
868                            || "Size".eq_ignore_ascii_case(value) =>
869                    {
870                        length = true;
871                        if let Some((pa, Token::Name(extra))) = extra {
872                            if "Declare".eq_ignore_ascii_case(extra) {
873                                all = false;
874                            } else if "Function".eq_ignore_ascii_case(extra) {
875                                length = false;
876                                all = false;
877                            } else if !"All".eq_ignore_ascii_case(extra) {
878                                return Err(self
879                                    .syntax_error_pos(*pa, "Option Arrayの指定が不正です".into()));
880                            }
881                        }
882                    }
883                    _ => {
884                        return Err(
885                            self.syntax_error_pos(*pv, "Option Arrayの指定が不正です".into())
886                        )
887                    }
888                }
889                self.declare_array_with_length = Some(length);
890                self.use_bound_for_array_function = length != all;
891                self.add_statement(Statement::CompileOption {
892                    option: CompileOption::ArraySize { length, all },
893                });
894            }
895            Token::Name(target)
896                if "Allocator".eq_ignore_ascii_case(target)
897                    || "Alloc".eq_ignore_ascii_case(target)
898                    || "Allocate".eq_ignore_ascii_case(target)
899                    || "Allocation".eq_ignore_ascii_case(target)
900                    || "Recur".eq_ignore_ascii_case(target)
901                    || "Recursion".eq_ignore_ascii_case(target)
902                    || "Recursive".eq_ignore_ascii_case(target) =>
903            {
904                for stmt in self.statements.first().unwrap().iter() {
905                    if let Statement::CompileOption {
906                        option: CompileOption::Allocator { .. },
907                    } = stmt
908                    {
909                        return Err(self.syntax_error_pos(
910                            *pt,
911                            format!("Option {}は既に指定されています", target),
912                        ));
913                    }
914                }
915                match value {
916                    Token::Boolean(true) => {
917                        if extra.is_some() {
918                            return Err(self.syntax_error_pos(
919                                *pv,
920                                format!("Option {}の指定が不正です", target),
921                            ));
922                        }
923                        self.add_statement(Statement::CompileOption {
924                            option: CompileOption::Allocator {
925                                enabled: true,
926                                common: true,
927                                size: MAX_ALLOCATION_SIZE,
928                            },
929                        });
930                    }
931                    Token::Name(value)
932                        if "Common".eq_ignore_ascii_case(value)
933                            || "Share".eq_ignore_ascii_case(value)
934                            || "Sharing".eq_ignore_ascii_case(value)
935                            || "Shared".eq_ignore_ascii_case(value)
936                            || "External".eq_ignore_ascii_case(value)
937                            || "Global".eq_ignore_ascii_case(value)
938                            || "Public".eq_ignore_ascii_case(value)
939                            || "On".eq_ignore_ascii_case(value)
940                            || "Enable".eq_ignore_ascii_case(value)
941                            || "Enabled".eq_ignore_ascii_case(value) =>
942                    {
943                        if extra.is_some() {
944                            return Err(self.syntax_error_pos(
945                                *pv,
946                                format!("Option {}の指定が不正です", target),
947                            ));
948                        }
949                        self.add_statement(Statement::CompileOption {
950                            option: CompileOption::Allocator {
951                                enabled: true,
952                                common: true,
953                                size: MAX_ALLOCATION_SIZE,
954                            },
955                        });
956                    }
957                    Token::Boolean(false) => {
958                        if extra.is_some() {
959                            return Err(self.syntax_error_pos(
960                                *pv,
961                                format!("Option {}の指定が不正です", target),
962                            ));
963                        }
964                        self.add_statement(Statement::CompileOption {
965                            option: CompileOption::Allocator {
966                                enabled: false,
967                                common: false,
968                                size: 0,
969                            },
970                        });
971                    }
972                    Token::Name(value)
973                        if "Default".eq_ignore_ascii_case(value)
974                            || "Disable".eq_ignore_ascii_case(value)
975                            || "Disabled".eq_ignore_ascii_case(value)
976                            || "Label".eq_ignore_ascii_case(value)
977                            || "Labeling".eq_ignore_ascii_case(value)
978                            || "Labeled".eq_ignore_ascii_case(value)
979                            || "Fix".eq_ignore_ascii_case(value)
980                            || "Fixing".eq_ignore_ascii_case(value)
981                            || "Fixed".eq_ignore_ascii_case(value)
982                            || "Pair".eq_ignore_ascii_case(value)
983                            || "Paired".eq_ignore_ascii_case(value)
984                            || "Pairing".eq_ignore_ascii_case(value)
985                            || "Unique".eq_ignore_ascii_case(value)
986                            || "Off".eq_ignore_ascii_case(value)
987                            || "No".eq_ignore_ascii_case(value)
988                            || "Nothing".eq_ignore_ascii_case(value)
989                            || "None".eq_ignore_ascii_case(value) =>
990                    {
991                        if extra.is_some() {
992                            return Err(self.syntax_error_pos(
993                                *pv,
994                                format!("Option {}の指定が不正です", target),
995                            ));
996                        }
997                        self.add_statement(Statement::CompileOption {
998                            option: CompileOption::Allocator {
999                                enabled: false,
1000                                common: false,
1001                                size: 0,
1002                            },
1003                        });
1004                    }
1005                    Token::Name(value)
1006                        if "Special".eq_ignore_ascii_case(value)
1007                            || "Intern".eq_ignore_ascii_case(value)
1008                            || "Internal".eq_ignore_ascii_case(value)
1009                            || "Local".eq_ignore_ascii_case(value)
1010                            || "Private".eq_ignore_ascii_case(value)
1011                            || "Personal".eq_ignore_ascii_case(value)
1012                            || "Own".eq_ignore_ascii_case(value)
1013                            || "Owned".eq_ignore_ascii_case(value) =>
1014                    {
1015                        match extra {
1016                            None => {
1017                                self.add_statement(Statement::CompileOption {
1018                                    option: CompileOption::Allocator {
1019                                        enabled: true,
1020                                        common: false,
1021                                        size: MAX_ALLOCATION_SIZE,
1022                                    },
1023                                });
1024                            }
1025                            Some((_, Token::Integer(size)))
1026                                if (1..=MAX_ALLOCATION_SIZE as i32).contains(size) =>
1027                            {
1028                                self.maximum_variable_area_size = *size as usize;
1029                                self.add_statement(Statement::CompileOption {
1030                                    option: CompileOption::Allocator {
1031                                        enabled: true,
1032                                        common: false,
1033                                        size: *size as usize,
1034                                    },
1035                                });
1036                            }
1037                            Some((pv, _)) => {
1038                                return Err(self.syntax_error_pos(
1039                                    *pv,
1040                                    format!("Option {}の指定が不正です", target),
1041                                ))
1042                            }
1043                        }
1044                    }
1045                    _ => {
1046                        return Err(self
1047                            .syntax_error_pos(*pt, format!("Option {}の指定が不正です", target)))
1048                    }
1049                }
1050            }
1051            _ if extra.is_some() => {
1052                let (pe, _) = extra.unwrap();
1053                return Err(self.syntax_error_pos(*pe, "Optionの指定が不正です".into()));
1054            }
1055            Token::Function(Function::Eof) => {
1056                for stmt in self.statements.first().unwrap().iter() {
1057                    if let Statement::CompileOption {
1058                        option: CompileOption::Eof { .. },
1059                    } = stmt
1060                    {
1061                        return Err(
1062                            self.syntax_error_pos(*pt, "Option EOFは既に指定されています".into())
1063                        );
1064                    }
1065                }
1066                match value {
1067                    Token::Keyword(Keyword::Extern) => {
1068                        self.add_statement(Statement::CompileOption {
1069                            option: CompileOption::Eof { common: true },
1070                        });
1071                    }
1072                    Token::Name(value)
1073                        if "Common".eq_ignore_ascii_case(value)
1074                            || "Share".eq_ignore_ascii_case(value)
1075                            || "Sharing".eq_ignore_ascii_case(value)
1076                            || "Shared".eq_ignore_ascii_case(value)
1077                            || "External".eq_ignore_ascii_case(value)
1078                            || "Global".eq_ignore_ascii_case(value)
1079                            || "Public".eq_ignore_ascii_case(value) =>
1080                    {
1081                        self.add_statement(Statement::CompileOption {
1082                            option: CompileOption::Eof { common: true },
1083                        });
1084                    }
1085                    Token::Name(value)
1086                        if "Default".eq_ignore_ascii_case(value)
1087                            || "Special".eq_ignore_ascii_case(value)
1088                            || "Intern".eq_ignore_ascii_case(value)
1089                            || "Internal".eq_ignore_ascii_case(value)
1090                            || "Local".eq_ignore_ascii_case(value)
1091                            || "Personal".eq_ignore_ascii_case(value)
1092                            || "Private".eq_ignore_ascii_case(value)
1093                            || "Own".eq_ignore_ascii_case(value)
1094                            || "Owned".eq_ignore_ascii_case(value) =>
1095                    {
1096                        self.add_statement(Statement::CompileOption {
1097                            option: CompileOption::Eof { common: false },
1098                        });
1099                    }
1100                    _ => {
1101                        return Err(self.syntax_error_pos(*pv, "Option EOFの指定が不正です".into()))
1102                    }
1103                }
1104            }
1105            Token::Name(target) if "Register".eq_ignore_ascii_case(target) => {
1106                for stmt in self.statements.first().unwrap().iter() {
1107                    if let Statement::CompileOption {
1108                        option: CompileOption::Register { .. },
1109                    } = stmt
1110                    {
1111                        return Err(self.syntax_error_pos(
1112                            *pt,
1113                            "Option Registerは既に指定されています".into(),
1114                        ));
1115                    }
1116                }
1117                // Recover 呼び出し前に回復する
1118                // Restore 呼び出し前を復元する
1119                // Back    呼び出し前の状態に戻る
1120                // Break   破壊(呼び出し前の状態には戻らない)
1121                // Dirty   汚染(呼び出し前の状態には戻らない) (Pollutionでもいいかもしれない)
1122                // Unclean  汚染(呼び出し前の状態には戻らない) (反対がcleanにするわけではないので違和感はある)
1123                // Keep,Leave,Saveは対象がどうなるのか俺にはよくわからん
1124                // Keep は呼び出し前を維持するのか、終了状態を維持するのか、
1125                // Save は呼び出し前を保存するのか、終了状態を保存するのか、
1126                // Leave は呼び出し前を残しておくのか、終了状態を残しておくのか、(Leaveは後者な雰囲気はある)
1127                match value {
1128                    Token::Name(value)
1129                        if "Default".eq_ignore_ascii_case(value)
1130                            || "Recover".eq_ignore_ascii_case(value)
1131                            || "Restore".eq_ignore_ascii_case(value)
1132                            || "Back".eq_ignore_ascii_case(value) =>
1133                    {
1134                        self.add_statement(Statement::CompileOption {
1135                            option: CompileOption::Register { restore: true },
1136                        });
1137                    }
1138                    Token::Name(value)
1139                        if "Break".eq_ignore_ascii_case(value)
1140                            || "Dirty".eq_ignore_ascii_case(value)
1141                            || "Unclear".eq_ignore_ascii_case(value)
1142                            || "Unclean".eq_ignore_ascii_case(value) =>
1143                    {
1144                        self.add_statement(Statement::CompileOption {
1145                            option: CompileOption::Register { restore: false },
1146                        });
1147                    }
1148                    _ => {
1149                        return Err(
1150                            self.syntax_error_pos(*pv, "Option Registerの指定が不正です".into())
1151                        )
1152                    }
1153                }
1154            }
1155            Token::Name(target) if "Variable".eq_ignore_ascii_case(target) => {
1156                for stmt in self.statements.first().unwrap().iter() {
1157                    if let Statement::CompileOption {
1158                        option: CompileOption::Variable { .. },
1159                    } = stmt
1160                    {
1161                        return Err(self.syntax_error_pos(
1162                            *pt,
1163                            "Option Variableは既に指定されています".into(),
1164                        ));
1165                    }
1166                }
1167                match value {
1168                    Token::Name(value)
1169                        if "Default".eq_ignore_ascii_case(value)
1170                            || "Initialize".eq_ignore_ascii_case(value)
1171                            || "Init".eq_ignore_ascii_case(value)
1172                            || "Initialized".eq_ignore_ascii_case(value)
1173                            || "Format".eq_ignore_ascii_case(value)
1174                            || "Clear".eq_ignore_ascii_case(value)
1175                            || "Clean".eq_ignore_ascii_case(value)
1176                            || "Zero".eq_ignore_ascii_case(value) =>
1177                    {
1178                        self.add_statement(Statement::CompileOption {
1179                            option: CompileOption::Variable { initialize: true },
1180                        });
1181                    }
1182                    Token::Name(value)
1183                        if "Uninitialize".eq_ignore_ascii_case(value)
1184                            || "Uninitialized".eq_ignore_ascii_case(value)
1185                            || "Uninit".eq_ignore_ascii_case(value)
1186                            || "Unclear".eq_ignore_ascii_case(value)
1187                            || "Unclean".eq_ignore_ascii_case(value)
1188                            || "Dirty".eq_ignore_ascii_case(value) =>
1189                    {
1190                        self.add_statement(Statement::CompileOption {
1191                            option: CompileOption::Variable { initialize: false },
1192                        });
1193                    }
1194                    _ => {
1195                        return Err(
1196                            self.syntax_error_pos(*pv, "Option Variableの指定が不正です".into())
1197                        )
1198                    }
1199                }
1200            }
1201            _ => return Err(self.syntax_error_pos(*pt, "Optionの指定が不正です".into())),
1202        }
1203
1204        Ok(())
1205    }
1206
1207    // Fill <bool_arr>, <value>
1208    // Fill <ref_bool_arr>, <value>
1209    // Fill <int_arr>, <value>
1210    // Fill <ref_int_arr>, <value>
1211    // Fill <str_var>, <char>
1212    // Fill <ref_str_var>, <char>
1213    fn parse_command_fill(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
1214        let param = self.parse_expr(pos_and_tokens)?;
1215        let (var, value) = if let Expr::ParamList(list) = &param {
1216            if let [var, value] = list.as_slice() {
1217                (var, value)
1218            } else {
1219                return Err(self.syntax_error("不正なFillステートメントです".into()));
1220            }
1221        } else {
1222            return Err(self.syntax_error("不正なFillステートメントです".into()));
1223        };
1224
1225        match var {
1226            Expr::VarString(var_name) if matches!(value.return_type(), ExprType::Integer) => {
1227                self.add_statement(Statement::FillString {
1228                    var_name: var_name.clone(),
1229                    value: value.clone(),
1230                });
1231            }
1232            Expr::VarRefString(var_name) if matches!(value.return_type(), ExprType::Integer) => {
1233                self.add_statement(Statement::FillRefString {
1234                    var_name: var_name.clone(),
1235                    value: value.clone(),
1236                });
1237            }
1238            Expr::ReferenceOfVar(var_name, VarType::ArrayOfBoolean(_))
1239                if matches!(value.return_type(), ExprType::Boolean) =>
1240            {
1241                self.add_statement(Statement::FillArrayOfBoolean {
1242                    var_name: var_name.clone(),
1243                    value: value.clone(),
1244                });
1245            }
1246            Expr::ReferenceOfVar(var_name, VarType::RefArrayOfBoolean(_))
1247                if matches!(value.return_type(), ExprType::Boolean) =>
1248            {
1249                self.add_statement(Statement::FillRefArrayOfBoolean {
1250                    var_name: var_name.clone(),
1251                    value: value.clone(),
1252                });
1253            }
1254            Expr::ReferenceOfVar(var_name, VarType::ArrayOfInteger(_))
1255                if matches!(value.return_type(), ExprType::Integer) =>
1256            {
1257                self.add_statement(Statement::FillArrayOfInteger {
1258                    var_name: var_name.clone(),
1259                    value: value.clone(),
1260                });
1261            }
1262            Expr::ReferenceOfVar(var_name, VarType::RefArrayOfInteger(_))
1263                if matches!(value.return_type(), ExprType::Integer) =>
1264            {
1265                self.add_statement(Statement::FillRefArrayOfInteger {
1266                    var_name: var_name.clone(),
1267                    value: value.clone(),
1268                });
1269            }
1270            _ => return Err(self.syntax_error("不正なFillステートメントです".into())),
1271        }
1272
1273        Ok(())
1274    }
1275
1276    // Call <name>
1277    // Call <name> (<arguments>, ..)
1278    // Call <name> With
1279    fn parse_command_call_extern_sub(
1280        &mut self,
1281        pos_and_tokens: &[(usize, Token)],
1282    ) -> Result<(), SyntaxError> {
1283        match pos_and_tokens {
1284            [(pn, Token::Name(name)), (_, Token::Operator(Operator::OpenBracket)), (_, Token::Operator(Operator::CloseBracket))]
1285            | [(pn, Token::Name(name))] => {
1286                if let Some(args) = self.callables.get(name) {
1287                    if !args.is_empty() {
1288                        return Err(self.syntax_error_pos(*pn, "引数の指定が必要です".into()));
1289                    }
1290                } else {
1291                    return Err(
1292                        self.syntax_error_pos(*pn, format!("サブルーチン{}が未定義です", name))
1293                    );
1294                }
1295                self.add_statement(Statement::Call {
1296                    name: name.clone(),
1297                    arguments: Vec::new(),
1298                });
1299            }
1300            [(pn, Token::Name(name)), (_, Token::Keyword(Keyword::With))] => {
1301                if !self.callables.contains_key(name) {
1302                    return Err(
1303                        self.syntax_error_pos(*pn, format!("サブルーチン{}が未定義です", name))
1304                    );
1305                }
1306                assert!(self.temp_progam_name.is_none());
1307                assert!(self.temp_call_with_arguments.is_empty());
1308                assert!(!self.in_call_with);
1309                self.temp_progam_name = Some(name.clone());
1310                self.in_call_with = true;
1311                self.allocate_temporary_area_size = 0;
1312            }
1313            [(pn, Token::Name(name)), rest @ ..] => {
1314                let param = self.parse_expr(rest)?;
1315                let mut temp_area: usize = 0;
1316                let arguments = if let Some(args) = self.callables.get(name) {
1317                    if let Expr::ParamList(list) = param {
1318                        if list.len() != args.len() {
1319                            return Err(self.syntax_error("引数の数が一致しません".into()));
1320                        }
1321                        let mut arguments = Vec::with_capacity(list.len());
1322                        for (arg, expr) in args.iter().zip(list) {
1323                            if !arg.is_valid_type(&expr) {
1324                                return Err(self.syntax_error(format!(
1325                                    "引数と値の型が一致しません: {} = {}",
1326                                    arg.var_name, expr
1327                                )));
1328                            }
1329                            if !expr.can_access_variable() && arg.var_type.is_reference() {
1330                                if let Some(size) = arg.var_type.get_array_size() {
1331                                    temp_area += size;
1332                                } else if arg.var_type.is_string() {
1333                                    temp_area += 257;
1334                                } else if arg.var_type.is_boolean() || arg.var_type.is_integer() {
1335                                    temp_area += 1;
1336                                } else {
1337                                    unreachable!("BUG");
1338                                }
1339                            }
1340                            arguments.push((arg.var_name.clone(), expr));
1341                        }
1342                        arguments
1343                    } else if args.len() == 1 {
1344                        let arg = args.first().unwrap();
1345                        if !arg.is_valid_type(&param) {
1346                            return Err(self.syntax_error(format!(
1347                                "引数と値の型が一致しません: {} = {}",
1348                                arg.var_name, param
1349                            )));
1350                        }
1351                        if !param.can_access_variable() && arg.var_type.is_reference() {
1352                            if let Some(size) = arg.var_type.get_array_size() {
1353                                temp_area += size;
1354                            } else if arg.var_type.is_string() {
1355                                temp_area += 257;
1356                            } else if arg.var_type.is_boolean() || arg.var_type.is_integer() {
1357                                temp_area += 1;
1358                            } else {
1359                                unreachable!("BUG");
1360                            }
1361                        }
1362                        vec![(arg.var_name.clone(), param)]
1363                    } else {
1364                        return Err(self.syntax_error_pos(*pn, "引数の数が一致しません".into()));
1365                    }
1366                } else {
1367                    return Err(
1368                        self.syntax_error_pos(*pn, format!("サブルーチン{}が未定義です", name))
1369                    );
1370                };
1371                self.maximum_allocate_temporary_area_size =
1372                    self.maximum_allocate_temporary_area_size.max(temp_area);
1373                self.add_statement(Statement::Call {
1374                    name: name.clone(),
1375                    arguments,
1376                });
1377            }
1378            _ => return Err(self.syntax_error("不正なCallステートメントです".into())),
1379        }
1380        Ok(())
1381    }
1382
1383    // プログラム名の正当性チェック
1384    fn check_valid_program_name(&self, pn: usize, name: &str) -> Result<(), SyntaxError> {
1385        if !is_valid_program_name(name) {
1386            Err(self.syntax_error_pos(pn, format!("禁止されている名前です: {}", name)))
1387        } else if self.callables.contains_key(name) {
1388            Err(self.syntax_error_pos(pn, format!("既に使用されている名前です: {}", name)))
1389        } else {
1390            Ok(())
1391        }
1392    }
1393
1394    // Program <name>
1395    fn parse_command_program_name(
1396        &mut self,
1397        pos_and_tokens: &[(usize, Token)],
1398    ) -> Result<(), SyntaxError> {
1399        if !self.header_state.can_program_name() {
1400            return Err(
1401                self.syntax_error("この位置にSubステートメントを置くことはできません".into())
1402            );
1403        }
1404        if let [(pn, Token::Name(name))] = pos_and_tokens {
1405            self.check_valid_program_name(*pn, name)?;
1406            assert!(self.temp_progam_name.is_none());
1407            assert!(self.temp_argumets.is_empty());
1408            self.temp_progam_name = Some(name.clone());
1409            self.add_statement(Statement::ProgramName { name: name.clone() });
1410        } else {
1411            return Err(self.syntax_error("不正なSubステートメントです".into()));
1412        }
1413        self.header_state = HeaderState::Argument;
1414        self.end_program_state = EndProgramState::Required;
1415        Ok(())
1416    }
1417
1418    // Extern Sub <name>
1419    // Extern Sub <name> With
1420    fn parse_command_extern_sub(
1421        &mut self,
1422        pos_and_tokens: &[(usize, Token)],
1423    ) -> Result<(), SyntaxError> {
1424        if !self.header_state.can_extern_sub() {
1425            return Err(self
1426                .syntax_error("この位置にExtern Subステートメントを置くことはできません".into()));
1427        }
1428        match pos_and_tokens {
1429            [(_, Token::Keyword(Keyword::Sub)), (pn, Token::Name(name)), (_, Token::Keyword(Keyword::With))] =>
1430            {
1431                self.check_valid_program_name(*pn, name)?;
1432                assert!(self.temp_argumets.is_empty(), "BUG");
1433                self.temp_progam_name = Some(name.clone());
1434                self.header_state = HeaderState::InExternSub;
1435            }
1436            [(_, Token::Keyword(Keyword::Sub)), (pn, Token::Name(name))] => {
1437                self.check_valid_program_name(*pn, name)?;
1438                self.callables.insert(name.clone(), Vec::new());
1439                self.add_statement(Statement::ExternSub {
1440                    name: name.clone(),
1441                    arguments: Vec::new(),
1442                });
1443            }
1444            _ => return Err(self.syntax_error("不正なExtern Subステートメントです".into())),
1445        }
1446        Ok(())
1447    }
1448
1449    // ByRef <name> As {Boolean / Integer} { From / To } <register>
1450    // ByRef <name> As String { From / To } <register>,<register>
1451    // ByRef <name>(<ubound>) As {Boolean / Integer} { From / To } <register>
1452    fn parse_command_byref(
1453        &mut self,
1454        pos_and_tokens: &[(usize, Token)],
1455    ) -> Result<(), SyntaxError> {
1456        use Keyword::As;
1457        use Operator::{CloseBracket as Cb, Comma as Co, OpenBracket as Ob};
1458        use Token::{Integer as I, Keyword as K, Name as N, Operator as Op, TypeName as T};
1459        use TypeName as Tn;
1460        self.variable_area_size += 1;
1461        let ((pn, var_name), var_type, (pf, flow), (pr1, reg1), reg2) = match pos_and_tokens {
1462            [(pn, N(name)), (_, K(As)), (_, T(Tn::Boolean)), (pf, K(flow)), (pr, N(reg))] => {
1463                ((pn, name), VarType::RefBoolean, (pf, flow), (pr, reg), None)
1464            }
1465            [(pn, N(name)), (_, K(As)), (_, T(Tn::Integer)), (pf, K(flow)), (pr, N(reg))] => {
1466                ((pn, name), VarType::RefInteger, (pf, flow), (pr, reg), None)
1467            }
1468            [(pn, N(name)), (_, K(As)), (_, T(Tn::String)), (pf, K(flow)), (pr1, N(reg1)), (_, Op(Co)), (pr2, N(reg2))] =>
1469            {
1470                self.variable_area_size += 1;
1471                let reg2 = Some((pr2, reg2));
1472                let var_type = VarType::RefString;
1473                ((pn, name), var_type, (pf, flow), (pr1, reg1), reg2)
1474            }
1475            [(pn, N(name)), (_, Op(Ob)), (pu, I(ubound)), (_, Op(Cb)), (_, K(As)), (_, T(Tn::Boolean)), (pf, K(flow)), (pr, N(reg))] =>
1476            {
1477                let size = self.parse_declare_array_size(*ubound).ok_or_else(|| {
1478                    self.syntax_error_pos(*pu, "配列の大きさの指定が不正です".into())
1479                })?;
1480                let var_type = VarType::RefArrayOfBoolean(size);
1481                ((pn, name), var_type, (pf, flow), (pr, reg), None)
1482            }
1483            [(pn, N(name)), (_, Op(Ob)), (pu, I(ubound)), (_, Op(Cb)), (_, K(As)), (_, T(Tn::Integer)), (pf, K(flow)), (pr, N(reg))] =>
1484            {
1485                let size = self.parse_declare_array_size(*ubound).ok_or_else(|| {
1486                    self.syntax_error_pos(*pu, "配列の大きさの指定が不正です".into())
1487                })?;
1488                let var_type = VarType::RefArrayOfInteger(size);
1489                ((pn, name), var_type, (pf, flow), (pr, reg), None)
1490            }
1491            _ => return Err(self.syntax_error("不正なByRefステートメントです".into())),
1492        };
1493
1494        if self
1495            .temp_argumets
1496            .iter()
1497            .any(|arg| arg.var_name.eq(var_name))
1498        {
1499            return Err(self.syntax_error_pos(*pn, format!("引数名が重複しています: {}", var_name)));
1500        }
1501
1502        match flow {
1503            Keyword::From if self.header_state.in_argument() => {}
1504            Keyword::To if self.header_state.in_extern_sub() => {}
1505            _ => return Err(self.syntax_error_pos(*pf, "不正なByRefステートメントです".into())),
1506        }
1507
1508        let register1 = IndexRegister::try_from(reg1.as_str()).map_err(|_| {
1509            self.syntax_error_pos(*pr1, format!("不正なレジスタ名です: {}", reg1.as_str()))
1510        })?;
1511        if self
1512            .temp_argumets
1513            .iter()
1514            .any(|arg| arg.register1 == register1 || arg.register2 == Some(register1))
1515        {
1516            return Err(
1517                self.syntax_error_pos(*pr1, format!("レジスタが重複しています: {}", register1))
1518            );
1519        }
1520
1521        let register2 = if let Some((pr2, reg2)) = reg2 {
1522            let register2 = IndexRegister::try_from(reg2.as_str()).map_err(|_| {
1523                self.syntax_error_pos(*pr2, format!("不正なレジスタ名です: {}", reg2.as_str()))
1524            })?;
1525            if self
1526                .temp_argumets
1527                .iter()
1528                .any(|arg| arg.register1 == register2 || arg.register2 == Some(register2))
1529                || register1 == register2
1530            {
1531                return Err(self.syntax_error_pos(
1532                    *pr2,
1533                    format!("レジスタが重複しています: {}", reg2.as_str()),
1534                ));
1535            }
1536            Some(register2)
1537        } else {
1538            None
1539        };
1540
1541        let arg_info = ArgumentInfo {
1542            var_name: var_name.clone(),
1543            var_type,
1544            register1,
1545            register2,
1546        };
1547
1548        self.temp_argumets.push(arg_info);
1549
1550        Ok(())
1551    }
1552
1553    // ByVal <name> As {Boolean / Integer} { From / To } <register>
1554    // ByVal <name> As String { From / To } <register>,<register>
1555    // ByVal <name>(<ubound>) As {Boolean / Integer} { From / To } <register>
1556    fn parse_command_byval(
1557        &mut self,
1558        pos_and_tokens: &[(usize, Token)],
1559    ) -> Result<(), SyntaxError> {
1560        use Keyword::As;
1561        use Operator::{CloseBracket as Cb, Comma as Co, OpenBracket as Ob};
1562        use Token::{Integer as I, Keyword as K, Name as N, Operator as Op, TypeName as T};
1563        use TypeName as Tn;
1564        let ((pn, var_name), var_type, (pf, flow), (pr1, reg1), reg2) = match pos_and_tokens {
1565            [(pn, N(name)), (_, K(As)), (_, T(Tn::Boolean)), (pf, K(flow)), (pr, N(reg))] => {
1566                self.variable_area_size += 1;
1567                ((pn, name), VarType::Boolean, (pf, flow), (pr, reg), None)
1568            }
1569            [(pn, N(name)), (_, K(As)), (_, T(Tn::Integer)), (pf, K(flow)), (pr, N(reg))] => {
1570                self.variable_area_size += 1;
1571                ((pn, name), VarType::Integer, (pf, flow), (pr, reg), None)
1572            }
1573            [(pn, N(name)), (_, K(As)), (_, T(Tn::String)), (pf, K(flow)), (pr1, N(reg1)), (_, Op(Co)), (pr2, N(reg2))] =>
1574            {
1575                self.variable_area_size += 257;
1576                let reg2 = Some((pr2, reg2));
1577                let var_type = VarType::String;
1578                ((pn, name), var_type, (pf, flow), (pr1, reg1), reg2)
1579            }
1580            [(pn, N(name)), (_, Op(Ob)), (pu, I(ubound)), (_, Op(Cb)), (_, K(As)), (_, T(Tn::Boolean)), (pf, K(flow)), (pr, N(reg))] =>
1581            {
1582                let size = self.parse_declare_array_size(*ubound).ok_or_else(|| {
1583                    self.syntax_error_pos(*pu, "配列の大きさの指定が不正です".into())
1584                })?;
1585                self.variable_area_size += size;
1586                let var_type = VarType::ArrayOfBoolean(size);
1587                ((pn, name), var_type, (pf, flow), (pr, reg), None)
1588            }
1589            [(pn, N(name)), (_, Op(Ob)), (pu, I(ubound)), (_, Op(Cb)), (_, K(As)), (_, T(Tn::Integer)), (pf, K(flow)), (pr, N(reg))] =>
1590            {
1591                let size = self.parse_declare_array_size(*ubound).ok_or_else(|| {
1592                    self.syntax_error_pos(*pu, "配列の大きさの指定が不正です".into())
1593                })?;
1594                self.variable_area_size += size;
1595                let var_type = VarType::ArrayOfInteger(size);
1596                ((pn, name), var_type, (pf, flow), (pr, reg), None)
1597            }
1598            _ => return Err(self.syntax_error("不正なByValステートメントです".into())),
1599        };
1600
1601        if self
1602            .temp_argumets
1603            .iter()
1604            .any(|arg| arg.var_name.eq(var_name))
1605        {
1606            return Err(self.syntax_error_pos(*pn, format!("引数名が重複しています: {}", var_name)));
1607        }
1608
1609        match flow {
1610            Keyword::From if self.header_state.in_argument() => {}
1611            Keyword::To if self.header_state.in_extern_sub() => {}
1612            _ => return Err(self.syntax_error_pos(*pf, "不正なByValステートメントです".into())),
1613        }
1614
1615        let register1 = IndexRegister::try_from(reg1.as_str()).map_err(|_| {
1616            self.syntax_error_pos(*pr1, format!("不正なレジスタ名です: {}", reg1.as_str()))
1617        })?;
1618        if self
1619            .temp_argumets
1620            .iter()
1621            .any(|arg| arg.register1 == register1 || arg.register2 == Some(register1))
1622        {
1623            return Err(
1624                self.syntax_error_pos(*pr1, format!("レジスタが重複しています: {}", reg1.as_str()))
1625            );
1626        }
1627
1628        let register2 = if let Some((pr2, reg2)) = reg2 {
1629            let register2 = IndexRegister::try_from(reg2.as_str()).map_err(|_| {
1630                self.syntax_error_pos(*pr2, format!("不正なレジスタ名です: {}", reg2.as_str()))
1631            })?;
1632            if self
1633                .temp_argumets
1634                .iter()
1635                .any(|arg| arg.register1 == register2 || arg.register2 == Some(register2))
1636                || register1 == register2
1637            {
1638                return Err(self.syntax_error_pos(
1639                    *pr2,
1640                    format!("レジスタが重複しています: {}", reg2.as_str()),
1641                ));
1642            }
1643            Some(register2)
1644        } else {
1645            None
1646        };
1647
1648        let arg_info = ArgumentInfo {
1649            var_name: var_name.clone(),
1650            var_type,
1651            register1,
1652            register2,
1653        };
1654
1655        self.temp_argumets.push(arg_info);
1656
1657        Ok(())
1658    }
1659
1660    // Argumentステートメント
1661    fn parse_command_argument(
1662        &mut self,
1663        pos_and_tokens: &[(usize, Token)],
1664    ) -> Result<(), SyntaxError> {
1665        if !self.header_state.can_argument() {
1666            return Err(
1667                self.syntax_error("この位置にArgumentステートメントを置くことはできません".into())
1668            );
1669        }
1670
1671        if !pos_and_tokens.is_empty() {
1672            return Err(self.syntax_error("不正なArgumentステートメントです".into()));
1673        }
1674
1675        self.header_state = HeaderState::InArgument;
1676
1677        Ok(())
1678    }
1679
1680    // Mid(<var_str>,<offset>) = <str_value>
1681    // Mid(<var_str>,<offset>,<length>) = <str_value>
1682    fn parse_command_mid(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
1683        // Midパラメータの括弧
1684        let mut close_pos: Option<usize> = None;
1685        let mut bracket_count = 1;
1686        for (i, (_, token)) in pos_and_tokens.iter().enumerate().skip(1) {
1687            match token {
1688                Token::Operator(Operator::OpenBracket) => bracket_count += 1,
1689                Token::Operator(Operator::CloseBracket) => bracket_count -= 1,
1690                _ => {}
1691            }
1692            if bracket_count == 0 {
1693                close_pos = Some(i);
1694                break;
1695            }
1696        }
1697        let close_pos = close_pos
1698            .take()
1699            .ok_or_else(|| self.syntax_error("閉じ括弧が不足しています".into()))?;
1700
1701        let (param, value) = pos_and_tokens.split_at(close_pos + 1);
1702
1703        let param = if let [_, inner @ .., _] = param {
1704            self.parse_expr(inner)?
1705        } else {
1706            return Err(self.syntax_error("不正なMidステートメントです".into()));
1707        };
1708
1709        let mut list = if let Expr::ParamList(list) = param {
1710            list
1711        } else {
1712            return Err(self.syntax_error("不正なMidステートメントです".into()));
1713        };
1714
1715        list.reverse();
1716
1717        let (var_name, var_is_ref) = match list.pop() {
1718            Some(Expr::VarString(var_name)) => (var_name, false),
1719            Some(Expr::VarRefString(var_name)) => (var_name, true),
1720            _ => return Err(self.syntax_error("文字列変数名が指定されていません".into())),
1721        };
1722
1723        let offset = match list.pop() {
1724            Some(offset) if matches!(offset.return_type(), ExprType::Integer) => offset,
1725            _ => return Err(self.syntax_error("不正なオフセット値の指定です".into())),
1726        };
1727
1728        let length = match list.pop() {
1729            None => None,
1730            Some(expr) if matches!(expr.return_type(), ExprType::Integer) && list.is_empty() => {
1731                Some(expr)
1732            }
1733            Some(_) => return Err(self.syntax_error("不正な長さの指定です".into())),
1734        };
1735
1736        // 要素への代入
1737        if let [(_, Token::Operator(Operator::Equal)), rest @ ..] = value {
1738            let value = self.parse_expr(rest)?;
1739            if matches!(value.return_type(), ExprType::String) {
1740                self.add_statement(Statement::Mid {
1741                    var_name,
1742                    var_is_ref,
1743                    offset,
1744                    length,
1745                    value,
1746                });
1747            } else {
1748                return Err(self.syntax_error("値の型が文字列ではありません".into()));
1749            }
1750        } else {
1751            return Err(self.syntax_error("不正なMidステートメントです".into()));
1752        }
1753
1754        Ok(())
1755    }
1756
1757    // End { Argument / Call / If / Program / Select / Sub }
1758    fn parse_command_end(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
1759        match pos_and_tokens {
1760            [(_, Token::Keyword(Keyword::Argument))] => self.compose_command_argument(),
1761            [(_, Token::Keyword(Keyword::Call))] => self.compose_command_call_with(),
1762            [(_, Token::Keyword(Keyword::If))] => self.compose_command_if(),
1763            [(_, Token::Keyword(Keyword::Select))] => self.compose_command_select(),
1764            [(_, Token::Keyword(Keyword::Sub))] => self.compose_command_sub(),
1765            _ => Err(self.syntax_error("不正なEndステートメントです".into())),
1766        }
1767    }
1768
1769    // End Call
1770    fn compose_command_call_with(&mut self) -> Result<(), SyntaxError> {
1771        if !self.in_call_with {
1772            return Err(self.syntax_error("不正なEndステートメントです".into()));
1773        }
1774
1775        let name = self.temp_progam_name.take().unwrap();
1776        let arguments = self.temp_call_with_arguments.split_off(0);
1777
1778        if self.callables.get(&name).unwrap().len() != arguments.len() {
1779            return Err(self.syntax_error("引数が不足しています".into()));
1780        }
1781
1782        self.maximum_allocate_temporary_area_size = self
1783            .maximum_allocate_temporary_area_size
1784            .max(self.allocate_temporary_area_size);
1785
1786        self.add_statement(Statement::Call { name, arguments });
1787
1788        self.in_call_with = false;
1789
1790        Ok(())
1791    }
1792
1793    // End Argument
1794    fn compose_command_argument(&mut self) -> Result<(), SyntaxError> {
1795        if !self.header_state.in_argument() {
1796            return Err(self.syntax_error("不正なEndステートメントです".into()));
1797        }
1798
1799        let arguments = self.temp_argumets.split_off(0);
1800
1801        for arg in arguments.iter() {
1802            self.variables.insert(arg.var_name.clone(), arg.var_type);
1803        }
1804
1805        if let Some(name) = self.temp_progam_name.take() {
1806            self.callables.insert(name, arguments.clone());
1807        }
1808
1809        self.add_statement(Statement::Argument { arguments });
1810
1811        self.header_state = HeaderState::Dim;
1812
1813        Ok(())
1814    }
1815
1816    // End Sub
1817    fn compose_command_sub(&mut self) -> Result<(), SyntaxError> {
1818        if !self.header_state.in_extern_sub() {
1819            if self.can_end_program() {
1820                self.end_program_state = EndProgramState::Satisfied;
1821                return Ok(());
1822            } else {
1823                return Err(self.syntax_error("不正なEndステートメントです".into()));
1824            }
1825        }
1826
1827        let name = if let Some(name) = self.temp_progam_name.take() {
1828            name
1829        } else {
1830            unreachable!("BUG");
1831        };
1832
1833        let arguments = self.temp_argumets.split_off(0);
1834
1835        self.callables.insert(name.clone(), arguments.clone());
1836
1837        self.add_statement(Statement::ExternSub { name, arguments });
1838
1839        self.header_state = HeaderState::ExternSub;
1840
1841        Ok(())
1842    }
1843
1844    // End If
1845    fn compose_command_if(&mut self) -> Result<(), SyntaxError> {
1846        let block = self.statements.pop().unwrap(); // 常に self.statements.len() > 0 なので
1847
1848        match self.provisionals.pop() {
1849            Some(Statement::ProvitionalIf { condition }) => {
1850                self.add_statement(Statement::If {
1851                    condition,
1852                    block,
1853                    else_blocks: Vec::new(),
1854                });
1855            }
1856            Some(Statement::ProvisionalElseIf { condition }) => {
1857                let else_if_statement = Statement::ElseIf { condition, block };
1858                if let Some(Statement::If {
1859                    condition,
1860                    block,
1861                    mut else_blocks,
1862                }) = self.provisionals.pop()
1863                {
1864                    else_blocks.push(else_if_statement);
1865                    self.add_statement(Statement::If {
1866                        condition,
1867                        block,
1868                        else_blocks,
1869                    });
1870                } else {
1871                    unreachable!("BUG");
1872                }
1873            }
1874            Some(Statement::ProvisionalElse) => {
1875                let else_statement = Statement::Else { block };
1876                if let Some(Statement::If {
1877                    condition,
1878                    block,
1879                    mut else_blocks,
1880                }) = self.provisionals.pop()
1881                {
1882                    else_blocks.push(else_statement);
1883                    self.add_statement(Statement::If {
1884                        condition,
1885                        block,
1886                        else_blocks,
1887                    });
1888                } else {
1889                    unreachable!("BUG");
1890                }
1891            }
1892            _ => return Err(self.syntax_error("不正なEndステートメントです".into())),
1893        }
1894
1895        Ok(())
1896    }
1897
1898    // End Select
1899    fn compose_command_select(&mut self) -> Result<(), SyntaxError> {
1900        let cur_exit_id = self
1901            .nest_of_select
1902            .pop()
1903            .ok_or_else(|| self.syntax_error("不正なEndステートメントです".into()))?;
1904
1905        match self.provisionals.pop() {
1906            Some(Statement::ProvisionalSelectInteger { exit_id, value }) => {
1907                assert!(self.is_select_head, "BUG");
1908                assert!(exit_id == cur_exit_id, "BUG");
1909                self.add_statement(Statement::SelectInteger {
1910                    exit_id,
1911                    value,
1912                    case_blocks: Vec::new(),
1913                });
1914                self.is_select_head = false;
1915            }
1916            Some(Statement::ProvisionalSelectString { exit_id, value }) => {
1917                assert!(self.is_select_head, "BUG");
1918                assert!(exit_id == cur_exit_id, "BUG");
1919                self.add_statement(Statement::SelectString {
1920                    exit_id,
1921                    value,
1922                    case_blocks: Vec::new(),
1923                });
1924                self.is_select_head = false;
1925            }
1926            Some(Statement::ProvisionalCaseInteger { values }) => {
1927                assert!(!self.is_select_head, "BUG");
1928                let block = self.statements.pop().unwrap();
1929                if let Some(Statement::SelectInteger {
1930                    exit_id,
1931                    value,
1932                    mut case_blocks,
1933                }) = self.provisionals.pop()
1934                {
1935                    assert!(exit_id == cur_exit_id, "BUG");
1936                    case_blocks.push(Statement::CaseInteger { values, block });
1937                    self.add_statement(Statement::SelectInteger {
1938                        exit_id,
1939                        value,
1940                        case_blocks,
1941                    });
1942                } else {
1943                    unreachable!("BUG");
1944                }
1945            }
1946            Some(Statement::ProvisionalCaseString { values }) => {
1947                assert!(!self.is_select_head, "BUG");
1948                let block = self.statements.pop().unwrap();
1949                if let Some(Statement::SelectString {
1950                    exit_id,
1951                    value,
1952                    mut case_blocks,
1953                }) = self.provisionals.pop()
1954                {
1955                    assert!(exit_id == cur_exit_id, "BUG");
1956                    case_blocks.push(Statement::CaseString { values, block });
1957                    self.add_statement(Statement::SelectString {
1958                        exit_id,
1959                        value,
1960                        case_blocks,
1961                    });
1962                } else {
1963                    unreachable!("BUG");
1964                }
1965            }
1966            Some(Statement::ProvisionalCaseElse) => {
1967                assert!(!self.is_select_head, "BUG");
1968                let block = self.statements.pop().unwrap();
1969                match self.provisionals.pop() {
1970                    Some(Statement::SelectInteger {
1971                        exit_id,
1972                        value,
1973                        mut case_blocks,
1974                    }) => {
1975                        assert!(exit_id == cur_exit_id, "BUG");
1976                        case_blocks.push(Statement::CaseElse { block });
1977                        self.add_statement(Statement::SelectInteger {
1978                            exit_id,
1979                            value,
1980                            case_blocks,
1981                        });
1982                    }
1983                    Some(Statement::SelectString {
1984                        exit_id,
1985                        value,
1986                        mut case_blocks,
1987                    }) => {
1988                        assert!(exit_id == cur_exit_id, "BUG");
1989                        case_blocks.push(Statement::CaseElse { block });
1990                        self.add_statement(Statement::SelectString {
1991                            exit_id,
1992                            value,
1993                            case_blocks,
1994                        });
1995                    }
1996                    _ => unreachable!("BUG"),
1997                }
1998            }
1999            _ => return Err(self.syntax_error("不正なEndステートメントです".into())),
2000        }
2001
2002        Ok(())
2003    }
2004
2005    // Else
2006    fn parse_command_else(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2007        match pos_and_tokens {
2008            [] => {}
2009            [(_, Token::Keyword(Keyword::If)), rest @ ..] => {
2010                return self.parse_command_elseif(rest)
2011            }
2012            _ => return Err(self.syntax_error("不正なElseステートメントです".into())),
2013        }
2014
2015        let block = self.statements.pop().unwrap(); // 常に self.statements.len() > 0 なので
2016
2017        match self.provisionals.pop() {
2018            Some(Statement::ProvitionalIf { condition }) => {
2019                self.provisionals.push(Statement::If {
2020                    condition,
2021                    block,
2022                    else_blocks: Vec::new(),
2023                });
2024            }
2025            Some(Statement::ProvisionalElseIf { condition }) => {
2026                if let Some(Statement::If { else_blocks, .. }) = self.provisionals.last_mut() {
2027                    else_blocks.push(Statement::ElseIf { condition, block });
2028                } else {
2029                    unreachable!("BUG");
2030                }
2031            }
2032            _ => return Err(self.syntax_error("不正なElseステートメントです".into())),
2033        }
2034
2035        self.provisionals.push(Statement::ProvisionalElse);
2036        self.statements.push(Vec::new());
2037
2038        Ok(())
2039    }
2040
2041    // ElseIf <condition> Then
2042    fn parse_command_elseif(
2043        &mut self,
2044        pos_and_tokens: &[(usize, Token)],
2045    ) -> Result<(), SyntaxError> {
2046        let block = self.statements.pop().unwrap(); // 常に self.statements.len() > 0 なので
2047
2048        match self.provisionals.pop() {
2049            Some(Statement::ProvitionalIf { condition }) => {
2050                self.provisionals.push(Statement::If {
2051                    condition,
2052                    block,
2053                    else_blocks: Vec::new(),
2054                });
2055            }
2056            Some(Statement::ProvisionalElseIf { condition }) => {
2057                if let Some(Statement::If { else_blocks, .. }) = self.provisionals.last_mut() {
2058                    else_blocks.push(Statement::ElseIf { condition, block });
2059                } else {
2060                    unreachable!("BUG");
2061                }
2062            }
2063            _ => return Err(self.syntax_error("不正なElse Ifステートメントです".into())),
2064        }
2065
2066        let condition = if let [rest @ .., (_, Token::Keyword(Keyword::Then))] = pos_and_tokens {
2067            self.parse_expr(rest)?
2068        } else {
2069            return Err(self.syntax_error("不正なElse Ifステートメントです".into()));
2070        };
2071
2072        if !matches!(condition.return_type(), ExprType::Boolean) {
2073            return Err(self.syntax_error("条件式の型が真理値ではありません".into()));
2074        }
2075
2076        self.provisionals
2077            .push(Statement::ProvisionalElseIf { condition });
2078        self.statements.push(Vec::new());
2079
2080        Ok(())
2081    }
2082
2083    // If <condition> Then
2084    fn parse_command_if(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2085        let condition = if let [rest @ .., (_, Token::Keyword(Keyword::Then))] = pos_and_tokens {
2086            self.parse_expr(rest)?
2087        } else {
2088            return Err(self.syntax_error("不正なIfステートメントです".into()));
2089        };
2090
2091        if !matches!(condition.return_type(), ExprType::Boolean) {
2092            return Err(self.syntax_error("条件式の型が真理値ではありません".into()));
2093        }
2094
2095        self.provisionals
2096            .push(Statement::ProvitionalIf { condition });
2097        self.statements.push(Vec::new());
2098
2099        Ok(())
2100    }
2101
2102    // Exit { Do / For / Program / Select }
2103    fn parse_command_exit(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2104        match pos_and_tokens {
2105            [(_, Token::Keyword(Keyword::Do))] => {
2106                if let Some(&exit_id) = self.nest_of_do.last() {
2107                    self.add_statement(Statement::ExitDo { exit_id });
2108                } else {
2109                    return Err(self.syntax_error("この位置にExit Doは置けません".into()));
2110                }
2111            }
2112            [(_, Token::Keyword(Keyword::For))] => {
2113                if let Some((exit_id, _)) = self.nest_of_for.last() {
2114                    let exit_id = *exit_id;
2115                    self.add_statement(Statement::ExitFor { exit_id });
2116                } else {
2117                    return Err(self.syntax_error("この位置にExit Forは置けません".into()));
2118                }
2119            }
2120            [(_, Token::Keyword(Keyword::Sub))] => self.add_statement(Statement::ExitProgram),
2121            [(_, Token::Keyword(Keyword::Select))] => {
2122                if let Some(&exit_id) = self.nest_of_select.last() {
2123                    self.add_statement(Statement::ExitSelect { exit_id });
2124                } else {
2125                    return Err(self.syntax_error("この位置にExit Selectは置けません".into()));
2126                }
2127            }
2128            _ => return Err(self.syntax_error("不正なExitステートメントです".into())),
2129        }
2130
2131        Ok(())
2132    }
2133
2134    // Case <integer/character> [, <integer/character>]*
2135    // Case <string> [, <string>]*
2136    // Case Else
2137    fn parse_command_case(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2138        let select_type = match self.provisionals.pop() {
2139            Some(Statement::ProvisionalSelectInteger { exit_id, value }) => {
2140                assert!(self.is_select_head, "BUG");
2141                self.provisionals.push(Statement::SelectInteger {
2142                    exit_id,
2143                    value,
2144                    case_blocks: vec![],
2145                });
2146                self.is_select_head = false;
2147                ExprType::Integer
2148            }
2149            Some(Statement::ProvisionalSelectString { exit_id, value }) => {
2150                assert!(self.is_select_head, "BUG");
2151                self.provisionals.push(Statement::SelectString {
2152                    exit_id,
2153                    value,
2154                    case_blocks: vec![],
2155                });
2156                self.is_select_head = false;
2157                ExprType::String
2158            }
2159            Some(Statement::ProvisionalCaseInteger { values }) => {
2160                assert!(!self.is_select_head, "BUG");
2161                let block = self.statements.pop().unwrap();
2162                if let Some(Statement::SelectInteger { case_blocks, .. }) =
2163                    self.provisionals.last_mut()
2164                {
2165                    case_blocks.push(Statement::CaseInteger { values, block });
2166                } else {
2167                    unreachable!("BUG");
2168                }
2169                ExprType::Integer
2170            }
2171            Some(Statement::ProvisionalCaseString { values }) => {
2172                assert!(!self.is_select_head, "BUG");
2173                let block = self.statements.pop().unwrap();
2174                if let Some(Statement::SelectString { case_blocks, .. }) =
2175                    self.provisionals.last_mut()
2176                {
2177                    case_blocks.push(Statement::CaseString { values, block });
2178                } else {
2179                    unreachable!("BUG");
2180                }
2181                ExprType::String
2182            }
2183            _ => return Err(self.syntax_error("不正なCaseステートメントです".into())),
2184        };
2185
2186        if matches!(pos_and_tokens, [(_, Token::Keyword(Keyword::Else))]) {
2187            self.provisionals.push(Statement::ProvisionalCaseElse);
2188            self.statements.push(Vec::new());
2189            return Ok(());
2190        }
2191
2192        match self.parse_expr(pos_and_tokens)? {
2193            Expr::LitCharacter(value) => {
2194                if let Some(Statement::SelectInteger { case_blocks, .. }) = self.provisionals.last()
2195                {
2196                    let found_duplicate = case_blocks.iter().any(|s| {
2197                        if let Statement::CaseInteger { values, .. } = s {
2198                            values.iter().any(|v| {
2199                                if let CaseIntegerItem::Character(v) = v {
2200                                    *v == value
2201                                } else {
2202                                    false
2203                                }
2204                            })
2205                        } else {
2206                            unreachable!("BUG");
2207                        }
2208                    });
2209                    if found_duplicate {
2210                        return Err(self
2211                            .syntax_error("Caseステートメントで値の指定に重複があります".into()));
2212                    }
2213                } else {
2214                    unreachable!("BUG");
2215                }
2216                self.provisionals.push(Statement::ProvisionalCaseInteger {
2217                    values: vec![CaseIntegerItem::Character(value)],
2218                });
2219            }
2220            Expr::LitInteger(value) => {
2221                if let Some(Statement::SelectInteger { case_blocks, .. }) = self.provisionals.last()
2222                {
2223                    let found_duplicate = case_blocks.iter().any(|s| {
2224                        if let Statement::CaseInteger { values, .. } = s {
2225                            values.iter().any(|v| {
2226                                if let CaseIntegerItem::Integer(v) = v {
2227                                    *v == value
2228                                } else {
2229                                    false
2230                                }
2231                            })
2232                        } else {
2233                            unreachable!("BUG");
2234                        }
2235                    });
2236                    if found_duplicate {
2237                        return Err(self
2238                            .syntax_error("Caseステートメントで値の指定に重複があります".into()));
2239                    }
2240                } else {
2241                    unreachable!("BUG");
2242                }
2243                self.provisionals.push(Statement::ProvisionalCaseInteger {
2244                    values: vec![CaseIntegerItem::Integer(value)],
2245                });
2246            }
2247            Expr::LitString(value) => {
2248                if let Some(Statement::SelectString { case_blocks, .. }) = self.provisionals.last()
2249                {
2250                    let found_duplicate = case_blocks.iter().any(|s| {
2251                        if let Statement::CaseString { values, .. } = s {
2252                            values.iter().any(|v| v == &value)
2253                        } else {
2254                            unreachable!("BUG");
2255                        }
2256                    });
2257                    if found_duplicate {
2258                        return Err(self
2259                            .syntax_error("Caseステートメントで値の指定に重複があります".into()));
2260                    }
2261                } else {
2262                    unreachable!("BUG");
2263                }
2264                self.provisionals.push(Statement::ProvisionalCaseString {
2265                    values: vec![value],
2266                });
2267            }
2268            Expr::ParamList(values) if matches!(select_type, ExprType::Integer) => {
2269                assert!(values.len() > 1, "BUG");
2270                let values = values
2271                    .into_iter()
2272                    .try_fold(vec![], |mut acc, expr| match expr {
2273                        Expr::LitInteger(value) => {
2274                            acc.push(CaseIntegerItem::Integer(value));
2275                            Ok(acc)
2276                        }
2277                        Expr::LitCharacter(value) => {
2278                            acc.push(CaseIntegerItem::Character(value));
2279                            Ok(acc)
2280                        }
2281                        _ => {
2282                            Err(self.syntax_error("Caseステートメントの値の指定が不正です".into()))
2283                        }
2284                    })?;
2285                if let Some(Statement::SelectInteger { case_blocks, .. }) = self.provisionals.last()
2286                {
2287                    let found_duplicate = values.iter().any(|value| {
2288                        case_blocks.iter().any(|s| {
2289                            if let Statement::CaseInteger { values, .. } = s {
2290                                values.iter().any(|v| v == value)
2291                            } else {
2292                                unreachable!("BUG");
2293                            }
2294                        })
2295                    });
2296                    if found_duplicate {
2297                        return Err(self
2298                            .syntax_error("Caseステートメントで値の指定に重複があります".into()));
2299                    }
2300                } else {
2301                    unreachable!("BUG");
2302                }
2303                self.provisionals
2304                    .push(Statement::ProvisionalCaseInteger { values });
2305            }
2306            Expr::ParamList(values) if matches!(select_type, ExprType::String) => {
2307                assert!(values.len() > 1, "BUG");
2308                let values = values.into_iter().try_fold(vec![], |mut acc, expr| {
2309                    if let Expr::LitString(value) = expr {
2310                        acc.push(value);
2311                        Ok(acc)
2312                    } else {
2313                        Err(self.syntax_error("Caseステートメントの値の指定が不正です".into()))
2314                    }
2315                })?;
2316                if let Some(Statement::SelectString { case_blocks, .. }) = self.provisionals.last()
2317                {
2318                    let found_duplicate = values.iter().any(|value| {
2319                        case_blocks.iter().any(|s| {
2320                            if let Statement::CaseString { values, .. } = s {
2321                                values.iter().any(|v| v == value)
2322                            } else {
2323                                unreachable!("BUG");
2324                            }
2325                        })
2326                    });
2327                    if found_duplicate {
2328                        return Err(self
2329                            .syntax_error("Caseステートメントで値の指定に重複があります".into()));
2330                    }
2331                } else {
2332                    unreachable!("BUG");
2333                }
2334                self.provisionals
2335                    .push(Statement::ProvisionalCaseString { values });
2336            }
2337            _ => return Err(self.syntax_error("不正なCaseステートメントです".into())),
2338        }
2339
2340        self.statements.push(Vec::new());
2341
2342        Ok(())
2343    }
2344
2345    // Select Case <expr>
2346    fn parse_command_select(
2347        &mut self,
2348        pos_and_tokens: &[(usize, Token)],
2349    ) -> Result<(), SyntaxError> {
2350        let exit_id = self.get_new_exit_id();
2351
2352        let statement = match pos_and_tokens {
2353            [(_, Token::Keyword(Keyword::Case)), rest @ ..] | rest @ [_, ..] => {
2354                let value = self.parse_expr(rest)?;
2355                match value.return_type() {
2356                    ExprType::Integer => Statement::ProvisionalSelectInteger { exit_id, value },
2357                    ExprType::String => Statement::ProvisionalSelectString { exit_id, value },
2358                    _ => return Err(self.syntax_error("不正なSelectステートメントです".into())),
2359                }
2360            }
2361            [] => return Err(self.syntax_error("不正なSelectステートメントです".into())),
2362        };
2363
2364        self.is_select_head = true;
2365        self.nest_of_select.push(exit_id);
2366        self.provisionals.push(statement);
2367
2368        Ok(())
2369    }
2370
2371    // Continue { Do / For }
2372    fn parse_command_continue(
2373        &mut self,
2374        pos_and_tokens: &[(usize, Token)],
2375    ) -> Result<(), SyntaxError> {
2376        match pos_and_tokens {
2377            [(_, Token::Keyword(Keyword::Do))] => {
2378                if let Some(&exit_id) = self.nest_of_do.last() {
2379                    self.add_statement(Statement::ContinueDo { exit_id });
2380                } else {
2381                    return Err(self.syntax_error("この位置にContinue Doは置けません".into()));
2382                }
2383            }
2384            [(_, Token::Keyword(Keyword::For))] => {
2385                if let Some((exit_id, _)) = self.nest_of_for.last() {
2386                    let exit_id = *exit_id;
2387                    self.add_statement(Statement::ContinueFor { exit_id });
2388                } else {
2389                    return Err(self.syntax_error("この位置にContinue Forは置けません".into()));
2390                }
2391            }
2392            _ => return Err(self.syntax_error("不正なContinueステートメントです".into())),
2393        }
2394
2395        Ok(())
2396    }
2397
2398    // Loop [{ While / Until } <condition>]
2399    fn parse_command_loop(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2400        let cur_exit_id = self.nest_of_do.pop().ok_or_else(|| {
2401            self.syntax_error("対応するDoステートメントのない不正なLoopステートメントです".into())
2402        })?;
2403
2404        let block = self.statements.pop().unwrap();
2405
2406        if let Some(Statement::ProvisionalDo {
2407            exit_id,
2408            until_condition,
2409            while_condition,
2410        }) = self.provisionals.pop()
2411        {
2412            assert!(exit_id == cur_exit_id, "BUG");
2413            assert!(
2414                until_condition.is_none() || while_condition.is_none(),
2415                "BUG"
2416            );
2417            match pos_and_tokens {
2418                [] => {
2419                    if let Some(condition) = until_condition {
2420                        self.add_statement(Statement::DoUntilLoop {
2421                            exit_id,
2422                            condition,
2423                            block,
2424                        });
2425                    } else if let Some(condition) = while_condition {
2426                        self.add_statement(Statement::DoWhileLoop {
2427                            exit_id,
2428                            condition,
2429                            block,
2430                        });
2431                    } else {
2432                        self.add_statement(Statement::DoLoop { exit_id, block });
2433                    }
2434                }
2435                _ if until_condition.or(while_condition).is_some() => {
2436                    return Err(self.syntax_error("不正なLoopステートメントです".into()))
2437                }
2438                [(pos, Token::Keyword(Keyword::Until)), rest @ ..] => {
2439                    let condition = self.parse_expr(rest)?;
2440                    if !matches!(condition.return_type(), ExprType::Boolean) {
2441                        return Err(self.syntax_error_pos(
2442                            *pos,
2443                            "条件式には真理値式を置く必要があります".into(),
2444                        ));
2445                    }
2446                    self.add_statement(Statement::DoLoopUntil {
2447                        exit_id,
2448                        condition,
2449                        block,
2450                    });
2451                }
2452                [(pos, Token::Keyword(Keyword::While)), rest @ ..] => {
2453                    let condition = self.parse_expr(rest)?;
2454                    if !matches!(condition.return_type(), ExprType::Boolean) {
2455                        return Err(self.syntax_error_pos(
2456                            *pos,
2457                            "条件式には真理値式を置く必要があります".into(),
2458                        ));
2459                    }
2460                    self.add_statement(Statement::DoLoopWhile {
2461                        exit_id,
2462                        condition,
2463                        block,
2464                    });
2465                }
2466                _ => return Err(self.syntax_error("不正なLoopステートメントです".into())),
2467            }
2468        } else {
2469            return Err(self.syntax_error("この位置にLoopステートメントは置けません".into()));
2470        }
2471
2472        Ok(())
2473    }
2474
2475    // Do [{ While / Until } <condition>]
2476    fn parse_command_do(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2477        let exit_id = self.get_new_exit_id();
2478
2479        let statement = match pos_and_tokens {
2480            [] => Statement::ProvisionalDo {
2481                exit_id,
2482                until_condition: None,
2483                while_condition: None,
2484            },
2485            [(pos, Token::Keyword(Keyword::Until)), rest @ ..] => {
2486                let condition = self.parse_expr(rest)?;
2487                if !matches!(condition.return_type(), ExprType::Boolean) {
2488                    return Err(self
2489                        .syntax_error_pos(*pos, "条件式には真理値式を置く必要があります".into()));
2490                }
2491                Statement::ProvisionalDo {
2492                    exit_id,
2493                    until_condition: Some(condition),
2494                    while_condition: None,
2495                }
2496            }
2497            [(pos, Token::Keyword(Keyword::While)), rest @ ..] => {
2498                let condition = self.parse_expr(rest)?;
2499                if !matches!(condition.return_type(), ExprType::Boolean) {
2500                    return Err(self
2501                        .syntax_error_pos(*pos, "条件式には真理値式を置く必要があります".into()));
2502                }
2503                Statement::ProvisionalDo {
2504                    exit_id,
2505                    until_condition: None,
2506                    while_condition: Some(condition),
2507                }
2508            }
2509            _ => return Err(self.syntax_error("不正なDoステートメントです".into())),
2510        };
2511
2512        self.nest_of_do.push(exit_id);
2513        self.statements.push(Vec::new());
2514        self.provisionals.push(statement);
2515
2516        Ok(())
2517    }
2518
2519    // Next [<counter>]
2520    fn parse_command_next(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2521        let name = match pos_and_tokens {
2522            [] => None,
2523            [(_, Token::Name(name))] => Some(name),
2524            _ => return Err(self.syntax_error("不正なNextステートメントです".into())),
2525        };
2526
2527        let (cur_exit_id, _) = self.nest_of_for.pop().ok_or_else(|| {
2528            self.syntax_error("対応するForのない不正なNextステートメントです".into())
2529        })?;
2530
2531        let block = self.statements.pop().unwrap();
2532
2533        if let Some(Statement::ProvisionalFor {
2534            exit_id,
2535            counter,
2536            counter_is_ref,
2537            init,
2538            end,
2539            step,
2540        }) = self.provisionals.pop()
2541        {
2542            assert!(exit_id == cur_exit_id, "BUG");
2543            if name.filter(|name| *name != &counter).is_some() {
2544                return Err(self.syntax_error("カウンタの変数名が一致しません".into()));
2545            }
2546            self.add_statement(Statement::For {
2547                exit_id,
2548                counter,
2549                counter_is_ref,
2550                init,
2551                end,
2552                step,
2553                block,
2554            });
2555        } else {
2556            return Err(self.syntax_error("この位置にNextステートメントは置けません".into()));
2557        }
2558
2559        Ok(())
2560    }
2561
2562    // For <counter> = <init> To <end> [Step <step>]
2563    fn parse_command_for(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2564        let (name, rest) = if let [(_, Token::Name(name)), (_, Token::Operator(Operator::Equal)), rest @ ..] =
2565            pos_and_tokens
2566        {
2567            (name, rest)
2568        } else {
2569            return Err(self.syntax_error("不正なForステートメントです".into()));
2570        };
2571
2572        if self
2573            .nest_of_for
2574            .iter()
2575            .any(|(_, counter)| counter.as_str() == name.as_str())
2576        {
2577            return Err(self.syntax_error(format!(
2578                "同じカウンタ同士のForをネストすることはできません: {}",
2579                name
2580            )));
2581        }
2582
2583        let counter_is_ref = match self.variables.get(name) {
2584            Some(VarType::Integer) => false,
2585            Some(VarType::RefInteger) => true,
2586            _ => return Err(self.syntax_error(format!("カウンタ名が不正です: {}", name))),
2587        };
2588
2589        let to_position = rest
2590            .iter()
2591            .enumerate()
2592            .find(|(_, (_, token))| matches!(token, Token::Keyword(Keyword::To)))
2593            .map(|(i, _)| i)
2594            .ok_or_else(|| self.syntax_error("不正なForステートメントです".into()))?;
2595
2596        let (init, rest) = rest.split_at(to_position);
2597
2598        let step_position = rest
2599            .iter()
2600            .enumerate()
2601            .find(|(_, (_, token))| matches!(token, Token::Keyword(Keyword::Step)))
2602            .map_or(rest.len(), |(i, _)| i);
2603
2604        let (end, step) = rest.split_at(step_position);
2605
2606        let init = self.parse_expr(init)?;
2607        if !matches!(init.return_type(), ExprType::Integer) {
2608            return Err(self.syntax_error("カウンタの初期値の型が不正です".into()));
2609        }
2610
2611        let end = self.parse_expr(&end[1..])?;
2612        if !matches!(end.return_type(), ExprType::Integer) {
2613            return Err(self.syntax_error("終端値の型が不正です".into()));
2614        }
2615
2616        let step = if step.is_empty() {
2617            None
2618        } else {
2619            let step = self.parse_expr(&step[1..])?;
2620            if matches!(step.return_type(), ExprType::Integer) {
2621                Some(step)
2622            } else {
2623                return Err(self.syntax_error("Stepの値の型が不正です".into()));
2624            }
2625        };
2626
2627        let exit_id = self.get_new_exit_id();
2628        self.nest_of_for.push((exit_id, name.clone()));
2629        self.statements.push(Vec::new());
2630        self.provisionals.push(Statement::ProvisionalFor {
2631            exit_id,
2632            counter: name.clone(),
2633            counter_is_ref,
2634            init,
2635            end,
2636            step,
2637        });
2638
2639        Ok(())
2640    }
2641
2642    // Dim <var_name> As { Boolean / Integer / String }
2643    // Dim <arr_name>(<ubound>) As { Boolean / Integer }
2644    fn parse_command_dim(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
2645        if !self.header_state.can_dim() {
2646            return Err(
2647                self.syntax_error("この位置にDimステートメントは置くことができません".into())
2648            );
2649        }
2650        match pos_and_tokens {
2651            // プリミティブ変数の宣言
2652            [(pos, Token::Name(name)), (_, Token::Keyword(Keyword::As)), (_, Token::TypeName(type_name))] =>
2653            {
2654                if self.variables.contains_key(name) {
2655                    return Err(
2656                        self.syntax_error_pos(*pos, format!("変数名が重複しています: {}", name))
2657                    );
2658                }
2659                self.variable_area_size += 1;
2660                let var_type = match type_name {
2661                    TypeName::Boolean => VarType::Boolean,
2662                    TypeName::Integer => VarType::Integer,
2663                    TypeName::String => {
2664                        self.variable_area_size += 256;
2665                        VarType::String
2666                    }
2667                };
2668                self.variables.insert(name.clone(), var_type);
2669                self.add_statement(Statement::Dim {
2670                    var_name: name.clone(),
2671                    var_type,
2672                });
2673            }
2674            // 配列変数の宣言
2675            [(pos_n, Token::Name(name)), (_, Token::Operator(Operator::OpenBracket)), (pos_s, Token::Integer(size)), (_, Token::Operator(Operator::CloseBracket)), (_, Token::Keyword(Keyword::As)), (pos_t, Token::TypeName(type_name))] =>
2676            {
2677                if self.variables.contains_key(name) {
2678                    return Err(
2679                        self.syntax_error_pos(*pos_n, format!("変数名が重複しています: {}", name))
2680                    );
2681                }
2682                let size = self.parse_declare_array_size(*size).ok_or_else(|| {
2683                    self.syntax_error_pos(*pos_s, "配列の大きさの指定が不正です".into())
2684                })?;
2685                self.variable_area_size += size;
2686                let var_type = match type_name {
2687                    TypeName::Boolean => VarType::ArrayOfBoolean(size),
2688                    TypeName::Integer => VarType::ArrayOfInteger(size),
2689                    TypeName::String => {
2690                        return Err(
2691                            self.syntax_error_pos(*pos_t, "この型は配列にはできません".into())
2692                        )
2693                    }
2694                };
2695                self.variables.insert(name.clone(), var_type);
2696                self.add_statement(Statement::Dim {
2697                    var_name: name.clone(),
2698                    var_type,
2699                });
2700            }
2701            _ => return Err(self.syntax_error("不正なDimステートメントです".into())),
2702        }
2703
2704        Ok(())
2705    }
2706
2707    // Input { <var_name> / <arr_name>(<index>) }
2708    fn parse_command_input(
2709        &mut self,
2710        pos_and_tokens: &[(usize, Token)],
2711    ) -> Result<(), SyntaxError> {
2712        match pos_and_tokens {
2713            // プリミティブ変数への入力
2714            [(pos, Token::Name(name))] => match self.variables.get(name) {
2715                Some(VarType::Integer) => {
2716                    self.add_statement(Statement::InputInteger {
2717                        var_name: name.clone(),
2718                    });
2719                }
2720                Some(VarType::RefInteger) => {
2721                    self.add_statement(Statement::InputRefInteger {
2722                        var_name: name.clone(),
2723                    });
2724                }
2725                Some(VarType::String) => {
2726                    self.add_statement(Statement::InputString {
2727                        var_name: name.clone(),
2728                    });
2729                }
2730                Some(VarType::RefString) => {
2731                    self.add_statement(Statement::InputRefString {
2732                        var_name: name.clone(),
2733                    });
2734                }
2735                Some(_) => {
2736                    return Err(self.syntax_error_pos(
2737                        *pos,
2738                        "Inputステートメントに指定できない型の変数です".into(),
2739                    ))
2740                }
2741                None => {
2742                    return Err(
2743                        self.syntax_error_pos(*pos, format!("存在しない変数名です: {}", name))
2744                    )
2745                }
2746            },
2747            // 整数配列の指定位置への入力
2748            [(pos, Token::Name(name)), (_, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
2749            {
2750                let is_ref = match self.variables.get(name) {
2751                    Some(VarType::ArrayOfInteger(_)) => false,
2752                    Some(VarType::RefArrayOfInteger(_)) => true,
2753                    _ => {
2754                        return Err(self.syntax_error_pos(
2755                            *pos,
2756                            "要素へのInputステートメントは整数配列でのみ可能です".into(),
2757                        ))
2758                    }
2759                };
2760                let param = self.parse_expr(inner)?;
2761                if !matches!(param.return_type(), ExprType::Integer) {
2762                    return Err(self.syntax_error_pos(*pos, "インデックスの型が不正です".into()));
2763                }
2764                if is_ref {
2765                    self.add_statement(Statement::InputRefElementInteger {
2766                        var_name: name.clone(),
2767                        index: param,
2768                    });
2769                } else {
2770                    self.add_statement(Statement::InputElementInteger {
2771                        var_name: name.clone(),
2772                        index: param,
2773                    });
2774                }
2775            }
2776            _ => return Err(self.syntax_error("不正なInputステートメントです".into())),
2777        }
2778        Ok(())
2779    }
2780
2781    // Print [ <boolean> / <integer> / <string> / <var_name> / <expr> ]
2782    fn parse_command_print(
2783        &mut self,
2784        pos_and_tokens: &[(usize, Token)],
2785    ) -> Result<(), SyntaxError> {
2786        match pos_and_tokens {
2787            // 空文字列の出力
2788            [] => {
2789                self.add_statement(Statement::PrintLitString { value: "".into() });
2790                return Ok(());
2791            }
2792            // 真理値リテラルの出力
2793            [(_, Token::Boolean(value))] => {
2794                self.add_statement(Statement::PrintLitBoolean { value: *value });
2795                return Ok(());
2796            }
2797            // 整数リテラルの出力
2798            [(pos, Token::Integer(value))] => {
2799                if let Some(value) = validate_integer(false, *value) {
2800                    self.add_statement(Statement::PrintLitInteger { value });
2801                    return Ok(());
2802                } else {
2803                    return Err(
2804                        self.syntax_error_pos(*pos, format!("不正な整数リテラルです: {}", *value))
2805                    );
2806                }
2807            }
2808            // 負符号付きの整数リテラルの出力
2809            [(_, Token::Operator(Operator::Sub)), (pos, Token::Integer(value))] => {
2810                if let Some(value) = validate_integer(true, *value) {
2811                    self.add_statement(Statement::PrintLitInteger { value });
2812                    return Ok(());
2813                } else {
2814                    return Err(
2815                        self.syntax_error_pos(*pos, format!("不正な整数リテラルです: {}", *value))
2816                    );
2817                }
2818            }
2819            // 文字列リテラルの出力
2820            [(_, Token::String(value))] => {
2821                self.add_statement(Statement::PrintLitString {
2822                    value: value.clone(),
2823                });
2824                return Ok(());
2825            }
2826            // プリミティブ変数の出力
2827            [(_, Token::Name(name))] => match self.variables.get(name) {
2828                Some(VarType::Boolean)
2829                | Some(VarType::RefBoolean)
2830                | Some(VarType::Integer)
2831                | Some(VarType::RefInteger)
2832                | Some(VarType::RefString) => {}
2833                Some(VarType::String) => {
2834                    self.add_statement(Statement::PrintVarString {
2835                        var_name: name.clone(),
2836                    });
2837                    return Ok(());
2838                }
2839                _ => return Err(self.syntax_error("不正なPrintステートメントです".into())),
2840            },
2841            _ => {}
2842        }
2843        // 計算結果の出力
2844        let expr = self.parse_expr(pos_and_tokens)?;
2845        match expr.return_type() {
2846            ExprType::Boolean => self.add_statement(Statement::PrintExprBoolan { value: expr }),
2847            ExprType::Integer => self.add_statement(Statement::PrintExprInteger { value: expr }),
2848            ExprType::String => self.add_statement(Statement::PrintExprString { value: expr }),
2849            ExprType::ParamList | ExprType::ReferenceOfVar(..) => {
2850                return Err(self.syntax_error("不正なPrintステートメントです".into()))
2851            }
2852        }
2853        Ok(())
2854    }
2855
2856    // 式の分解
2857    fn parse_expr(&self, pos_and_tokens: &[(usize, Token)]) -> Result<Expr, SyntaxError> {
2858        // 項の最小単位
2859        match pos_and_tokens {
2860            // 空の項は存在してはダメ (構文エラー)
2861            [] => return Err(self.syntax_error("式がありません".into())),
2862
2863            // 真理値リテラル
2864            [(_, Token::Boolean(value))] => return Ok(Expr::LitBoolean(*value)),
2865
2866            // 文字リテラル
2867            [(_, Token::Character(value))] => return Ok(Expr::LitCharacter(*value)),
2868
2869            // 整数リテラル
2870            [(pos, Token::Integer(value))] => {
2871                if let Some(value) = validate_integer(false, *value) {
2872                    return Ok(Expr::LitInteger(value));
2873                } else {
2874                    return Err(
2875                        self.syntax_error_pos(*pos, format!("不正な整数リテラルです: {}", *value))
2876                    );
2877                }
2878            }
2879
2880            // 文字列リテラル
2881            [(_, Token::String(value))] => return Ok(Expr::LitString(value.clone())),
2882
2883            // プリミティブ変数
2884            [(pos, Token::Name(name))] => {
2885                let expr = match self.variables.get(name) {
2886                    Some(VarType::Boolean) => Expr::VarBoolean(name.clone()),
2887                    Some(VarType::Integer) => Expr::VarInteger(name.clone()),
2888                    Some(VarType::String) => Expr::VarString(name.clone()),
2889                    Some(VarType::RefBoolean) => Expr::VarRefBoolean(name.clone()),
2890                    Some(VarType::RefInteger) => Expr::VarRefInteger(name.clone()),
2891                    Some(VarType::RefString) => Expr::VarRefString(name.clone()),
2892                    Some(var_type) => {
2893                        assert!(matches!(
2894                            var_type,
2895                            VarType::ArrayOfBoolean(_)
2896                                | VarType::ArrayOfInteger(_)
2897                                | VarType::RefArrayOfBoolean(_)
2898                                | VarType::RefArrayOfInteger(_)
2899                        ));
2900                        Expr::ReferenceOfVar(name.clone(), *var_type)
2901                    }
2902                    None => {
2903                        return Err(
2904                            self.syntax_error_pos(*pos, format!("存在しない変数名です: {}", name))
2905                        )
2906                    }
2907                };
2908                return Ok(expr);
2909            }
2910
2911            // 単項演算子と真理値
2912            [(_, Token::Operator(op)), (_, Token::Boolean(value))] if op.can_be_unary_boolean() => {
2913                return Ok(Expr::UnaryOperatorBoolean(
2914                    *op,
2915                    Box::new(Expr::LitBoolean(*value)),
2916                ))
2917            }
2918
2919            // 単項演算子マイナスと整数
2920            [(_, Token::Operator(Operator::Sub)), (pos, Token::Integer(value))] => {
2921                if let Some(value) = validate_integer(true, *value) {
2922                    return Ok(Expr::LitInteger(value));
2923                } else {
2924                    return Err(
2925                        self.syntax_error_pos(*pos, format!("不正な整数リテラルです: -{}", *value))
2926                    );
2927                }
2928            }
2929
2930            // 単項演算子と整数
2931            [(_, Token::Operator(op)), (pos, Token::Integer(value))]
2932                if op.can_be_unary_integer() =>
2933            {
2934                if let Some(value) = validate_integer(false, *value) {
2935                    return Ok(Expr::UnaryOperatorInteger(
2936                        *op,
2937                        Box::new(Expr::LitInteger(value)),
2938                    ));
2939                } else {
2940                    return Err(
2941                        self.syntax_error_pos(*pos, format!("不正な整数リテラルです: {}", *value))
2942                    );
2943                }
2944            }
2945
2946            // 単項演算子と変数(真理値or整数)
2947            [(_, Token::Operator(op)), (pos, Token::Name(name))] if op.can_be_unary() => {
2948                match self.variables.get(name) {
2949                    Some(VarType::Boolean) if op.can_be_unary_boolean() => {
2950                        return Ok(Expr::UnaryOperatorBoolean(
2951                            *op,
2952                            Box::new(Expr::VarBoolean(name.clone())),
2953                        ))
2954                    }
2955                    Some(VarType::RefBoolean) if op.can_be_unary_boolean() => {
2956                        return Ok(Expr::UnaryOperatorBoolean(
2957                            *op,
2958                            Box::new(Expr::VarRefBoolean(name.clone())),
2959                        ))
2960                    }
2961                    Some(VarType::Integer) if op.can_be_unary_integer() => {
2962                        return Ok(Expr::UnaryOperatorInteger(
2963                            *op,
2964                            Box::new(Expr::VarInteger(name.clone())),
2965                        ))
2966                    }
2967                    Some(VarType::RefInteger) if op.can_be_unary_integer() => {
2968                        return Ok(Expr::UnaryOperatorInteger(
2969                            *op,
2970                            Box::new(Expr::VarRefInteger(name.clone())),
2971                        ))
2972                    }
2973                    Some(_) => return Err(self.syntax_error_pos(*pos, "不正な式です".into())),
2974                    None => {
2975                        return Err(
2976                            self.syntax_error_pos(*pos, format!("存在しない変数名です: {}", name))
2977                        )
2978                    }
2979                }
2980            }
2981
2982            // 存在してはいけないトークン列 (構文エラー)
2983            [(pos, token)] | [(pos, token), (_, _)] => {
2984                return Err(self.syntax_error_pos(*pos, format!("不正な式です: {:?}", token)))
2985            }
2986
2987            // 他はここでは処理しない
2988            _ => {}
2989        }
2990
2991        // 外側の演算子のうち一番右のを抽出する (括弧のネストに気をつける)
2992        //    項 op1 項 op2 項 op1 ... op2 項
2993        //   -> (項 op1 項 op2 項 op1 ...) op2 (項)
2994        //   分割して再帰的に処理していく
2995
2996        // 分割点となる演算子の抜き出し
2997        let mut target_op: Option<(usize, Operator)> = None;
2998        let mut next_unary = true;
2999        let mut next_term = true;
3000        let mut bracket_count = 0;
3001        for (i, (pos, token)) in pos_and_tokens.iter().enumerate() {
3002            if bracket_count > 0 {
3003                match token {
3004                    Token::Operator(Operator::OpenBracket) => bracket_count += 1,
3005                    Token::Operator(Operator::CloseBracket) => bracket_count -= 1,
3006                    _ => {}
3007                }
3008                continue;
3009            }
3010            if let Token::Operator(op) = token {
3011                if matches!(op, Operator::OpenBracket) {
3012                    bracket_count += 1;
3013                    next_unary = false;
3014                    next_term = false;
3015                    continue;
3016                }
3017                if next_unary {
3018                    // 単項演算子をそのまま重ねることは禁止
3019                    //  NG:  Not Not Not -123
3020                    //  OK:  Not (Not (Not (-123)))
3021                    if op.can_be_unary() {
3022                        next_unary = false;
3023                    } else {
3024                        return Err(self.syntax_error_pos(*pos, "不正な式です".into()));
3025                    }
3026                } else if op.can_be_binary() {
3027                    if target_op
3028                        .filter(|(_, cur_op)| cur_op.priority() > op.priority())
3029                        .is_none()
3030                    {
3031                        target_op = Some((i, *op));
3032                    }
3033                    next_unary = true;
3034                    next_term = true;
3035                } else {
3036                    return Err(self.syntax_error_pos(*pos, "不正な式です".into()));
3037                }
3038            } else {
3039                if !next_term {
3040                    return Err(self.syntax_error_pos(*pos, "不正な式です".into()));
3041                }
3042                next_unary = false;
3043                next_term = false;
3044            }
3045        }
3046
3047        if bracket_count > 0 || next_unary || next_term {
3048            return Err(self.syntax_error("不正な式です".into()));
3049        }
3050
3051        // 分割して再帰的に処理していく
3052        if let Some((i, op)) = target_op {
3053            let lhs = self.parse_expr(&pos_and_tokens[..i])?;
3054            let rhs = self.parse_expr(&pos_and_tokens[i + 1..])?;
3055            return Expr::binary(op, lhs, rhs).ok_or_else(|| {
3056                let (pos, _) = pos_and_tokens[i];
3057                self.syntax_error_pos(pos, "不正な式です".into())
3058            });
3059        }
3060
3061        // 外側の演算子がない場合、つまり、項が1つ
3062        // 構文ミスが無い場合は
3063        //    [unary-op] ( 式 )
3064        //    [unary-op] Array ( 引数 ) ' 要素取り出し
3065        //    [unary-op] Func ( 引数 )
3066        //    VarString ( 引数 ) ' 文字取り出し
3067        //    LitString ( 引数 ) ' 文字取り出し
3068        //    のどれかのハズ
3069        //    ※引数なし関数は定義しない ()
3070        //    ※配列自体や関数自体は計算結果として現れないため (CInt)("123")
3071        //    ※関数自体を持つ変数は作れないとするため 変数(引数) は現れない
3072        //    ※一時的に生成される文字列から文字取り出しはできないとする (s1 & s2 & "XYZ")(1) など
3073        // 構文ミスがある場合は例えば、項を繋ぐ演算子が無い場合
3074        //     値 ( 式 ) ( 式 ) 値 Func 値 ( 引数 ) unary-op 値
3075
3076        match pos_and_tokens {
3077            // 単項演算子の分離
3078            [(pos, Token::Operator(op)), rest @ ..] if op.can_be_unary() => {
3079                let expr = self.parse_expr(rest)?;
3080                match expr.return_type() {
3081                    ExprType::Boolean if op.can_be_unary_boolean() => {
3082                        Ok(Expr::UnaryOperatorBoolean(*op, Box::new(expr)))
3083                    }
3084                    ExprType::Integer if op.can_be_unary_integer() => {
3085                        Ok(Expr::UnaryOperatorInteger(*op, Box::new(expr)))
3086                    }
3087                    _ => Err(self.syntax_error_pos(*pos, "不正な式です".into())),
3088                }
3089            }
3090
3091            // ( 式 )
3092            [(_, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] => {
3093                self.parse_expr(inner)
3094            }
3095
3096            // 文字列リテラル ( 添え字 )
3097            [(_, Token::String(text)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3098            {
3099                let expr = self.parse_expr(inner)?;
3100                if matches!(expr.return_type(), ExprType::Integer) {
3101                    Ok(Expr::CharOfLitString(text.clone(), Box::new(expr)))
3102                } else {
3103                    Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3104                }
3105            }
3106
3107            // 配列変数 ( 添え字 )  もしくは  文字列変数 ( 添え字 )
3108            [(pos_n, Token::Name(name)), (pos_e, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3109            {
3110                let expr = self.parse_expr(inner)?;
3111                if !matches!(expr.return_type(), ExprType::Integer) {
3112                    Err(self.syntax_error_pos(*pos_e, "不正な式です".into()))
3113                } else {
3114                    match self.variables.get(name) {
3115                        Some(VarType::ArrayOfBoolean(_)) => {
3116                            Ok(Expr::VarArrayOfBoolean(name.clone(), Box::new(expr)))
3117                        }
3118                        Some(VarType::RefArrayOfBoolean(_)) => {
3119                            Ok(Expr::VarRefArrayOfBoolean(name.clone(), Box::new(expr)))
3120                        }
3121                        Some(VarType::ArrayOfInteger(_)) => {
3122                            Ok(Expr::VarArrayOfInteger(name.clone(), Box::new(expr)))
3123                        }
3124                        Some(VarType::RefArrayOfInteger(_)) => {
3125                            Ok(Expr::VarRefArrayOfInteger(name.clone(), Box::new(expr)))
3126                        }
3127                        Some(VarType::String) => {
3128                            Ok(Expr::CharOfVarString(name.clone(), Box::new(expr)))
3129                        }
3130                        Some(VarType::RefString) => {
3131                            Ok(Expr::CharOfVarRefString(name.clone(), Box::new(expr)))
3132                        }
3133                        Some(_) => Err(self.syntax_error_pos(*pos_n, "不正な式です".into())),
3134                        None => Err(self
3135                            .syntax_error_pos(*pos_n, format!("存在しない変数名です: {}", name))),
3136                    }
3137                }
3138            }
3139
3140            // 関数 ( )  ※引数なし関数
3141            [(_, Token::Function(function)), (pos, Token::Operator(Operator::OpenBracket)), (_, Token::Operator(Operator::CloseBracket))] => {
3142                if matches!(function, Function::Eof) {
3143                    Ok(Expr::FunctionBoolean(
3144                        *function,
3145                        Box::new(Expr::LitInteger(0)),
3146                    ))
3147                } else {
3148                    Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3149                }
3150            }
3151
3152            // 関数 Array ( 引数 )
3153            [(_, Token::Function(Function::Array)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3154            {
3155                let param = self.parse_expr(inner)?;
3156                match &param {
3157                    Expr::ParamList(list) if (1..=MAX_ARRAY_SIZE).contains(&list.len()) => {
3158                        let size = list.len();
3159                        if list
3160                            .iter()
3161                            .all(|expr| matches!(expr.return_type(), ExprType::Boolean))
3162                        {
3163                            return Ok(Expr::FunctionBooleanArray(
3164                                size,
3165                                Function::Array,
3166                                Box::new(param),
3167                            ));
3168                        } else if list
3169                            .iter()
3170                            .all(|expr| matches!(expr.return_type(), ExprType::Integer))
3171                        {
3172                            return Ok(Expr::FunctionIntegerArray(
3173                                size,
3174                                Function::Array,
3175                                Box::new(param),
3176                            ));
3177                        }
3178                    }
3179                    _ if matches!(param.return_type(), ExprType::Boolean) => {
3180                        return Ok(Expr::FunctionBooleanArray(
3181                            1,
3182                            Function::Array,
3183                            Box::new(param),
3184                        ));
3185                    }
3186                    _ if matches!(param.return_type(), ExprType::Integer) => {
3187                        return Ok(Expr::FunctionIntegerArray(
3188                            1,
3189                            Function::Array,
3190                            Box::new(param),
3191                        ));
3192                    }
3193                    _ => {}
3194                }
3195                Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3196            }
3197
3198            // 関数 SubArray ( 引数 )
3199            [(_, Token::Function(Function::SubArray)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3200            {
3201                let mut param = self.parse_expr(inner)?;
3202                if let Expr::ParamList(list) = &mut param {
3203                    match list.as_mut_slice() {
3204                        [Expr::FunctionBooleanArray(size, ..), offset, Expr::LitInteger(len)]
3205                        | [Expr::ReferenceOfVar(_, VarType::ArrayOfBoolean(size)), offset, Expr::LitInteger(len)]
3206                        | [Expr::ReferenceOfVar(_, VarType::RefArrayOfBoolean(size)), offset, Expr::LitInteger(len)] => {
3207                            if matches!(offset.return_type(), ExprType::Integer) {
3208                                if let Some(size) = self.parse_size_for_array_function(*size, *len)
3209                                {
3210                                    *len = size as i32;
3211                                    return Ok(Expr::FunctionBooleanArray(
3212                                        size,
3213                                        Function::SubArray,
3214                                        Box::new(param),
3215                                    ));
3216                                }
3217                            }
3218                        }
3219                        [Expr::FunctionIntegerArray(size, ..), offset, Expr::LitInteger(len)]
3220                        | [Expr::ReferenceOfVar(_, VarType::ArrayOfInteger(size)), offset, Expr::LitInteger(len)]
3221                        | [Expr::ReferenceOfVar(_, VarType::RefArrayOfInteger(size)), offset, Expr::LitInteger(len)] => {
3222                            if matches!(offset.return_type(), ExprType::Integer) {
3223                                if let Some(size) = self.parse_size_for_array_function(*size, *len)
3224                                {
3225                                    *len = size as i32;
3226                                    return Ok(Expr::FunctionIntegerArray(
3227                                        size,
3228                                        Function::SubArray,
3229                                        Box::new(param),
3230                                    ));
3231                                }
3232                            }
3233                        }
3234                        [expr, offset, Expr::LitInteger(_)]
3235                            if matches!(offset.return_type(), ExprType::Integer)
3236                                && (expr.return_type().is_bool_array()
3237                                    || expr.return_type().is_int_array()) =>
3238                        {
3239                            unreachable!("BUG")
3240                        }
3241                        _ => {}
3242                    }
3243                }
3244                Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3245            }
3246
3247            // 関数 CArray ( 引数 )
3248            [(_, Token::Function(Function::CArray)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3249            {
3250                let mut param = self.parse_expr(inner)?;
3251                if let Expr::ParamList(list) = &mut param {
3252                    if let [expr, Expr::LitInteger(len)] = list.as_mut_slice() {
3253                        if let Some(size) = self.parse_size_for_array_function(MAX_ARRAY_SIZE, *len)
3254                        {
3255                            if expr.return_type().is_bool_array() {
3256                                *len = size as i32;
3257                                return Ok(Expr::FunctionBooleanArray(
3258                                    size,
3259                                    Function::CArray,
3260                                    Box::new(param),
3261                                ));
3262                            } else if matches!(expr.return_type(), ExprType::String)
3263                                || expr.return_type().is_int_array()
3264                            {
3265                                *len = size as i32;
3266                                return Ok(Expr::FunctionIntegerArray(
3267                                    size,
3268                                    Function::CArray,
3269                                    Box::new(param),
3270                                ));
3271                            }
3272                        }
3273                    }
3274                }
3275                Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3276            }
3277
3278            // 関数 String( 引数 )
3279            [(_, Token::TypeName(TypeName::String)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3280            {
3281                let param = self.parse_expr(inner)?;
3282                if let Expr::ParamList(list) = &param {
3283                    if list.len() == 2
3284                        && list
3285                            .iter()
3286                            .all(|expr| matches!(expr.return_type(), ExprType::Integer))
3287                    {
3288                        return Ok(Expr::FunctionString(Function::String, Box::new(param)));
3289                    }
3290                } else if param.return_type().is_int_array() {
3291                    return Ok(Expr::FunctionString(Function::String, Box::new(param)));
3292                }
3293                Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3294            }
3295
3296            // 関数 ( 引数 )
3297            [(_, Token::Function(function)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3298            {
3299                let param = self.parse_expr(inner)?;
3300                if !function.check_param(&param) {
3301                    Err(self.syntax_error_pos(*pos, "不正な式です".into()))
3302                } else {
3303                    match function.return_type() {
3304                        ExprType::Boolean => Ok(Expr::FunctionBoolean(*function, Box::new(param))),
3305                        ExprType::Integer => Ok(Expr::FunctionInteger(*function, Box::new(param))),
3306                        ExprType::String => Ok(Expr::FunctionString(*function, Box::new(param))),
3307                        _ => Err(self.syntax_error_pos(*pos, "不正な式です".into())),
3308                    }
3309                }
3310            }
3311
3312            // 該当なし (構文エラー)
3313            _ => Err(self.syntax_error("不正な式です".into())),
3314        }
3315    }
3316}
3317
3318fn validate_integer(minus: bool, value: i32) -> Option<i32> {
3319    if minus {
3320        Some((-value) as i16 as i32)
3321    } else if value < (i16::MIN as i32).abs() {
3322        Some(value)
3323    } else {
3324        None
3325    }
3326}
3327
3328trait KeywordExtension {
3329    fn is_toplevel_token(&self) -> bool;
3330}
3331
3332impl KeywordExtension for Keyword {
3333    fn is_toplevel_token(&self) -> bool {
3334        use Keyword::*;
3335        match self {
3336            Argument | ByRef | ByVal | Call | Case | Continue | Else | ElseIf | End | Exit
3337            | Extern | Dim | Do | Fill | For | If | Input | Loop | Mid | Next | Option | Print
3338            | Select | Sub => true,
3339
3340            As | From | Rem | Step | Then | To | Until | While | With => false,
3341        }
3342    }
3343}
3344
3345trait OperatorExtension<T> {
3346    fn can_be_binary(&self) -> bool;
3347    fn can_be_unary(&self) -> bool;
3348    fn can_be_unary_integer(&self) -> bool;
3349    fn can_be_unary_boolean(&self) -> bool;
3350    fn priority(&self) -> i32;
3351}
3352
3353impl OperatorExtension<Operator> for Operator {
3354    fn can_be_binary(&self) -> bool {
3355        !matches!(
3356            self,
3357            Operator::Not
3358                | Operator::OpenBracket
3359                | Operator::CloseBracket
3360                | Operator::AddInto
3361                | Operator::SubInto
3362        )
3363    }
3364
3365    fn can_be_unary(&self) -> bool {
3366        matches!(self, Operator::Sub | Operator::Not)
3367    }
3368
3369    fn can_be_unary_integer(&self) -> bool {
3370        matches!(self, Operator::Sub | Operator::Not)
3371    }
3372
3373    fn can_be_unary_boolean(&self) -> bool {
3374        matches!(self, Operator::Not)
3375    }
3376
3377    fn priority(&self) -> i32 {
3378        use Operator::*;
3379        match self {
3380            OpenBracket | CloseBracket | AddInto | SubInto => 0,
3381
3382            Not => 2,
3383
3384            ShiftLeftArithmetic | ShiftRightArithmetic | ShiftLeftLogical | ShiftRightLogical => 4,
3385
3386            Mul | Div | Mod => 6,
3387
3388            Add | Sub | Concat => 8,
3389
3390            LessOrEequal | GreaterOrEqual | LessThan | GreaterThan => 12,
3391
3392            Equal | NotEqual => 14,
3393
3394            And | Or | Xor => 16,
3395
3396            Comma => 18,
3397        }
3398    }
3399}
3400
3401#[derive(PartialEq, Eq, Clone, Debug)]
3402pub struct ArgumentInfo {
3403    pub var_name: String,
3404    pub var_type: VarType,
3405    pub register1: IndexRegister,
3406    pub register2: Option<IndexRegister>,
3407}
3408
3409impl ArgumentInfo {
3410    fn is_valid_type(&self, expr: &Expr) -> bool {
3411        match self.var_type {
3412            VarType::Boolean | VarType::RefBoolean => {
3413                matches!(expr.return_type(), ExprType::Boolean)
3414            }
3415            VarType::Integer | VarType::RefInteger => {
3416                matches!(expr.return_type(), ExprType::Integer)
3417            }
3418            VarType::String | VarType::RefString => matches!(expr.return_type(), ExprType::String),
3419            VarType::ArrayOfBoolean(size1) | VarType::RefArrayOfBoolean(size1) => {
3420                match expr.return_type() {
3421                    ExprType::ReferenceOfVar(VarType::ArrayOfBoolean(size2))
3422                    | ExprType::ReferenceOfVar(VarType::RefArrayOfBoolean(size2)) => size1 == size2,
3423                    _ => false,
3424                }
3425            }
3426            VarType::ArrayOfInteger(size1) | VarType::RefArrayOfInteger(size1) => {
3427                match expr.return_type() {
3428                    ExprType::ReferenceOfVar(VarType::ArrayOfInteger(size2))
3429                    | ExprType::ReferenceOfVar(VarType::RefArrayOfInteger(size2)) => size1 == size2,
3430                    _ => false,
3431                }
3432            }
3433        }
3434    }
3435}
3436
3437#[derive(PartialEq, Eq, Clone, Debug)]
3438pub enum CompileOption {
3439    ArraySize {
3440        length: bool,
3441        all: bool,
3442    },
3443    Eof {
3444        common: bool,
3445    },
3446    Register {
3447        restore: bool,
3448    },
3449    Allocator {
3450        enabled: bool,
3451        common: bool,
3452        size: usize,
3453    },
3454    Variable {
3455        initialize: bool,
3456    },
3457}
3458
3459#[derive(PartialEq, Eq, Clone, Debug)]
3460pub enum Statement {
3461    CompileOption {
3462        option: CompileOption,
3463    },
3464    ProgramName {
3465        name: String,
3466    },
3467    ExitProgram,
3468    ExternSub {
3469        name: String,
3470        arguments: Vec<ArgumentInfo>,
3471    },
3472    Argument {
3473        arguments: Vec<ArgumentInfo>,
3474    },
3475    Call {
3476        name: String,
3477        arguments: Vec<(String, Expr)>,
3478    },
3479    AssignAddInto {
3480        var_name: String,
3481        value: Expr,
3482    },
3483    AssignRefAddInto {
3484        var_name: String,
3485        value: Expr,
3486    },
3487    AssignAddIntoElement {
3488        var_name: String,
3489        index: Expr,
3490        value: Expr,
3491    },
3492    AssignRefAddIntoElement {
3493        var_name: String,
3494        index: Expr,
3495        value: Expr,
3496    },
3497    AssignBoolean {
3498        var_name: String,
3499        value: Expr,
3500    },
3501    AssignRefBoolean {
3502        var_name: String,
3503        value: Expr,
3504    },
3505    AssignBooleanElement {
3506        var_name: String,
3507        index: Expr,
3508        value: Expr,
3509    },
3510    AssignRefBooleanElement {
3511        var_name: String,
3512        index: Expr,
3513        value: Expr,
3514    },
3515    AssignIntegerElement {
3516        var_name: String,
3517        index: Expr,
3518        value: Expr,
3519    },
3520    AssignRefIntegerElement {
3521        var_name: String,
3522        index: Expr,
3523        value: Expr,
3524    },
3525    AssignCharacterElement {
3526        var_name: String,
3527        index: Expr,
3528        value: Expr,
3529    },
3530    AssignRefCharacterElement {
3531        var_name: String,
3532        index: Expr,
3533        value: Expr,
3534    },
3535    AssignInteger {
3536        var_name: String,
3537        value: Expr,
3538    },
3539    AssignRefInteger {
3540        var_name: String,
3541        value: Expr,
3542    },
3543    AssignString {
3544        var_name: String,
3545        value: Expr,
3546    },
3547    AssignRefString {
3548        var_name: String,
3549        value: Expr,
3550    },
3551    AssignSubInto {
3552        var_name: String,
3553        value: Expr,
3554    },
3555    AssignRefSubInto {
3556        var_name: String,
3557        value: Expr,
3558    },
3559    AssignSubIntoElement {
3560        var_name: String,
3561        index: Expr,
3562        value: Expr,
3563    },
3564    AssignRefSubIntoElement {
3565        var_name: String,
3566        index: Expr,
3567        value: Expr,
3568    },
3569    AssignBooleanArray {
3570        var_name: String,
3571        value: Expr,
3572    },
3573    AssignRefBooleanArray {
3574        var_name: String,
3575        value: Expr,
3576    },
3577    AssignIntegerArray {
3578        var_name: String,
3579        value: Expr,
3580    },
3581    AssignRefIntegerArray {
3582        var_name: String,
3583        value: Expr,
3584    },
3585    ContinueDo {
3586        exit_id: usize,
3587    },
3588    ContinueFor {
3589        exit_id: usize,
3590    },
3591    Dim {
3592        var_name: String,
3593        var_type: VarType,
3594    },
3595    Mid {
3596        var_name: String,
3597        var_is_ref: bool,
3598        offset: Expr,
3599        length: Option<Expr>,
3600        value: Expr,
3601    },
3602    DoLoop {
3603        exit_id: usize,
3604        block: Vec<Statement>,
3605    },
3606    DoLoopUntil {
3607        exit_id: usize,
3608        condition: Expr,
3609        block: Vec<Statement>,
3610    },
3611    DoLoopWhile {
3612        exit_id: usize,
3613        condition: Expr,
3614        block: Vec<Statement>,
3615    },
3616    DoUntilLoop {
3617        exit_id: usize,
3618        condition: Expr,
3619        block: Vec<Statement>,
3620    },
3621    DoWhileLoop {
3622        exit_id: usize,
3623        condition: Expr,
3624        block: Vec<Statement>,
3625    },
3626    ProvisionalDo {
3627        exit_id: usize,
3628        until_condition: Option<Expr>,
3629        while_condition: Option<Expr>,
3630    },
3631    ExitDo {
3632        exit_id: usize,
3633    },
3634    ExitFor {
3635        exit_id: usize,
3636    },
3637    ExitSelect {
3638        exit_id: usize,
3639    },
3640    For {
3641        exit_id: usize,
3642        counter: String,
3643        counter_is_ref: bool,
3644        init: Expr,
3645        end: Expr,
3646        step: Option<Expr>,
3647        block: Vec<Statement>,
3648    },
3649    ProvisionalFor {
3650        exit_id: usize,
3651        counter: String,
3652        counter_is_ref: bool,
3653        init: Expr,
3654        end: Expr,
3655        step: Option<Expr>,
3656    },
3657    If {
3658        condition: Expr,
3659        block: Vec<Statement>,
3660        else_blocks: Vec<Statement>,
3661    },
3662    ProvitionalIf {
3663        condition: Expr,
3664    },
3665    ElseIf {
3666        condition: Expr,
3667        block: Vec<Statement>,
3668    },
3669    ProvisionalElseIf {
3670        condition: Expr,
3671    },
3672    Else {
3673        block: Vec<Statement>,
3674    },
3675    ProvisionalElse,
3676    SelectInteger {
3677        exit_id: usize,
3678        value: Expr,
3679        case_blocks: Vec<Statement>,
3680    },
3681    ProvisionalSelectInteger {
3682        exit_id: usize,
3683        value: Expr,
3684    },
3685    CaseInteger {
3686        values: Vec<CaseIntegerItem>,
3687        block: Vec<Statement>,
3688    },
3689    ProvisionalCaseInteger {
3690        values: Vec<CaseIntegerItem>,
3691    },
3692    SelectString {
3693        exit_id: usize,
3694        value: Expr,
3695        case_blocks: Vec<Statement>,
3696    },
3697    ProvisionalSelectString {
3698        exit_id: usize,
3699        value: Expr,
3700    },
3701    CaseString {
3702        values: Vec<String>,
3703        block: Vec<Statement>,
3704    },
3705    ProvisionalCaseString {
3706        values: Vec<String>,
3707    },
3708    CaseElse {
3709        block: Vec<Statement>,
3710    },
3711    ProvisionalCaseElse,
3712    InputElementInteger {
3713        var_name: String,
3714        index: Expr,
3715    },
3716    InputInteger {
3717        var_name: String,
3718    },
3719    InputString {
3720        var_name: String,
3721    },
3722    InputRefElementInteger {
3723        var_name: String,
3724        index: Expr,
3725    },
3726    InputRefInteger {
3727        var_name: String,
3728    },
3729    InputRefString {
3730        var_name: String,
3731    },
3732    PrintLitBoolean {
3733        value: bool,
3734    },
3735    PrintLitInteger {
3736        value: i32,
3737    },
3738    PrintLitString {
3739        value: String,
3740    },
3741    PrintVarString {
3742        var_name: String,
3743    },
3744    PrintExprBoolan {
3745        value: Expr,
3746    },
3747    PrintExprInteger {
3748        value: Expr,
3749    },
3750    PrintExprString {
3751        value: Expr,
3752    },
3753    FillArrayOfBoolean {
3754        var_name: String,
3755        value: Expr,
3756    },
3757    FillRefArrayOfBoolean {
3758        var_name: String,
3759        value: Expr,
3760    },
3761    FillArrayOfInteger {
3762        var_name: String,
3763        value: Expr,
3764    },
3765    FillRefArrayOfInteger {
3766        var_name: String,
3767        value: Expr,
3768    },
3769    FillString {
3770        var_name: String,
3771        value: Expr,
3772    },
3773    FillRefString {
3774        var_name: String,
3775        value: Expr,
3776    },
3777}
3778
3779#[derive(PartialEq, Eq, Clone, Copy, Debug)]
3780pub enum CaseIntegerItem {
3781    Integer(i32),
3782    Character(char),
3783}
3784
3785#[derive(PartialEq, Eq, Clone, Copy, Debug)]
3786pub enum VarType {
3787    Boolean,
3788    Integer,
3789    String,
3790    ArrayOfBoolean(usize),
3791    ArrayOfInteger(usize),
3792    RefBoolean,
3793    RefInteger,
3794    RefString,
3795    RefArrayOfBoolean(usize),
3796    RefArrayOfInteger(usize),
3797}
3798
3799#[derive(PartialEq, Eq, Clone, Copy, Debug)]
3800pub enum ExprType {
3801    Boolean,
3802    Integer,
3803    String,
3804    ParamList,
3805    ReferenceOfVar(VarType), // 現状は配列タイプのみ
3806}
3807
3808#[derive(PartialEq, Eq, Clone, Debug)]
3809pub enum Expr {
3810    BinaryOperatorBoolean(Operator, Box<Expr>, Box<Expr>),
3811    BinaryOperatorInteger(Operator, Box<Expr>, Box<Expr>),
3812    BinaryOperatorString(Operator, Box<Expr>, Box<Expr>),
3813    CharOfLitString(String, Box<Expr>),
3814    CharOfVarString(String, Box<Expr>),
3815    CharOfVarRefString(String, Box<Expr>),
3816    FunctionBoolean(Function, Box<Expr>),
3817    FunctionInteger(Function, Box<Expr>),
3818    FunctionString(Function, Box<Expr>),
3819    FunctionBooleanArray(usize, Function, Box<Expr>),
3820    FunctionIntegerArray(usize, Function, Box<Expr>),
3821    LitBoolean(bool),
3822    LitInteger(i32),
3823    LitString(String),
3824    LitCharacter(char),
3825    UnaryOperatorInteger(Operator, Box<Expr>),
3826    UnaryOperatorBoolean(Operator, Box<Expr>),
3827    VarBoolean(String),
3828    VarInteger(String),
3829    VarString(String),
3830    VarRefBoolean(String),
3831    VarRefInteger(String),
3832    VarRefString(String),
3833    VarArrayOfBoolean(String, Box<Expr>), // 命名が悪い、配列の要素を返すExpr, (変数名,インデックス)
3834    VarArrayOfInteger(String, Box<Expr>), // 同上
3835    VarRefArrayOfBoolean(String, Box<Expr>), // 同上
3836    VarRefArrayOfInteger(String, Box<Expr>), // 同上
3837    ReferenceOfVar(String, VarType),      // 現状、配列への参照を持つ用 (変数名,型)
3838    ParamList(Vec<Expr>),
3839}
3840
3841impl VarType {
3842    pub fn is_reference(&self) -> bool {
3843        use VarType::*;
3844        match self {
3845            Boolean | Integer | String | ArrayOfBoolean(..) | ArrayOfInteger(..) => false,
3846
3847            RefBoolean | RefInteger | RefString | RefArrayOfBoolean(..) | RefArrayOfInteger(..) => {
3848                true
3849            }
3850        }
3851    }
3852
3853    pub fn get_array_size(&self) -> Option<usize> {
3854        use VarType::*;
3855        match self {
3856            Boolean | Integer | String | RefBoolean | RefInteger | RefString => None,
3857
3858            ArrayOfBoolean(size)
3859            | ArrayOfInteger(size)
3860            | RefArrayOfBoolean(size)
3861            | RefArrayOfInteger(size) => Some(*size),
3862        }
3863    }
3864
3865    pub fn is_boolean(&self) -> bool {
3866        use VarType::*;
3867        match self {
3868            Boolean | RefBoolean => true,
3869
3870            Integer
3871            | String
3872            | RefInteger
3873            | RefString
3874            | ArrayOfBoolean(..)
3875            | ArrayOfInteger(..)
3876            | RefArrayOfBoolean(..)
3877            | RefArrayOfInteger(..) => false,
3878        }
3879    }
3880
3881    pub fn is_integer(&self) -> bool {
3882        use VarType::*;
3883        match self {
3884            Integer | RefInteger => true,
3885
3886            Boolean
3887            | RefBoolean
3888            | String
3889            | RefString
3890            | ArrayOfBoolean(..)
3891            | ArrayOfInteger(..)
3892            | RefArrayOfBoolean(..)
3893            | RefArrayOfInteger(..) => false,
3894        }
3895    }
3896
3897    pub fn is_string(&self) -> bool {
3898        use VarType::*;
3899        match self {
3900            String | RefString => true,
3901
3902            Boolean
3903            | RefBoolean
3904            | Integer
3905            | RefInteger
3906            | ArrayOfBoolean(..)
3907            | ArrayOfInteger(..)
3908            | RefArrayOfBoolean(..)
3909            | RefArrayOfInteger(..) => false,
3910        }
3911    }
3912}
3913
3914impl ExprType {
3915    pub fn match_for_bin_op(&self, other: &Self) -> bool {
3916        match self {
3917            Self::ReferenceOfVar(VarType::ArrayOfBoolean(size1))
3918            | Self::ReferenceOfVar(VarType::RefArrayOfBoolean(size1)) => match other {
3919                Self::ReferenceOfVar(VarType::ArrayOfBoolean(size2))
3920                | Self::ReferenceOfVar(VarType::RefArrayOfBoolean(size2)) => size1 == size2,
3921                _ => false,
3922            },
3923
3924            Self::ReferenceOfVar(VarType::ArrayOfInteger(size1))
3925            | Self::ReferenceOfVar(VarType::RefArrayOfInteger(size1)) => match other {
3926                Self::ReferenceOfVar(VarType::ArrayOfInteger(size2))
3927                | Self::ReferenceOfVar(VarType::RefArrayOfInteger(size2)) => size1 == size2,
3928                _ => false,
3929            },
3930
3931            Self::Boolean => matches!(other, Self::Boolean),
3932            Self::Integer => matches!(other, Self::Integer),
3933            Self::String => matches!(other, Self::String),
3934
3935            Self::ParamList | Self::ReferenceOfVar(..) => false,
3936        }
3937    }
3938
3939    pub fn is_bool_array(&self) -> bool {
3940        match self {
3941            Self::ReferenceOfVar(VarType::ArrayOfBoolean(_))
3942            | Self::ReferenceOfVar(VarType::RefArrayOfBoolean(_)) => true,
3943
3944            Self::Boolean
3945            | Self::Integer
3946            | Self::String
3947            | Self::ParamList
3948            | Self::ReferenceOfVar(..) => false,
3949        }
3950    }
3951
3952    pub fn is_int_array(&self) -> bool {
3953        match self {
3954            Self::ReferenceOfVar(VarType::ArrayOfInteger(_))
3955            | Self::ReferenceOfVar(VarType::RefArrayOfInteger(_)) => true,
3956
3957            Self::Boolean
3958            | Self::Integer
3959            | Self::String
3960            | Self::ParamList
3961            | Self::ReferenceOfVar(..) => false,
3962        }
3963    }
3964}
3965
3966impl Expr {
3967    fn binary(op: Operator, lhs: Expr, rhs: Expr) -> Option<Expr> {
3968        // op == , => ParamList, lhsとrhsは型が不一致でもOK
3969        // op != , => lhsとrhsは型が一致する必要がある
3970        // opが受け取れる型とopが返す型は様々
3971
3972        use Operator::*;
3973        let bin_op_expr = match op {
3974            // binary operator ではないもの、ここに来たらどこかにバグ
3975            OpenBracket | CloseBracket | AddInto | SubInto | Not => unreachable!(),
3976
3977            // 任意の結果を受け取ってパラメータリストとして返すもの
3978            Comma => {
3979                let v = match (lhs, rhs) {
3980                    (Expr::ParamList(mut v1), Expr::ParamList(mut v2)) => {
3981                        v1.append(&mut v2);
3982                        v1
3983                    }
3984                    (Expr::ParamList(mut v1), rhs) => {
3985                        v1.push(rhs);
3986                        v1
3987                    }
3988                    (lhs, Expr::ParamList(mut v2)) => {
3989                        v2.insert(0, lhs);
3990                        v2
3991                    }
3992                    (lhs, rhs) => vec![lhs, rhs],
3993                };
3994                return Some(Expr::ParamList(v));
3995            }
3996
3997            // カンマ以外の演算子で左辺と右辺の型が非互換なのはシンタックスエラー
3998            _ if !lhs.return_type().match_for_bin_op(&rhs.return_type()) => return None,
3999
4000            // 整数を受け取って整数を返すもの
4001            ShiftLeftArithmetic | ShiftRightArithmetic | ShiftLeftLogical | ShiftRightLogical
4002            | Mul | Div | Mod | Add | Sub
4003                if matches!(lhs.return_type(), ExprType::Integer) =>
4004            {
4005                Expr::BinaryOperatorInteger
4006            }
4007
4008            // 文字列を受け取って文字列を返すもの
4009            Concat if matches!(lhs.return_type(), ExprType::String) => Expr::BinaryOperatorString,
4010
4011            // 整数または文字列または配列を受け取って真理値を返すもの
4012            LessOrEequal | GreaterOrEqual | LessThan | GreaterThan
4013                if matches!(lhs.return_type(), ExprType::Integer | ExprType::String)
4014                    || lhs.return_type().is_int_array() =>
4015            {
4016                Expr::BinaryOperatorBoolean
4017            }
4018
4019            // 真理値または整数または文字列または配列を受け取って真理値を返すもの
4020            Equal | NotEqual
4021                if matches!(lhs.return_type(), ExprType::Boolean)
4022                    || matches!(lhs.return_type(), ExprType::Integer)
4023                    || matches!(lhs.return_type(), ExprType::String)
4024                    || lhs.return_type().is_bool_array()
4025                    || lhs.return_type().is_int_array() =>
4026            {
4027                Expr::BinaryOperatorBoolean
4028            }
4029
4030            // 真理値を受け取って真理値を返す、または整数を受け取って整数を返すもの
4031            And | Or | Xor if matches!(lhs.return_type(), ExprType::Boolean) => {
4032                Expr::BinaryOperatorBoolean
4033            }
4034            And | Or | Xor if matches!(lhs.return_type(), ExprType::Integer) => {
4035                Expr::BinaryOperatorInteger
4036            }
4037
4038            // 受け取る型に対応する演算子ではないのでシンタックスエラー
4039            // 漏れを無くすため全列挙…
4040            ShiftLeftArithmetic | ShiftRightArithmetic | ShiftLeftLogical | ShiftRightLogical
4041            | Mul | Div | Mod | Add | Sub | Concat | LessOrEequal | GreaterOrEqual | LessThan
4042            | GreaterThan | Equal | NotEqual | And | Or | Xor => return None,
4043        };
4044
4045        Some(bin_op_expr(op, Box::new(lhs), Box::new(rhs)))
4046    }
4047
4048    pub fn return_type(&self) -> ExprType {
4049        use Expr::*;
4050        match self {
4051            BinaryOperatorBoolean(..)
4052            | FunctionBoolean(..)
4053            | LitBoolean(..)
4054            | UnaryOperatorBoolean(..)
4055            | VarBoolean(..)
4056            | VarRefBoolean(..)
4057            | VarArrayOfBoolean(..)
4058            | VarRefArrayOfBoolean(..) => ExprType::Boolean,
4059
4060            BinaryOperatorInteger(..)
4061            | FunctionInteger(..)
4062            | LitInteger(..)
4063            | LitCharacter(..)
4064            | UnaryOperatorInteger(..)
4065            | VarInteger(..)
4066            | VarRefInteger(..)
4067            | VarArrayOfInteger(..)
4068            | VarRefArrayOfInteger(..)
4069            | CharOfLitString(..)
4070            | CharOfVarString(..)
4071            | CharOfVarRefString(..) => ExprType::Integer,
4072
4073            BinaryOperatorString(..)
4074            | FunctionString(..)
4075            | LitString(..)
4076            | VarString(..)
4077            | VarRefString(..) => ExprType::String,
4078
4079            ParamList(..) => ExprType::ParamList,
4080
4081            FunctionBooleanArray(size, ..) => {
4082                ExprType::ReferenceOfVar(VarType::ArrayOfBoolean(*size))
4083            }
4084
4085            FunctionIntegerArray(size, ..) => {
4086                ExprType::ReferenceOfVar(VarType::ArrayOfInteger(*size))
4087            }
4088
4089            ReferenceOfVar(_, var_type) => ExprType::ReferenceOfVar(*var_type),
4090        }
4091    }
4092
4093    pub fn can_access_variable(&self) -> bool {
4094        use Expr::*;
4095        match self {
4096            BinaryOperatorBoolean(..)
4097            | BinaryOperatorInteger(..)
4098            | BinaryOperatorString(..)
4099            | FunctionBoolean(..)
4100            | FunctionInteger(..)
4101            | FunctionString(..)
4102            | FunctionBooleanArray(..)
4103            | FunctionIntegerArray(..)
4104            | LitBoolean(..)
4105            | LitInteger(..)
4106            | LitCharacter(..)
4107            | LitString(..)
4108            | CharOfLitString(..)
4109            | UnaryOperatorBoolean(..)
4110            | UnaryOperatorInteger(..)
4111            | ParamList(..) => false,
4112
4113            CharOfVarString(..)
4114            | CharOfVarRefString(..)
4115            | VarBoolean(..)
4116            | VarRefBoolean(..)
4117            | VarArrayOfBoolean(..)
4118            | VarRefArrayOfBoolean(..)
4119            | VarInteger(..)
4120            | VarRefInteger(..)
4121            | VarArrayOfInteger(..)
4122            | VarRefArrayOfInteger(..)
4123            | VarString(..)
4124            | VarRefString(..)
4125            | ReferenceOfVar(..) => true,
4126        }
4127    }
4128}
4129
4130trait FunctionExtension {
4131    fn return_type(&self) -> ExprType;
4132    fn check_param(&self, param: &Expr) -> bool;
4133}
4134
4135impl FunctionExtension for Function {
4136    fn return_type(&self) -> ExprType {
4137        use Function::*;
4138        match self {
4139            CBool | Eof => ExprType::Boolean,
4140            Abs | Asc | CInt | Len | Max | Min => ExprType::Integer,
4141            Chr | CStr | Mid | Space | String => ExprType::String,
4142            Array | CArray | SubArray => unreachable!("BUG"),
4143        }
4144    }
4145
4146    fn check_param(&self, param: &Expr) -> bool {
4147        use Function::*;
4148        match self {
4149            // 引数なし
4150            Eof => false,
4151
4152            // 引数は整数1個
4153            Abs | CBool | Chr | Space => matches!(param.return_type(), ExprType::Integer),
4154
4155            // 引数は真理値1個あるいは整数1個
4156            CInt => matches!(param.return_type(), ExprType::Boolean | ExprType::String),
4157
4158            // 引数は真理値1個あるいは文字列1個
4159            CStr => matches!(param.return_type(), ExprType::Boolean | ExprType::Integer),
4160
4161            // 引数は整数2個
4162            Max | Min => {
4163                if let Expr::ParamList(list) = param {
4164                    list.len() == 2
4165                        && list
4166                            .iter()
4167                            .all(|expr| matches!(expr.return_type(), ExprType::Integer))
4168                } else {
4169                    false
4170                }
4171            }
4172
4173            // 引数は文字列1個と整数1個あるいは文字列1個と整数2個
4174            Mid => {
4175                if let Expr::ParamList(list) = param {
4176                    let list: Vec<_> = list.iter().map(|e| e.return_type()).collect();
4177                    matches!(
4178                        list.as_slice(),
4179                        [ExprType::String, ExprType::Integer]
4180                            | [ExprType::String, ExprType::Integer, ExprType::Integer]
4181                    )
4182                } else {
4183                    false
4184                }
4185            }
4186
4187            // 引数は文字列1個
4188            Asc => matches!(param.return_type(), ExprType::String),
4189
4190            // 引数は文字列1個または配列
4191            Len => {
4192                matches!(param.return_type(), ExprType::String)
4193                    || param.return_type().is_bool_array()
4194                    || param.return_type().is_int_array()
4195            }
4196
4197            // 引数は整数配列か整数2個
4198            String => {
4199                if let Expr::ParamList(list) = param {
4200                    list.len() == 2
4201                        && list
4202                            .iter()
4203                            .all(|expr| matches!(expr.return_type(), ExprType::Integer))
4204                } else {
4205                    param.return_type().is_int_array()
4206                }
4207            }
4208
4209            Array | CArray | SubArray => unreachable!("BUG"),
4210        }
4211    }
4212}
4213
4214impl std::fmt::Display for ArgumentInfo {
4215    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4216        let s = match self.var_type {
4217            VarType::Boolean => {
4218                format!("ByVal {} As Boolean [{}]", self.var_name, self.register1)
4219            }
4220            VarType::Integer => {
4221                format!("ByVal {} As Integer [{}]", self.var_name, self.register1)
4222            }
4223            VarType::String => format!(
4224                "ByVal {} As String [{},{}]",
4225                self.var_name,
4226                self.register1,
4227                self.register2.unwrap()
4228            ),
4229            VarType::ArrayOfBoolean(size) => format!(
4230                "ByVal {}({}) As Boolean [{}]",
4231                self.var_name,
4232                size - 1,
4233                self.register1
4234            ),
4235            VarType::ArrayOfInteger(size) => format!(
4236                "ByVal {}({}) As Integer [{}]",
4237                self.var_name,
4238                size - 1,
4239                self.register1
4240            ),
4241            VarType::RefBoolean => {
4242                format!("ByRef {} As Boolean [{}]", self.var_name, self.register1)
4243            }
4244            VarType::RefInteger => {
4245                format!("ByRef {} As Integer [{}]", self.var_name, self.register1)
4246            }
4247            VarType::RefString => format!(
4248                "ByRef {} As String [{},{}]",
4249                self.var_name,
4250                self.register1,
4251                self.register2.unwrap()
4252            ),
4253            VarType::RefArrayOfBoolean(size) => format!(
4254                "ByRef {}({}) As Boolean [{}]",
4255                self.var_name,
4256                size - 1,
4257                self.register1
4258            ),
4259            VarType::RefArrayOfInteger(size) => format!(
4260                "ByRef {}({}) As Integer [{}]",
4261                self.var_name,
4262                size - 1,
4263                self.register1
4264            ),
4265        };
4266        s.fmt(f)
4267    }
4268}
4269
4270impl std::fmt::Display for CaseIntegerItem {
4271    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4272        match self {
4273            Self::Integer(value) => value.fmt(f),
4274            Self::Character('"') => r#"""""c"#.fmt(f),
4275            Self::Character(ch) => format!(r#""{}"c"#, ch).fmt(f),
4276        }
4277    }
4278}
4279
4280impl std::fmt::Display for Expr {
4281    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4282        use Expr::*;
4283        match self {
4284            BinaryOperatorBoolean(op, lhs, rhs)
4285            | BinaryOperatorInteger(op, lhs, rhs)
4286            | BinaryOperatorString(op, lhs, rhs) => format!("({} {} {})", lhs, op, rhs).fmt(f),
4287            CharOfLitString(lit, index)
4288                if matches!(
4289                    index.as_ref(),
4290                    BinaryOperatorBoolean(..)
4291                        | BinaryOperatorInteger(..)
4292                        | BinaryOperatorString(..)
4293                ) =>
4294            {
4295                format!(r#""{}"{}"#, lit.replace('"', r#""""#), index).fmt(f)
4296            }
4297            CharOfLitString(lit, index) => {
4298                format!(r#""{}"({})"#, lit.replace('"', r#""""#), index).fmt(f)
4299            }
4300            VarArrayOfBoolean(var, index)
4301            | VarArrayOfInteger(var, index)
4302            | CharOfVarString(var, index)
4303            | VarRefArrayOfBoolean(var, index)
4304            | VarRefArrayOfInteger(var, index)
4305            | CharOfVarRefString(var, index)
4306                if matches!(
4307                    index.as_ref(),
4308                    BinaryOperatorBoolean(..)
4309                        | BinaryOperatorInteger(..)
4310                        | BinaryOperatorString(..)
4311                ) =>
4312            {
4313                format!("{}{}", var, index).fmt(f)
4314            }
4315            VarArrayOfBoolean(var, index)
4316            | VarArrayOfInteger(var, index)
4317            | CharOfVarString(var, index)
4318            | VarRefArrayOfBoolean(var, index)
4319            | VarRefArrayOfInteger(var, index)
4320            | CharOfVarRefString(var, index) => format!("{}({})", var, index).fmt(f),
4321            FunctionBoolean(func, param)
4322                if matches!(func, Function::Eof)
4323                    && matches!(param.as_ref(), Expr::LitInteger(0)) =>
4324            {
4325                format!("{}()", func).fmt(f)
4326            }
4327            FunctionBoolean(func, param)
4328            | FunctionInteger(func, param)
4329            | FunctionString(func, param)
4330            | FunctionBooleanArray(_, func, param)
4331            | FunctionIntegerArray(_, func, param)
4332                if matches!(
4333                    param.as_ref(),
4334                    BinaryOperatorBoolean(..)
4335                        | BinaryOperatorInteger(..)
4336                        | BinaryOperatorString(..)
4337                ) =>
4338            {
4339                format!("{}{}", func, param).fmt(f)
4340            }
4341            FunctionBoolean(func, param)
4342            | FunctionInteger(func, param)
4343            | FunctionString(func, param)
4344            | FunctionBooleanArray(_, func, param)
4345            | FunctionIntegerArray(_, func, param) => format!("{}({})", func, param).fmt(f),
4346            LitBoolean(lit) => (if *lit { "True" } else { "False" }).fmt(f),
4347            LitInteger(lit) => lit.fmt(f),
4348            LitString(lit) => format!(r#""{}""#, lit.replace('"', r#""""#)).fmt(f),
4349            LitCharacter('"') => r#"""""c"#.fmt(f),
4350            LitCharacter(lit) => format!(r#""{}"c"#, lit).fmt(f),
4351            UnaryOperatorInteger(op, value) | UnaryOperatorBoolean(op, value) => {
4352                format!("{}({})", op, value).fmt(f)
4353            }
4354            VarBoolean(var)
4355            | VarInteger(var)
4356            | VarString(var)
4357            | VarRefBoolean(var)
4358            | VarRefInteger(var)
4359            | VarRefString(var)
4360            | ReferenceOfVar(var, ..) => var.fmt(f),
4361            ParamList(list) => list
4362                .iter()
4363                .map(|v| v.to_string())
4364                .collect::<Vec<_>>()
4365                .join(", ")
4366                .fmt(f),
4367        }
4368    }
4369}