Created
October 17, 2014 17:16
-
-
Save augustt198/4fdc92075f23a845ed82 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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