diff --git a/crates/generated_parser/src/lib.rs b/crates/generated_parser/src/lib.rs index 837360417..d7e148bc8 100644 --- a/crates/generated_parser/src/lib.rs +++ b/crates/generated_parser/src/lib.rs @@ -18,8 +18,9 @@ pub use ast_builder::{AstBuilder, AstBuilderDelegate}; pub use declaration_kind::DeclarationKind; pub use error::{ParseError, Result}; pub use parser_tables_generated::{ - full_actions, noop_actions, ErrorCode, NonterminalId, ParseTable, ParserTrait, Term, TermValue, - TerminalId, START_STATE_MODULE, START_STATE_SCRIPT, TABLES, + full_actions, noop_actions, ErrorCode, NonterminalId, ParseTable, Term, TerminalId, + START_STATE_MODULE, START_STATE_SCRIPT, TABLES, }; pub use stack_value_generated::StackValue; pub use token::{Token, TokenValue}; +pub use traits::{ParserTrait, TermValue}; diff --git a/crates/generated_parser/src/traits/mod.rs b/crates/generated_parser/src/traits/mod.rs index 117c3d984..cc1ede4fd 100644 --- a/crates/generated_parser/src/traits/mod.rs +++ b/crates/generated_parser/src/traits/mod.rs @@ -1,6 +1,34 @@ +use crate::error::Result; +use crate::parser_tables_generated::Term; + /// This macro is pre-processed by the python grammar processor and generate /// code out-side the current context. #[macro_export] macro_rules! grammar_extension { ( $($_:tt)* ) => {}; } + +/// Aggregate a Value (= StackValue or ()) and a nonterminal/terminal as a stack +/// element. The term is currently used for replaying the parse table when +/// handling errors and non-optimized reduced actions with lookahead. +#[derive(Debug)] +pub struct TermValue { + pub term: Term, + pub value: Value, +} + +/// The parser trait is an abstraction to define the primitive of an LR Parser +/// with variable lookahead which can be replayed. +pub trait ParserTrait<'alloc, Value> { + fn shift(&mut self, tv: TermValue) -> Result<'alloc, bool>; + fn unshift(&mut self); + fn rewind(&mut self, n: usize) { + for _ in 0..n { + self.unshift(); + } + } + fn pop(&mut self) -> TermValue; + fn replay(&mut self, tv: TermValue); + fn epsilon(&mut self, state: usize); + fn check_not_on_new_line(&mut self, peek: usize) -> Result<'alloc, bool>; +} diff --git a/jsparagus/emit/rust.py b/jsparagus/emit/rust.py index 29f357aee..c5a2ad6b8 100644 --- a/jsparagus/emit/rust.py +++ b/jsparagus/emit/rust.py @@ -365,7 +365,6 @@ def emit(self): self.shift() self.error_codes() self.check_camel_case() - self.parser_trait() self.actions() self.entry() @@ -381,6 +380,7 @@ def header(self): self.write(0, "") self.write(0, "use crate::ast_builder::AstBuilderDelegate;") self.write(0, "use crate::stack_value_generated::{StackValue, TryIntoStack};") + self.write(0, "use crate::traits::{TermValue, ParserTrait};") self.write(0, "use crate::error::Result;") traits = OrderedSet() for mode_traits in self.parse_table.exec_modes.values(): @@ -647,28 +647,6 @@ def type_to_rust(self, ty, namespace="", boxed=False): else: return rty - def parser_trait(self): - self.write(0, "#[derive(Debug)]") - self.write(0, "pub struct TermValue {") - self.write(1, "pub term: Term,") - self.write(1, "pub value: Value,") - self.write(0, "}") - self.write(0, "") - self.write(0, "pub trait ParserTrait<'alloc, Value> {") - self.write(1, "fn shift(&mut self, tv: TermValue) -> Result<'alloc, bool>;") - self.write(1, "fn unshift(&mut self);") - self.write(1, "fn rewind(&mut self, n: usize) {") - self.write(2, "for _ in 0..n {") - self.write(3, "self.unshift();") - self.write(2, "}") - self.write(1, "}") - self.write(1, "fn pop(&mut self) -> TermValue;") - self.write(1, "fn replay(&mut self, tv: TermValue);") - self.write(1, "fn epsilon(&mut self, state: usize);") - self.write(1, "fn check_not_on_new_line(&mut self, peek: usize) -> Result<'alloc, bool>;") - self.write(0, "}") - self.write(0, "") - def actions(self): # For each execution mode, add a corresponding function which # implements various traits. The trait list is used for filtering which