1use 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 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 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 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 match pos_and_tokens {
310 [(_, 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 [(_, 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 [(_, 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 [(_, 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 [(_, 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 [(_, 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 fn parse_assign_element(
483 &mut self,
484 name: &str,
485 var_type: VarType,
486 pos_and_tokens: &[(usize, Token)],
487 ) -> Result<(), SyntaxError> {
488 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 [(_, 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 [(_, 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 [(_, 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 [(_, 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 [(_, 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 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 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 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 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 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 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) = ¶m {
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 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(¶m) {
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 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 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 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 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 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 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 fn parse_command_mid(&mut self, pos_and_tokens: &[(usize, Token)]) -> Result<(), SyntaxError> {
1683 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 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 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 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 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 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 fn compose_command_if(&mut self) -> Result<(), SyntaxError> {
1846 let block = self.statements.pop().unwrap(); 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 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 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(); 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 fn parse_command_elseif(
2043 &mut self,
2044 pos_and_tokens: &[(usize, Token)],
2045 ) -> Result<(), SyntaxError> {
2046 let block = self.statements.pop().unwrap(); 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 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 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 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 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 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 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 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 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 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 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 [(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 [(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 fn parse_command_input(
2709 &mut self,
2710 pos_and_tokens: &[(usize, Token)],
2711 ) -> Result<(), SyntaxError> {
2712 match pos_and_tokens {
2713 [(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 [(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 fn parse_command_print(
2783 &mut self,
2784 pos_and_tokens: &[(usize, Token)],
2785 ) -> Result<(), SyntaxError> {
2786 match pos_and_tokens {
2787 [] => {
2789 self.add_statement(Statement::PrintLitString { value: "".into() });
2790 return Ok(());
2791 }
2792 [(_, Token::Boolean(value))] => {
2794 self.add_statement(Statement::PrintLitBoolean { value: *value });
2795 return Ok(());
2796 }
2797 [(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 [(_, 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 [(_, Token::String(value))] => {
2821 self.add_statement(Statement::PrintLitString {
2822 value: value.clone(),
2823 });
2824 return Ok(());
2825 }
2826 [(_, 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 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 fn parse_expr(&self, pos_and_tokens: &[(usize, Token)]) -> Result<Expr, SyntaxError> {
2858 match pos_and_tokens {
2860 [] => return Err(self.syntax_error("式がありません".into())),
2862
2863 [(_, Token::Boolean(value))] => return Ok(Expr::LitBoolean(*value)),
2865
2866 [(_, Token::Character(value))] => return Ok(Expr::LitCharacter(*value)),
2868
2869 [(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 [(_, Token::String(value))] => return Ok(Expr::LitString(value.clone())),
2882
2883 [(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 [(_, 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 [(_, 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 [(_, 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 [(_, 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 [(pos, token)] | [(pos, token), (_, _)] => {
2984 return Err(self.syntax_error_pos(*pos, format!("不正な式です: {:?}", token)))
2985 }
2986
2987 _ => {}
2989 }
2990
2991 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 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 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 match pos_and_tokens {
3077 [(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 [(_, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] => {
3093 self.parse_expr(inner)
3094 }
3095
3096 [(_, 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 [(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 [(_, 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 [(_, Token::Function(Function::Array)), (pos, Token::Operator(Operator::OpenBracket)), inner @ .., (_, Token::Operator(Operator::CloseBracket))] =>
3154 {
3155 let param = self.parse_expr(inner)?;
3156 match ¶m {
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 [(_, 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 [(_, 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 [(_, 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) = ¶m {
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 [(_, 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(¶m) {
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 _ => 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), }
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>), VarArrayOfInteger(String, Box<Expr>), VarRefArrayOfBoolean(String, Box<Expr>), VarRefArrayOfInteger(String, Box<Expr>), ReferenceOfVar(String, VarType), 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 use Operator::*;
3973 let bin_op_expr = match op {
3974 OpenBracket | CloseBracket | AddInto | SubInto | Not => unreachable!(),
3976
3977 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 _ if !lhs.return_type().match_for_bin_op(&rhs.return_type()) => return None,
3999
4000 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 Concat if matches!(lhs.return_type(), ExprType::String) => Expr::BinaryOperatorString,
4010
4011 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 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 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 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 Eof => false,
4151
4152 Abs | CBool | Chr | Space => matches!(param.return_type(), ExprType::Integer),
4154
4155 CInt => matches!(param.return_type(), ExprType::Boolean | ExprType::String),
4157
4158 CStr => matches!(param.return_type(), ExprType::Boolean | ExprType::Integer),
4160
4161 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 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 Asc => matches!(param.return_type(), ExprType::String),
4189
4190 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 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}