#![cfg(test)]
#[cfg(feature = "generated_tests")]
use crate::lexer::ChannelId;
mod lex {
use std::collections::HashMap;
use std::io::Read;
use crate::lexer::{ActionOption, Lexer, ModeOption, StateId, Terminal};
use crate::segmap::{GroupId, Seg, SegMap};
const NBR_GROUPS: u32 = 25;
const INITIAL_STATE: StateId = 0;
const FIRST_END_STATE: StateId = 50;
const NBR_STATES: StateId = 86;
static ASCII_TO_GROUP: [GroupId; 128] = [
25, 25, 25, 25, 25, 25, 25, 25, 25, 10, 10, 25, 25, 10, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 24, 25, 25, 25, 25, 25, 25, 8, 12, 1, 25, 24, 25, 24, 25, 11, 2, 3, 11, 11, 11, 11, 11, 11, 11, 25, 25, 25, 25, 25, 24, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 22, 25, 4, 9, 23, 20, 14, 23, 23, 21, 23, 23, 5, 23, 6, 23, 15, 7, 23, 19, 13, 23, 16, 23, 18, 23, 17, 23, 25, 25, 25, 25, 25, ];
static UTF8_TO_GROUP: [(char, GroupId); 0] = [
];
static SEG_TO_GROUP: [(Seg, GroupId); 0] = [
];
static TERMINAL_TABLE: [Terminal;36] = [
Terminal { action: ActionOption::Skip, channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(0), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(1), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(2), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(3), channel: 0, mode: ModeOption::Mode(1), mode_state: Some(6), pop: false },
Terminal { action: ActionOption::Token(4), channel: 0, mode: ModeOption::Push(1), mode_state: Some(6), pop: false },
Terminal { action: ActionOption::Token(5), channel: 1, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(6), channel: 2, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Skip, channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(7), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::More, channel: 0, mode: ModeOption::Mode(2), mode_state: Some(26), pop: false },
Terminal { action: ActionOption::Token(1), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Skip, channel: 0, mode: ModeOption::Mode(2), mode_state: Some(26), pop: false },
Terminal { action: ActionOption::Token(8), channel: 0, mode: ModeOption::Push(1), mode_state: Some(6), pop: false },
Terminal { action: ActionOption::Skip, channel: 0, mode: ModeOption::Push(2), mode_state: Some(26), pop: false },
Terminal { action: ActionOption::Token(9), channel: 0, mode: ModeOption::None, mode_state: None, pop: true },
Terminal { action: ActionOption::Token(10), channel: 0, mode: ModeOption::Push(2), mode_state: Some(26), pop: true },
Terminal { action: ActionOption::Skip, channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(11), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(1), channel: 0, mode: ModeOption::None, mode_state: None, pop: false },
Terminal { action: ActionOption::Token(12), channel: 0, mode: ModeOption::Push(2), mode_state: Some(26), pop: false },
Terminal { action: ActionOption::Token(13), channel: 0, mode: ModeOption::None, mode_state: None, pop: true },
];
static STATE_TABLE: [StateId; 2151] = [
50, 51, 1, 30, 52, 53, 54, 55, 86, 52, 50, 86, 86, 52, 52, 52, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 86, 86, 86, 86, 86, 86, 4, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 68, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 69, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 4, 86, 4, 4, 4, 4, 4, 4, 86, 4, 86, 4, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 86, 4, 4, 5, 86, 5, 5, 5, 5, 5, 5, 86, 5, 86, 5, 71, 5, 5, 5, 5, 5, 5, 5, 5, 5, 86, 5, 5, 72, 73, 86, 86, 86, 7, 86, 8, 86, 74, 72, 86, 86, 9, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 10, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 19, 20, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 33, 15, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 11, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 12, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 13, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 14, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 75, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 31, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 18, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 76, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 79, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 21, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 35, 86, 86, 86, 86, 86, 86, 86, 77, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 78, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 48, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 80, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 81, 82, 86, 86, 86, 49, 86, 32, 86, 86, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 83, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 85, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 84, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 5, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 17, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 28, 46, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 16, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 27, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 22, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 23, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 25, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 29, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 34, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 36, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 37, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 38, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 39, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 40, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 41, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 42, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 43, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 45, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 47, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 50, 86, 86, 86, 86, 86, 86, 86, 86, 86, 50, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 56, 52, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 62, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 65, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 57, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 58, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 59, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 60, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 61, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 63, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 64, 52, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 66, 52, 52, 52, 52, 52, 52, 52, 52, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 52, 67, 86, 52, 86, 86, 86, 52, 52, 52, 52, 52, 52, 86, 52, 86, 52, 86, 52, 52, 52, 52, 52, 52, 52, 52, 52, 3, 52, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 72, 86, 86, 86, 86, 86, 86, 86, 86, 86, 72, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 24, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86 ];
pub fn build_lexer<R: Read>() -> Lexer<'static, R> {
Lexer::new(
NBR_GROUPS,
INITIAL_STATE,
FIRST_END_STATE,
NBR_STATES,
&ASCII_TO_GROUP,
HashMap::<char, GroupId>::from(UTF8_TO_GROUP),
SegMap::<GroupId>::from(SEG_TO_GROUP),
&STATE_TABLE,
&TERMINAL_TABLE,
)
}
}
const CH_DEFAULT : ChannelId = 0;
const CH_1 : ChannelId = 1;
const CH_2 : ChannelId = 2;
mod tok {
use crate::TokenId;
pub const STAR : TokenId = 0 ; pub const KEYWORD : TokenId = 1 ; pub const ID : TokenId = 2 ; pub const MODE_A : TokenId = 3 ; pub const PUSH_A : TokenId = 4 ; pub const CH1 : TokenId = 5 ; pub const CH2 : TokenId = 6 ; pub const STAR_A : TokenId = 7 ; pub const PUSH_A2 : TokenId = 8 ; pub const POP_FROM_A : TokenId = 9 ; pub const POP_FROM_A_PUSH_B : TokenId = 10; pub const STAR_B : TokenId = 11; pub const PUSH_B2 : TokenId = 12; pub const POP_FROM_B : TokenId = 13;
pub static NAMES: &[&str; 14] = &[
"STAR", "KEYWORD", "ID", "MODE_A", "PUSH_A", "CH1", "CH2", "STAR_A",
"PUSH_A2", "POP_FROM_A", "POP_FROM_A_PUSH_B","STAR_B", "PUSH_B2", "POP_FROM_B"
];
}
mod lexicon {
use crate::char_reader::CharReader;
use crate::{CollectJoin, TokenId};
use crate::lexer::{Lexer, LexerError, Pos, PosSpan};
use super::*;
use super::lex::build_lexer;
use super::tok::*;
#[test]
fn test_iter() {
let tests: Vec<(&str, &str, Vec<TokenId>, Vec<TokenId>, Vec<TokenId>, Vec<&str>, Vec<&str>, Vec<&str>, Vec<&str>)> = vec![
( "*", "",
vec![STAR], vec![], vec![],
vec!["*"], vec![], vec![],
vec!["1:1"],
),
( " * ", "",
vec![STAR], vec![], vec![],
vec!["*"], vec![], vec![],
vec!["1:2"],
),
( "mode_a *", "",
vec![MODE_A, STAR_A], vec![], vec![],
vec!["mode_a", "*"], vec![], vec![],
vec!["1:1-6", "1:8"],
),
( "push_a * spush_b * pop * pop *", "",
vec![PUSH_A, STAR_A, STAR_B, POP_FROM_B, STAR_A, POP_FROM_A, STAR], vec![], vec![],
vec!["push_a", "*", "*", "pop", "*", "pop", "*"], vec![], vec![],
vec!["1:1-6", "1:8", "1:18", "1:20-22", "1:24", "1:26-28", "1:30"],
),
( "mode_a b *", "",
vec![MODE_A, STAR_B], vec![], vec![],
vec!["mode_a", "b*"], vec![], vec![],
vec!["1:1-6", "1:10"],
),
( "mode_a * keyword smode_b * keyword", "",
vec![MODE_A, STAR_A, KEYWORD, STAR_B, KEYWORD], vec![], vec![],
vec!["mode_a", "*", "keyword", "*", "keyword"], vec![], vec![],
vec!["1:1-6", "1:8", "1:10-16", "1:26", "1:28-34"],
),
( "1(hello)\n 2(world)", "",
vec![], vec![CH1], vec![CH2],
vec![], vec!["1(hello)"], vec!["2(world)"],
vec!["1:1-8", "2:2-9"],
),
( "keywor d keyword", "",
vec![ID, ID, KEYWORD], vec![], vec![],
vec!["keywor", "d", "keyword"], vec![], vec![],
vec!["1:1-6", "1:8", "1:10-16"],
),
( "push_a * * push_a * spush_b *", "",
vec![PUSH_A, STAR_A, STAR_A, PUSH_A2, STAR_A, STAR_B], vec![], vec![],
vec!["push_a", "*", "*", "push_a", "*", "*"], vec![], vec![],
vec!["1:1-6", "1:8", "1:10", "1:12-17", "1:19", "1:29"],
),
( "*", "",
vec![STAR], vec![], vec![],
vec!["*"], vec![], vec![],
vec!["1:1"],
),
( "push_a pop_push_b * pop *", "",
vec![PUSH_A, POP_FROM_A_PUSH_B, STAR_B, POP_FROM_B, STAR], vec![], vec![],
vec!["push_a", "pop_push_b", "*", "pop", "*"], vec![], vec![],
vec!["1:1-6", "1:8-17", "1:19", "1:21-23", "1:25"],
),
( "mode_a smode_b * push_b * pop *", "",
vec![MODE_A, STAR_B, PUSH_B2, STAR_B, POP_FROM_B, STAR_B], vec![], vec![],
vec!["mode_a", "*", "push_b", "*", "pop", "*"], vec![], vec![],
vec!["1:1-6", "1:16", "1:18-23", "1:25", "1:27-29", "1:31"],
),
( "*+", "unrecognized character '+', line 1, col 2 (stream pos = 1)",
vec![STAR], vec![], vec![],
vec!["*"], vec![], vec![],
vec!["1:1"],
),
( "", "end of stream, line 1, col 1 (stream pos = 0)",
vec![], vec![], vec![],
vec![], vec![], vec![],
vec![],
),
];
const VERBOSE: bool = false;
static INDENT1: &str = " ";
static INDENT2: &str = " ";
let mut lexer = build_lexer();
for (id, (text, exp_err, exp_ch0, exp_ch1, exp_ch2, exp_ch_s0, exp_ch_s1, exp_ch_s2, exp_spans)) in tests.into_iter().enumerate() {
let stream = CharReader::new(text.as_bytes());
lexer.attach_stream(stream);
let mut ch = vec![vec![], vec![], vec![]];
let mut ch_s = vec![vec![], vec![], vec![]];
let mut spans = vec![];
for (tokenid, channelid, string, posspan) in lexer.tokens() {
assert!(channelid <= CH_2, "unexpected channel id {channelid}");
ch[channelid as usize].push(tokenid);
ch_s[channelid as usize].push(string);
spans.push(format!("{posspan}"));
};
let err = if lexer.has_error() { format!("{}", lexer.get_error()) } else { String::new() };
if VERBOSE {
println!("{INDENT1}( // {id}\n{INDENT2}{text:?}, {err:?},");
println!("{INDENT2}{},", (0..3).map(|i| format!("vec![{}]", ch[i].iter().map(|&t| NAMES[t as usize]).join(", "))).join(", "));
println!("{INDENT2}{},", (0..3).map(|i| format!("vec![{}]", ch_s[i].iter().map(|s| format!("{s:?}")).join(", "))).join(", "));
println!("{INDENT2}vec![{}],", spans.iter().map(|s| format!("{s:?}")).join(", "));
println!("{INDENT1}),");
}
let msg = format!("## ERROR in test {id}");
assert_eq!(
err, exp_err,
"{msg}: lexer should have {}{err}", if err.is_empty() { "no error" } else { "this error: " });
assert_eq!(ch[0], exp_ch0, "{msg}: mismatch in channel 0");
assert_eq!(ch[1], exp_ch1, "{msg}: mismatch in channel 1");
assert_eq!(ch[2], exp_ch2, "{msg}: mismatch in channel 2");
assert_eq!(ch_s[0], exp_ch_s0, "{msg}: mismatch in channel 0");
assert_eq!(ch_s[1], exp_ch_s1, "{msg}: mismatch in channel 1");
assert_eq!(ch_s[2], exp_ch_s2, "{msg}: mismatch in channel 2");
assert_eq!(spans, exp_spans, "{msg}: mismatch in spans");
}
}
#[test]
fn test_get_token() {
fn get_lexer_state(lexer: &Lexer<&[u8]>) -> (bool, LexerError, bool, bool) {
(lexer.has_error(), lexer.get_error().clone(), lexer.is_eos(), lexer.is_open())
}
fn check_next_eos(lexer: &mut Lexer<&[u8]>, expected_msg: &str) {
assert_eq!(lexer.get_token().err().map(|e| e.to_string()), Some(expected_msg.to_string()));
let error = lexer.get_error().clone();
assert!(matches!(error, LexerError::EndOfStream { .. }), "error is {error:?} instead of EndOfStream");
assert_eq!(get_lexer_state(&lexer), (true, error, true, false));
}
let mut lexer = build_lexer();
let text = "* id 1()";
let stream = CharReader::new(text.as_bytes());
lexer.attach_stream(stream);
assert_eq!(lexer.get_token(), Ok(Some((STAR, CH_DEFAULT, "*".to_string(), PosSpan::new(Pos(1, 1), Pos(1, 1))))));
assert_eq!(get_lexer_state(&lexer), (false, LexerError::None, false, true));
assert_eq!(lexer.get_token(), Ok(Some((ID, CH_DEFAULT, "id".to_string(), PosSpan::new(Pos(1, 3), Pos(1, 4))))));
assert_eq!(get_lexer_state(&lexer), (false, LexerError::None, false, true));
assert_eq!(lexer.get_token(), Ok(Some((CH1, CH_1, "1()".to_string(), PosSpan::new(Pos(1, 6), Pos(1, 8))))));
assert_eq!(get_lexer_state(&lexer), (false, LexerError::None, true, false));
check_next_eos(&mut lexer, "end of stream, line 1, col 9 (stream pos = 8)");
check_next_eos(&mut lexer, "end of stream, line 1, col 9 (stream pos = 8)");
let text = "\n *+";
let stream = CharReader::new(text.as_bytes());
lexer.attach_stream(stream);
assert_eq!(lexer.get_token(), Ok(Some((STAR, CH_DEFAULT, "*".to_string(), PosSpan::new(Pos(2, 2), Pos(2, 2))))));
assert_eq!(get_lexer_state(&lexer), (false, LexerError::None, false, true));
assert_eq!(lexer.get_token().err().map(|e| e.to_string()), Some("unrecognized character '+', line 2, col 3 (stream pos = 3)".to_string()));
let error = lexer.get_error().clone();
assert!(matches!(error, LexerError::UnrecognizedChar { .. }), "error is {error:?} instead of UnrecognizedChar");
assert_eq!(get_lexer_state(&lexer), (true, error, false, true));
check_next_eos(&mut lexer, "end of stream, line 2, col 4 (stream pos = 4)");
check_next_eos(&mut lexer, "end of stream, line 2, col 4 (stream pos = 4)");
let text = " + end";
let stream = CharReader::new(text.as_bytes());
lexer.attach_stream(stream);
assert_eq!(lexer.get_token().err().map(|e| e.to_string()), Some("unrecognized character '+', line 1, col 2 (stream pos = 1)".to_string()));
let error = lexer.get_error().clone();
assert!(matches!(error, LexerError::UnrecognizedChar { .. }), "error is {error:?} instead of UnrecognizedChar");
assert_eq!(get_lexer_state(&lexer), (true, error, false, true));
assert_eq!(lexer.get_token(), Ok(Some((ID, CH_DEFAULT, "end".to_string(), PosSpan::new(Pos(1, 4), Pos(1, 6))))));
check_next_eos(&mut lexer, "end of stream, line 1, col 7 (stream pos = 6)");
check_next_eos(&mut lexer, "end of stream, line 1, col 7 (stream pos = 6)");
}
}