/* * Copyright 2022 Arnaud Golfouse * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use ielr::{ input::{Grammar, Node, Token}, output::{Action, Lookahead, Table}, }; pub struct Runtime<'a> { pub table: Table, pub grammar: &'a Grammar, } impl Runtime<'_> { pub fn is_valid(&self, start: Node, tokens: &[Token]) -> bool { let mut stack = Vec::new(); let start_state = self.table.get_starting_state(start).unwrap(); stack.push(start_state); let mut tokens = tokens.iter().copied().peekable(); loop { let top = *stack.last().unwrap(); let state = &self.table.states[top]; let lookahead = match tokens.peek() { Some(token) => Lookahead::Token(*token), None => Lookahead::Eof, }; match state.action_table().get_action(lookahead) { Some(Action::Shift(to_state)) => { tokens.next(); stack.push(to_state); } Some(Action::Reduce(production)) => { let rhs = self.grammar.get_rhs(production).unwrap(); for _ in 0..rhs.len() { stack.pop(); } let top = *stack.last().unwrap(); let state = &self.table.states[top]; match state.goto_table().get_goto(production.lhs) { Some(to_state) => { stack.push(to_state); } None => return false, } } Some(Action::Accept(node)) => { if node == start { break; } else { return false; } } None => return false, } } stack.len() == 2 } }