mirror of
				https://github.com/tursodatabase/libsql.git
				synced 2025-10-31 12:16:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			124 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| %token_type { i32 }
 | |
| 
 | |
| // An extra argument to the constructor for the parser, which is available
 | |
| // to all actions.
 | |
| %extra_context {ctx: Context}
 | |
| 
 | |
| %left PLUS MINUS.
 | |
| %left DIVIDE TIMES.
 | |
| 
 | |
| %include {
 | |
| 
 | |
| use log::{debug, error, log_enabled, Level, LevelFilter, Metadata, Record, SetLoggerError};
 | |
| 
 | |
| pub struct Context {
 | |
|     expr: Option<Expr>,
 | |
| }
 | |
| 
 | |
| #[derive(Debug)]
 | |
| pub enum Operator {
 | |
|     Add,
 | |
|     Substract,
 | |
|     Multiply,
 | |
|     Divide,
 | |
| }
 | |
| 
 | |
| #[derive(Debug)]
 | |
| pub enum Expr {
 | |
|     Number(i32),
 | |
|     Binary(Operator, Box<Expr>, Box<Expr>),
 | |
| }
 | |
| impl Expr {
 | |
|     fn binary(op: Operator, lhs: Expr, rhs: Expr) -> Expr {
 | |
|         Expr::Binary(op, Box::new(lhs), Box::new(rhs))
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn main() {
 | |
|     init_logger().unwrap();
 | |
| 
 | |
|     let r = Context { expr: None };
 | |
|     let mut p = yyParser::new(r);
 | |
|     p.Parse(TokenType::INTEGER, Some(5));
 | |
|     p.Parse(TokenType::PLUS, None);
 | |
|     p.Parse(TokenType::INTEGER, Some(10));
 | |
|     p.Parse(TokenType::TIMES, None);
 | |
|     p.Parse(TokenType::INTEGER, Some(4));
 | |
|     p.Parse(TokenType::EOF, None);
 | |
|     p.ParseFinalize();
 | |
|     let s = format!("{:?}", p.ctx.expr);
 | |
|     assert_eq!(s, "Some(Binary(Add, Number(5), Binary(Multiply, Number(10), Number(4))))");
 | |
| 
 | |
|     let r = Context { expr: None };
 | |
|     let mut p = yyParser::new(r);
 | |
|     p.Parse(TokenType::INTEGER, Some(15));
 | |
|     p.Parse(TokenType::DIVIDE, None);
 | |
|     p.Parse(TokenType::INTEGER, Some(5));
 | |
|     p.Parse(TokenType::EOF, None);
 | |
|     p.ParseFinalize();
 | |
|     let s = format!("{:?}", p.ctx.expr);
 | |
|     assert_eq!(s, "Some(Binary(Divide, Number(15), Number(5)))");
 | |
| 
 | |
|     let r = Context { expr: None };
 | |
|     let mut p = yyParser::new(r);
 | |
|     p.Parse(TokenType::INTEGER, Some(50));
 | |
|     p.Parse(TokenType::PLUS, None);
 | |
|     p.Parse(TokenType::INTEGER, Some(125));
 | |
|     p.Parse(TokenType::EOF, None);
 | |
|     p.ParseFinalize();
 | |
|     let s = format!("{:?}", p.ctx.expr);
 | |
|     assert_eq!(s, "Some(Binary(Add, Number(50), Number(125)))");
 | |
| 
 | |
|     let r = Context { expr: None };
 | |
|     let mut p = yyParser::new(r);
 | |
|     p.Parse(TokenType::INTEGER, Some(50));
 | |
|     p.Parse(TokenType::TIMES, None);
 | |
|     p.Parse(TokenType::INTEGER, Some(125));
 | |
|     p.Parse(TokenType::PLUS, None);
 | |
|     p.Parse(TokenType::INTEGER, Some(125));
 | |
|     p.Parse(TokenType::EOF, None);
 | |
|     p.ParseFinalize();
 | |
|     let s = format!("{:?}", p.ctx.expr);
 | |
|     assert_eq!(s, "Some(Binary(Add, Binary(Multiply, Number(50), Number(125)), Number(125)))");
 | |
| }
 | |
| 
 | |
| static LOGGER: Logger = Logger;
 | |
| struct Logger;
 | |
| 
 | |
| impl log::Log for Logger {
 | |
|     fn enabled(&self, metadata: &Metadata) -> bool {
 | |
|         metadata.level() <= Level::Debug
 | |
|     }
 | |
| 
 | |
|     fn log(&self, record: &Record) {
 | |
|         if self.enabled(record.metadata()) {
 | |
|             eprintln!("{} - {}", record.level(), record.args());
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     fn flush(&self) {
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn init_logger() -> Result<(), SetLoggerError> {
 | |
|     log::set_logger(&LOGGER)?;
 | |
|     log::set_max_level(LevelFilter::Debug);
 | |
|     Ok(())
 | |
| }
 | |
| }
 | |
| 
 | |
| %syntax_error {
 | |
|     let _ = yymajor;
 | |
|     println!("near token {:?}: syntax error", yyminor);
 | |
| }
 | |
| 
 | |
| program ::= expr(A). { self.ctx.expr = Some(A); }
 | |
| 
 | |
| %type expr { Expr }
 | |
| expr(A) ::= expr(B) MINUS expr(C). { A = Expr::binary(Operator::Substract, B, C); }
 | |
| expr(A) ::= expr(B) PLUS expr(C). { A = Expr::binary(Operator::Add, B, C); }
 | |
| expr(A) ::= expr(B) TIMES expr(C). { A = Expr::binary(Operator::Multiply, B, C); }
 | |
| expr(A) ::= expr(B) DIVIDE expr(C). { A = Expr::binary(Operator::Divide, B, C); }
 | |
| 
 | |
| expr(A) ::= INTEGER(B). { A = Expr::Number(B.unwrap()); }
 |