CodeBlanks Logo Icon CodeBlanks

TokenStream

Produce streaming code with TokenStream.

TokenStream

TokenStream is the form in which the compiler sees source code: a sequence of token trees. There are four kinds of tokens: Ident (a name, a keyword), Punct (:, +, ->), Literal (42, "metin") and Group (a sub-sequence inside parentheses, brackets or braces):

fn kare(x: i32)
// Ident(fn) Ident(kare) Group(( Ident(x) Punct(:) Ident(i32) ))

Whitespace and comments aren't tokens; the macro doesn't see them.

A small tokenizer

The compiler's first step is splitting text into tokens. A simple version: join runs of letters, digits and underscores, split other symbols one by one, skip whitespace:

fn belirtecler(s: &str) -> Vec<String> {
    let mut sonuc = Vec::new();
    let mut ad = String::new();
    for c in s.chars() {
        if c.is_alphanumeric() || c == '_' {
            ad.push(c);
            continue;
        }
        if !ad.is_empty() {
            sonuc.push(std::mem::take(&mut ad));
        }
        if !c.is_whitespace() {
            sonuc.push(c.to_string());
        }
    }
    if !ad.is_empty() {
        sonuc.push(ad);
    }
    sonuc
}

Practice Split into tokens

Write the belirtecler function above. Print the result for "fn kare(x: i32)" with {:?}.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn belirtecler(s: &str) -> Vec<String> {
    let mut sonuc = Vec::new();
    let mut ad = String::new();
    for c in s.chars() {
        if c.is_alphanumeric() || c == '_' {
            ad.push(c);
            continue;
        }
        if !ad.is_empty() {
            sonuc.push(std::mem::take(&mut ad));
        }
        if !c.is_whitespace() {
            sonuc.push(c.to_string());
        }
    }
    if !ad.is_empty() {
        sonuc.push(ad);
    }
    sonuc
}

fn main() {
    println!("{:?}", belirtecler("fn kare(x: i32)"));
}

Expected output

["fn", "kare", "(", "x", ":", "i32", ")"]

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What does <code>$x:tt</code> match in declarative macros?

  • A type
  • An expression
  • A line
  • A single token tree: one token or a bracketed group Correct answer

Explanation: tt is the most flexible fragment; with $($t:tt)* anything can be forwarded as is.

2 Take the value and empty it

Question
sonuc.push(std::mem::____(&mut ad));
Answer
sonuc.push(std::mem::take(&mut ad));

Explanation: mem::take takes the value and leaves the default (an empty String) in its place.

3 Token and kind

Term Meaning
kare Ident
: Punct
42 Literal
( x: i32 ) Group

All lessons in Advanced