Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use crate::Token;
- use crate::TokenType;
- use TokenType::*;
- use crate::vm::VmError;
- use crate::Op::*;
- use Precedence::*;
- use std::vec::IntoIter;
- //only needs lifetime parameter because
- //token contains string slice
- struct Parser<'a> {
- previous: Token<'a>,
- current: Token<'a>,
- }
- struct ParseRule {
- prefix: for<'a, 'b> fn(&'a mut Compiler<'b>),//Fn<&'a mut self>,
- infix: for<'a, 'b> fn(&'a mut Compiler<'b>),//Fn<&'a mut self>,
- prec: Precedence,
- }
- //impl ParseRule {
- // fn new(pre: fn(&mut self), in: fn(&mut self), prec: Precedence) -> Self {
- // ParseRule{ prefix: pre, infix: in, prec: prec }
- // }
- //}
- #[repr(u8)]
- enum Precedence {
- Primary,
- Call, // . ()
- Unary, // !
- Factor, // * /
- Term, // + -
- Comparison, // > < >= <=
- Equality,
- And,
- Or,
- Assignemnt,
- Null,
- }
- pub struct Compiler<'a> {
- parser: Parser<'a>,
- tokens: IntoIter<Token<'a>>,
- bytecode: Vec<u8>,
- const_pool: Vec<f64>,
- }
- impl<'a> Compiler<'a> {
- pub fn new(tokens: Vec<Token<'a>>) -> Self {
- Self {
- tokens: tokens.into_iter(),
- parser: Parser {
- previous: Token {
- kind: Blank,
- line_num: 0,
- content: ""
- },
- current: Token {
- kind: Blank,
- line_num: 0,
- content: ""
- }
- },
- const_pool: vec![],
- bytecode: vec![],
- }
- }
- //just implement the authors way, and change later
- pub fn compile(&mut self) -> Result<Vec<u8>, VmError> {
- while let Some(token) = self.tokens.next() {
- self.parser.previous = self.parser.current;
- self.parser.current = token;
- match token.kind {
- Number => {
- self.number();
- },
- LeftParen => {
- //expression() is probably just compile()
- self.grouping();
- },
- _ => todo!()
- };
- }
- //FIND way to clone without copying when you're not tired
- Ok(std::mem::take(&mut self.bytecode))
- }
- fn expression<'b>(&'b mut self) {
- self.parse_precedence(Assignemnt);
- }
- //prolly gonna have to change this later
- fn grouping<'b>(&'b mut self) {
- //Never be afraid to express yourself :)
- self.expression();
- if self.tokens.next().map(|token| token.kind) != Some(RightParen) { panic!("Expected ')'"); }
- }
- fn number<'b>(&'b mut self) {
- let val = self.parser.current.content.parse::<f64>().unwrap();
- self.const_pool.push(val);
- if self.const_pool.len() > 256 { panic!("No room in const pool"); }
- self.bytecode.push(OpConstant as u8);
- self.bytecode.push((self.const_pool.len()-1) as u8);
- }
- //keep for now, possibly remove later
- fn unary<'b>(&'b mut self) {
- let op = self.parser.previous.kind;
- self.expression();
- match op {
- Minus => {
- self.bytecode.push(OpNegate as u8);
- },
- _ => unreachable!(),
- };
- }
- //What the fuck
- fn parse_precedence(&mut self, level: Precedence) {
- }
- fn get_rule<'b>(&'b mut self, token_type: TokenType) -> ParseRule {
- let null_fn = || {};
- match token_type {
- LeftParen => ParseRule{ prefix: Compiler::<'b>::<'b>::grouping, infix: null_fn, prec: Null },
- Minus => ParseRule{ prefix: Compiler::<'b>::unary, infix: Compiler::<'b>::binary, prec: Term },
- Plus => ParseRule{ prefix: null_fn, infix: Compiler::<'b>::binary, prec: Term },
- Slash => ParseRule{ prefix: null_fn, infix: Compiler::<'b>::binary, prec: Factor },
- Star => ParseRule{ prefix: null_fn, infix: Compiler::<'b>::binary, prec: Factor },
- Number => ParseRule{ prefix: Compiler::<'b>::number, infix: null_fn, prec: Null },
- _ => ParseRule{ prefix: null_fn, infix: null_fn, prec: Null },
- }
- }
- }
- /*
- Lox book C code reference:
- bool compile(const char* source, Chunk* chunk) {
- initScanner(source);
- advance();
- expression();
- consume(TOKEN_EOF, "Expect end of expression.");
- }
- //is this handled automatically in loop?
- void initScanner(const char* source) {
- scanner.start = source;
- scanner.current = source;
- scanner.line = 1;
- }
- static void advance() {
- parser.previous = parser.current;
- parser.current = scanToken();
- }
- //scanner is for scanning TEXT, not tokens
- //handle with for loop
- Token scanToken() {
- scanner.start = scanner.current;
- if (isAtEnd()) return makeToken(TOKEN_EOF);
- return errorToken("Unexpected character.");
- }
- static void consume(TokenType type, const char* message) {
- if (parser.current.type == type) {
- advance();
- return;
- }
- errorAtCurrent(message);
- }
- static void number() {
- double value = strtod(parser.previous.start, NULL);
- emitConstant(value);
- }
- static void unary() {
- TokenType operatorType = parser.previous.type;
- // Compile the operand.
- expression();
- // Emit the operator instruction.
- switch (operatorType) {
- case TOKEN_MINUS: emitByte(OP_NEGATE); break;
- default: return; // Unreachable.
- }
- }
- static void parsePrecedence(Precedence precedence) {
- // What goes here?
- }
- */
Add Comment
Please, Sign In to add comment