Skip to content

Instantly share code, notes, and snippets.

@drozdziak1
Created August 19, 2018 08:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drozdziak1/3ebc8fd4f1b6e238a8232e3b6d3cd926 to your computer and use it in GitHub Desktop.
Save drozdziak1/3ebc8fd4f1b6e238a8232e3b6d3cd926 to your computer and use it in GitHub Desktop.
#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;
extern crate env_logger;
use nom::double_s;
use std::env;
use std::io;
use std::io::Write;
#[derive(Debug)]
pub enum Token {
LeftParen,
RightParen,
Operator(Opcode),
Operand(Type),
Illegal,
}
#[derive(Debug)]
pub enum Opcode {
Add,
Subtract,
Multiply,
Divide,
And,
Or,
Gt,
Lt,
}
#[derive(Debug)]
pub enum Type {
Bool(bool),
Numerical(f64),
}
// Parentheses
named!(left_paren<&str, Token>, do_parse!(tag!("(") >> (Token::LeftParen)));
named!(right_paren<&str, Token>, do_parse!(tag!(")") >> (Token::RightParen)));
// Operators
named!(operator<&str, Token>, alt_complete!(op_add | op_sub | op_mul | op_div | op_and | op_or | op_gt | op_lt));
named!(op_add<&str, Token>, do_parse!(tag!("+") >> (Token::Operator(Opcode::Add))));
named!(op_sub<&str, Token>, do_parse!(tag!("-") >> (Token::Operator(Opcode::Subtract))));
named!(op_mul<&str, Token>, do_parse!(tag!("*") >> (Token::Operator(Opcode::Multiply))));
named!(op_div<&str, Token>, do_parse!(tag!("/") >> (Token::Operator(Opcode::Divide))));
named!(op_and<&str, Token>, do_parse!(tag!("&&") >> (Token::Operator(Opcode::And))));
named!(op_or<&str, Token>, do_parse!(tag!("||") >> (Token::Operator(Opcode::Or))));
named!(op_gt<&str, Token>, do_parse!(tag!(">") >> (Token::Operator(Opcode::Gt))));
named!(op_lt<&str, Token>, do_parse!(tag!("<") >> (Token::Operator(Opcode::Lt))));
// Operands
named!(operand<&str, Token>, alt_complete!(opand_bool | opand_num));
named!(opand_bool<&str, Token>, alt_complete!(opand_bool_true | opand_bool_false));
named!(opand_bool_true<&str, Token>, do_parse!(tag!("true") >> (Token::Operand(Type::Bool(true)))));
named!(opand_bool_false<&str, Token>, do_parse!(tag!("false") >> (Token::Operand(Type::Bool(false)))));
named!(opand_num<&str, Token>, do_parse!(num: double_s >> (Token::Operand(Type::Numerical(num)))));
// Illegal
named!(illegal<&str, Token>, do_parse!(take!(1) >> (Token::Illegal)));
named!(lex_expr<&str, Vec<Token> >, ws!(many0!(alt_complete!(left_paren | right_paren | operator | operand | illegal))));
fn main() {
match env::var("RUST_LOG") {
Ok(_) => env_logger::init(),
Err(_) => env_logger::Builder::from_default_env()
.filter_level(log::LevelFilter::Info)
.init(),
}
loop {
print!("> ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
match lex_expr(&input.trim()) {
Ok((rest, parsed)) => {
info!("Parsed {:?}, {:?} remains", parsed, rest);
}
Err(nom::Err::Incomplete(i)) => {
error!("Incomplete: {:?}", i);
}
Err(nom::Err::Failure(f)) => {
error!("Failure: {:?}", f);
}
Err(nom::Err::Error(e)) => {
error!("Other error: {:?}", e);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment