Sit back, relax, stay awhile…

Where I explore some more sources of Rust knowledge and dive into a more complicated project than a simple exercise

Colorized Linux directory listing on screen
I’m watching you, code

I saw two intriguing sources this past weekend. I’ve added both to my resources page. The first one takes a while, but it’s not boring because he works FAST and you have to pay attention in order to follow along! This is @Jonhoo letting us sit over his shoulder while he develops (more advanced solutions) in Rust. But watch this on your widescreen TV or monitor – not with your phone – you need to be able to read the code while he works. Fascinating to watch a library crate be developed start to finish. I never could have gotten the syntax right at this point, but I feel good that I understood probably 90% of what he does! But, what about some (mut simpler, less impressive) Rust coding of my own? See below where I learn some fancy Rust stdin processing.




A Second Source

The second source was a blog post: Writing An Interpreter In Rust by @_chr4 based on his first chapter work adapting Writing An Interpreter In Go by Thorsten Ball to Rust. I started heavily with the code _chr4 had worked out – first on his own and then with some suggestions of readers of that blog post which prompted a second post. But, I then adapted mine to work with “MonkeyCode” either in a source file or keyed interactively. So, I have my project on GitHub as well, but I’m concentrating on just my main.rs file right now:

pub mod lexer;
pub mod token;

use std::env;
use std::fs;
use std::io;

use lexer::Lexer;
use token::Token;

fn main() {
    let args: Vec<String> = env::args().collect();

    if args.len() == 2 {
        process_file(&args[1]);
    } else {
        process_stdin();
    }
    println!("End.");
}

fn process_stdin() {
    loop {
        print!(">> ");

        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(size) if size > 1 => tokenize(&line),
            Ok(size) if size == 1 => println!("CTRL-D to end."),
            Ok(size) if size == 0 => break,
            _ => panic!("Error reading from stdin"),
        }
    }
}

fn process_file(filename: &str) {
    let contents = fs::read_to_string(filename).expect("Reached end of file");
    for line in contents.lines() {
        print!(">> ");
        tokenize(line);
    }
}

fn tokenize(mut line: &str) {
    let mut lexer = Lexer::new(&mut line);

    loop {
        let tok = lexer.next_token();
        println!("{:?}", tok);
        if tok == Token::EndOfLine {
            break;
        }
    }
}

Fancy Rust stdin Processing

Man with arms held up, while sun sets
Success!!

This really seems to work well both ways: either provide a filename as the first parameter and it will read in that file and tokenize the “MonkeyCode” inside, or if you don’t provide an argument, you’ll enter interactive mode and can type “MonkeyCode” live and watch it tokenize each line you enter. I also have it watching stdin for a CTRL-D as a way to exit (of course, CTRL-C works pretty well too, but CTRL-D is a natural, controlled ending of my app).

Author: Jeff Culverhouse

I am a remote Sr Software Engineer for ZipRecruiter.com, mainly perl. Learning Rust in my spare time. Plus taking classes at James Madison University. Culverhouse - English: from Old English culfrehūs ‘dovecote’, hence a topographic name for someone living near a dovecote, or possibly a metonymic occupational name for the keeper of a dovecote. ISTP, occasionally INTP.