summaryrefslogtreecommitdiffstats
path: root/crates/rebel-parse/src/token.rs
blob: 2f2f84980b502fd23ac0019eb25aba40b207b531 (plain)
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
61
62
63
64
65
66
67
68
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Token<'a> {
	Ident(&'a str),
	Punct(Punct),
	String(String<'a>),
	Number(&'a str),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Punct(pub char, pub Spacing);

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Spacing {
	Alone,
	Joint,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct String<'a> {
	pub pieces: Vec<StringPiece<'a>>,
	pub kind: StringKind,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum StringPiece<'a> {
	Chars(&'a str),
	Escape(char),
	Interp(TokenStream<'a>),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StringKind {
	String,
	RawString,
	ScriptString,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TokenStream<'a>(pub Vec<Token<'a>>);

impl<'a> peg::Parse for TokenStream<'a> {
	type PositionRepr = usize;

	fn start(&self) -> usize {
		0
	}

	fn is_eof(&self, pos: usize) -> bool {
		pos >= self.0.len()
	}

	fn position_repr(&self, pos: usize) -> Self::PositionRepr {
		pos
	}
}

impl<'input, 'a: 'input> peg::ParseElem<'input> for TokenStream<'a> {
	type Element = &'input Token<'a>;

	fn parse_elem(&'input self, pos: usize) -> peg::RuleResult<Self::Element> {
		use peg::RuleResult;

		match self.0[pos..].first() {
			Some(c) => RuleResult::Matched(pos + 1, c),
			None => RuleResult::Failed,
		}
	}
}