Skip to content

Commit

Permalink
Expose API to use SPPF as output of RNGLR parsers (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
woutersl committed Oct 5, 2023
1 parent 407a0d7 commit e60ca6c
Show file tree
Hide file tree
Showing 8 changed files with 476 additions and 200 deletions.
10 changes: 10 additions & 0 deletions himecc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ pub fn main() -> miette::Result<()> {
"rnglalr1"
])
)
.arg(
Arg::new("debug")
.long("debug")
.help("Print debug data when building a grammar.")
.takes_value(false)
.required(false)
)
.arg(
Arg::new("rust_no_std")
.long("--no-std")
Expand Down Expand Up @@ -206,6 +213,9 @@ pub fn main() -> miette::Result<()> {
Some("rnglalr1") => task.method = Some(ParsingMethod::RNGLALR1),
_ => {}
}
if matches.is_present("debug") {
task.print_debug_data = Some(true);
}
if matches.is_present("rust_no_std") {
task.rust_use_std = Some(false);
}
Expand Down
21 changes: 21 additions & 0 deletions runtime-rust/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,27 @@ impl TableElemRef {
pub fn index(self) -> usize {
self.data & 0x3FFF_FFFF
}

/// Formats this table reference
///
/// # Errors
///
/// Propagates the error from `write!`
pub fn fmt(
&self,
f: &mut Formatter<'_>,
variables: &[Symbol],
virtuals: &[Symbol]
) -> Result<(), Error> {
match self.table_type() {
TableType::None => write!(f, "none[{}]", self.index())?,
TableType::Token => write!(f, "token[{}]", self.index())?,
TableType::Variable => write!(f, "{}", variables[self.index()].name)?,
TableType::Virtual => write!(f, "{}", virtuals[self.index()].name)?
}

Ok(())
}
}

/// Represents a cell in an AST inner structure
Expand Down
24 changes: 7 additions & 17 deletions runtime-rust/src/lexers/fuzzy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ struct FuzzyMatcherHead {
/// The associated DFA state
state: u32,
/// The data representing this head
errors: Option<Vec<u32>>
errors: Vec<u32>
}

impl FuzzyMatcherHead {
/// Initializes this head with a state and a 0 distance
pub fn new(state: u32) -> FuzzyMatcherHead {
FuzzyMatcherHead {
state,
errors: None
errors: Vec::new()
}
}

Expand All @@ -58,33 +58,23 @@ impl FuzzyMatcherHead {
distance: usize
) -> FuzzyMatcherHead {
let mut errors = Vec::with_capacity(distance);
if previous.errors.is_some() {
let others = previous.errors.as_ref().unwrap();
for x in others {
errors.push(*x);
}
for &error in &previous.errors {
errors.push(error);
}
while errors.len() < distance {
errors.push(offset as u32);
}
FuzzyMatcherHead {
state,
errors: Some(errors)
}
FuzzyMatcherHead { state, errors }
}

/// Gets the Levenshtein distance of this head from the input
pub fn get_distance(&self) -> usize {
if self.errors.is_none() {
0
} else {
self.errors.as_ref().unwrap().len()
}
self.errors.len()
}

/// Gets the offset in the input of the i-th lexical error on this head
pub fn get_error(&self, i: usize) -> u32 {
self.errors.as_ref().unwrap()[i]
self.errors[i]
}
}

Expand Down
46 changes: 13 additions & 33 deletions runtime-rust/src/parsers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,60 +169,40 @@ struct LRContextOpening {
#[derive(Default, Clone)]
pub struct LRContexts {
/// The contexts, if any
openings: Option<Vec<LRContextOpening>>
openings: Vec<LRContextOpening>
}

impl LRContexts {
/// Initializes empty contexts
#[must_use]
pub fn new() -> LRContexts {
LRContexts { openings: None }
LRContexts {
openings: Vec::new()
}
}

/// Registers a new context
pub fn add(&mut self, identifier: u16, context: u16) {
match self.openings.as_mut() {
None => {
self.openings = Some(alloc::vec![LRContextOpening {
identifier,
context
}]);
}
Some(data) => {
data.push(LRContextOpening {
identifier,
context
});
}
}
self.openings.push(LRContextOpening {
identifier,
context
});
}

/// Gets whether the specified context opens by a transition using the specified terminal ID
#[must_use]
pub fn opens(&self, terminal_id: u32, context: u16) -> bool {
match self.openings.as_ref() {
None => false,
Some(data) => {
for x in data {
if u32::from(x.identifier) == terminal_id && x.context == context {
return true;
}
}
false
}
}
self.openings.iter().any(|opening| {
u32::from(opening.identifier) == terminal_id && opening.context == context
})
}

/// Gets the context opened by a symbol, if any
#[must_use]
pub fn get_context_opened_by(&self, terminal_id: u32) -> Option<u16> {
self.openings
.as_ref()
.and_then(|openings| {
openings
.iter()
.find(|op| u32::from(op.identifier) == terminal_id)
})
.iter()
.find(|op| u32::from(op.identifier) == terminal_id)
.map(|op| op.context)
}
}
Expand Down
Loading

0 comments on commit e60ca6c

Please sign in to comment.