Last active
April 3, 2022 06:21
-
-
Save amorphobia/e781c9a12ee10a164eea2ede41dff8e4 to your computer and use it in GitHub Desktop.
龙书图2-27例程的 Rust 移植版本
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
import readchar | |
class Parser: | |
def __init__(self): | |
self.lookahead = readchar.readchar() | |
def expr(self): | |
self.term() | |
while True: | |
if self.lookahead == b'+': | |
self.match(b'+') | |
self.term() | |
print('+', end='') | |
elif self.lookahead == b'-': | |
self.match(b'-') | |
self.term() | |
print('-', end='') | |
else: | |
return | |
def term(self): | |
if self.lookahead.isdigit(): | |
print(self.lookahead.decode("utf-8"), end='') | |
self.match(self.lookahead) | |
else: | |
raise Exception("syntax error") | |
def match(self, t): | |
if self.lookahead == t: | |
self.lookahead = readchar.readchar() | |
else: | |
raise Exception("syntax error") | |
if __name__ == '__main__': | |
parse = Parser() | |
parse.expr() | |
print("") |
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
use std::fmt; | |
use std::io::{Error, ErrorKind, Read}; | |
enum ParseError { | |
SyntaxError, | |
Parse(Error), | |
} | |
impl From<Error> for ParseError { | |
fn from(err: Error) -> Self { | |
ParseError::Parse(err) | |
} | |
} | |
impl fmt::Display for ParseError { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
match *self { | |
ParseError::SyntaxError => write!(f, "syntax error"), | |
ParseError::Parse(ref e) => e.fmt(f), | |
} | |
} | |
} | |
struct Parser { | |
lookahead: u8, | |
} | |
impl Parser { | |
pub fn new() -> Self { | |
let ch = read_char().expect("Cannot read charactor from input!"); | |
Self { lookahead: ch } | |
} | |
pub fn expr(&mut self) -> Result<(), ParseError> { | |
self.term()?; | |
loop { | |
let c = self.lookahead; | |
match c { | |
b'+' | b'-' => { | |
self.pmatch(c)?; | |
self.term()?; | |
print!("{}", char::from(c)); | |
} | |
_ => return Ok(()), | |
} | |
} | |
} | |
pub fn term(&mut self) -> Result<(), ParseError> { | |
if self.lookahead.is_ascii_digit() { | |
print!("{}", char::from(self.lookahead)); | |
self.pmatch(self.lookahead) | |
} else { | |
Err(ParseError::SyntaxError) | |
} | |
} | |
pub fn pmatch(&mut self, t: u8) -> Result<(), ParseError> { | |
if self.lookahead == t { | |
let input = read_char()?; | |
self.lookahead = input; | |
Ok(()) | |
} else { | |
Err(ParseError::SyntaxError) | |
} | |
} | |
} | |
fn read_char() -> Result<u8, Error> { | |
std::io::stdin() | |
.bytes() | |
.filter(|b| match *b { | |
Ok(b) => b != b' ', | |
Err(_) => false, | |
}) | |
.next() | |
.unwrap_or(Err(Error::new(ErrorKind::Other, "Cannot read from stdin!"))) | |
} | |
fn main() { | |
let mut parse = Parser::new(); | |
match parse.expr() { | |
Ok(_) => println!(""), | |
Err(e) => println!("{}", e), | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment