Skip to content

Instantly share code, notes, and snippets.

@amorphobia
Last active April 3, 2022 06:21
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 amorphobia/e781c9a12ee10a164eea2ede41dff8e4 to your computer and use it in GitHub Desktop.
Save amorphobia/e781c9a12ee10a164eea2ede41dff8e4 to your computer and use it in GitHub Desktop.
龙书图2-27例程的 Rust 移植版本
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("")
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