Skip to content

Instantly share code, notes, and snippets.

@augustt198
Created October 17, 2014 17:16
Show Gist options
  • Save augustt198/4fdc92075f23a845ed82 to your computer and use it in GitHub Desktop.
Save augustt198/4fdc92075f23a845ed82 to your computer and use it in GitHub Desktop.
fn is_alpha(c: char) -> bool {
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
#[allow(dead_code)]
struct StringReader {
pos: uint,
source: String,
col: uint,
line: uint
}
impl StringReader {
fn new(source: String) -> StringReader {
StringReader {
pos: 0,
line: 1,
col: 0,
source: source
}
}
fn peak(&mut self) -> Option<char> {
if self.pos < self.source.len() {
Some(self.source.as_slice().char_at(self.pos))
} else {
None
}
}
fn read(&mut self) -> Option<char> {
let next = self.peak();
if next.is_some() {
if next.unwrap() == '\n' {
self.line += 1;
self.col = 0;
} else {
self.col += 1;
}
self.pos += 1;
}
next
}
}
struct Lexer {
reader: StringReader
}
impl Lexer {
fn tok(&self, token_type: Type) -> Token {
Token { token_type: token_type, col: 0u, line: 0u }
}
fn next_token(&mut self) -> Token {
loop {
let c = match self.reader.read() {
Some(c) => c,
None => return self.tok(EOF)
};
if c == '(' { return self.tok(LParen) }
else if c == ')' { return self.tok(RParen) }
else if c == '&' { return self.tok(And) }
else if c == '|' { return self.tok(Or) }
else if c == '!' { return self.tok(Not) }
else if c == '^' { return self.tok(Xor) }
else if is_alpha(c) { return self.next_ident(c)}
else if c == ' ' || c == '\n' { continue }
else { fail!("Unexpected character: {}", c) }
}
}
fn next_ident(&mut self, current: char) -> Token {
let mut string = String::new();
string.push(current);
loop {
let peak = self.reader.peak();
if peak.is_some() && is_alpha(peak.unwrap()) {
string.push(peak.unwrap());
self.reader.read();
} else {
break
}
}
self.tok(Ident(string))
}
}
#[allow(dead_code)]
#[deriving(Show)]
enum Type {
LParen,
RParen,
Ident(String),
And,
Or,
Not,
Xor,
EOF
}
#[allow(dead_code)]
struct Token {
token_type: Type,
col: uint,
line: uint
}
struct Operation {
components: Vec<Component>,
ops: Vec<Token>
}
enum VarOrExpr {
Var(String),
Expr(Operation)
}
struct Component {
value: VarOrExpr,
negated: bool
}
struct Parser {
tokens: Vec<Token>,
pos: uint
}
impl Parser {
fn new(lexer: &mut Lexer) -> Parser {
let mut tokens = vec!();
let mut token;
loop {
token = lexer.next_token();
match token.token_type {
EOF => {
tokens.push(token);
break
},
_ => {
tokens.push(token);
}
}
}
Parser { tokens: tokens, pos: 0 }
}
fn next(&self) -> Token {
let idx = self.pos;
self.pos += 1;
self.tokens[self.pos]
}
fn back(&self) { self.pos -= 1; }
fn parse(&self) -> Operation {
let op = Operation { components: vec!(), ops: vec!() };
let component = self.component();
let token = self.next();
loop {
match token.token_type {
Or | Xor | And => {
op.ops.push(token);
op.components.push(self.component());
},
_ => {
self.back();
break;
}
};
}
op
}
fn component(&self) -> Component {
let token = self.next();
let neg = false;
let val: VarOrExpr;
loop {
match token.token_type {
Not => neg = !neg,
LParen => {
val = Expr(self.parse());
self.read(); // we want RParen
// TODO ...
}
}
fn main() {
let mut lexer = Lexer { reader: StringReader::new("!!!hello".to_string()) };
loop {
let tok = lexer.next_token();
println!("{}", tok.token_type)
match tok.token_type {
EOF => break,
_ => {}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment