Skip to content

Commit 944e99a

Browse files
committed
Add test/example for a token struct
From #324
1 parent 8a40aa3 commit 944e99a

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

tests/run-pass/tokens_struct.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use peg::{Parse, ParseElem, RuleResult};
2+
3+
/// The default implementation of the parsing traits for `[T]` expects `T` to be
4+
/// `Copy`, as in the `[u8]` or simple enum cases. This wrapper exposes the
5+
/// elements by `&T` reference, which is `Copy`.
6+
pub struct SliceByRef<'a, T>(pub &'a [T]);
7+
8+
impl<'a , T> Parse for SliceByRef<'a, T> {
9+
type PositionRepr = usize;
10+
fn start(&self) -> usize {
11+
0
12+
}
13+
14+
fn is_eof(&self, pos: usize) -> bool {
15+
pos >= self.0.len()
16+
}
17+
18+
fn position_repr(&self, pos: usize) -> usize {
19+
pos
20+
}
21+
}
22+
23+
impl<'a, T: 'a> ParseElem<'a> for SliceByRef<'a, T> {
24+
type Element = &'a T;
25+
26+
fn parse_elem(&'a self, pos: usize) -> RuleResult<&'a T> {
27+
match self.0[pos..].first() {
28+
Some(c) => RuleResult::Matched(pos + 1, c),
29+
None => RuleResult::Failed,
30+
}
31+
}
32+
}
33+
34+
#[derive(PartialEq)]
35+
pub enum TokenType {
36+
Word,
37+
Number,
38+
}
39+
40+
pub struct Token {
41+
pub token_type: TokenType,
42+
pub term: String,
43+
}
44+
45+
peg::parser!{
46+
grammar tokenparser<'a>() for SliceByRef<'a, Token> {
47+
// The [] syntax works just like (and expands into) an arm of a match
48+
// in regular Rust, so you can use a pattern that matches one field
49+
// and ignores the rest
50+
pub rule word_by_field() = [ Token { token_type: TokenType::Word, .. } ]
51+
52+
// Or capture the token as a variable and then test it with an if guard.
53+
pub rule word_by_eq() = [t if t.token_type == TokenType::Word]
54+
55+
// You could wrap this in a rule that accepts the TokenType as an argument
56+
rule tok(ty: TokenType) -> &'input Token = [t if t.token_type == ty]
57+
pub rule number() = tok(TokenType::Number)
58+
}
59+
}
60+
61+
fn main() {
62+
let word_tok = vec![
63+
Token { token_type: TokenType::Word, term: "foo".into() }
64+
];
65+
66+
let number_tok = vec![
67+
Token { token_type: TokenType::Number, term: "123".into() }
68+
];
69+
70+
assert!(tokenparser::word_by_field(&SliceByRef(&word_tok[..])).is_ok());
71+
assert!(tokenparser::word_by_eq(&SliceByRef(&word_tok[..])).is_ok());
72+
assert!(tokenparser::number(&SliceByRef(&number_tok[..])).is_ok());
73+
}

0 commit comments

Comments
 (0)