1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use crate::data::{token::Token, *};

pub fn unexpected_token_or_eof_to_kiki_err(unexpected: Option<&Token>, src: &str) -> KikiErr {
    let Some(token) = unexpected else {
        return get_unexpected_eof_err(src);
    };

    let start = token.start();
    let end = ByteIndex(start.0 + token.content_len());
    let content = src[start.0..end.0].to_string();
    KikiErr::Parse(start, content, end)
}

fn get_unexpected_eof_err(src: &str) -> KikiErr {
    KikiErr::Parse(ByteIndex(src.len()), "".to_string(), ByteIndex(src.len()))
}

impl Token {
    fn start(&self) -> ByteIndex {
        match self {
            Token::Underscore(start) => *start,
            Token::Ident(ident) => ident.position,
            Token::TerminalIdent(ident) => ByteIndex(ident.dollarless_position.0 - "$".len()),
            Token::StartKw(start) => *start,
            Token::StructKw(start) => *start,
            Token::EnumKw(start) => *start,
            Token::TerminalKw(start) => *start,
            Token::Colon(start) => *start,
            Token::DoubleColon(start) => *start,
            Token::Comma(start) => *start,
            Token::LParen(start) => *start,
            Token::RParen(start) => *start,
            Token::LCurly(start) => *start,
            Token::RCurly(start) => *start,
            Token::LAngle(start) => *start,
            Token::RAngle(start) => *start,
        }
    }

    fn content_len(&self) -> usize {
        match self {
            Token::Underscore(_) => "_".len(),
            Token::Ident(ident) => ident.name.len(),
            Token::TerminalIdent(ident) => "$".len() + ident.name.raw().len(),
            Token::StartKw(_) => "start".len(),
            Token::StructKw(_) => "struct".len(),
            Token::EnumKw(_) => "enum".len(),
            Token::TerminalKw(_) => "terminal".len(),
            Token::Colon(_) => ":".len(),
            Token::DoubleColon(_) => "::".len(),
            Token::Comma(_) => ",".len(),
            Token::LParen(_) => "(".len(),
            Token::RParen(_) => ")".len(),
            Token::LCurly(_) => "{".len(),
            Token::RCurly(_) => "}".len(),
            Token::LAngle(_) => "<".len(),
            Token::RAngle(_) => ">".len(),
        }
    }
}