Generalize precedence datatype to include strings

Right now, the strings are not used in comparisons, but they
are passed through the grammar processing pipeline, and are
available to the parse table construction algorithm.

This also cleans up a confusing aspect of the parse table
construction, in which precedences and associativities were
temporarily stored in the parse table data structure itself.
This commit is contained in:
Max Brunsfeld 2021-02-23 20:48:32 -08:00
parent 2f28a35e1b
commit d40f118370
10 changed files with 235 additions and 162 deletions

View file

@ -1,5 +1,5 @@
use super::grammars::{InputGrammar, Variable, VariableType};
use super::rules::Rule;
use super::rules::{Precedence, Rule};
use crate::error::Result;
use serde_derive::Deserialize;
use serde_json::{Map, Value};
@ -44,15 +44,15 @@ enum RuleJSON {
content: Box<RuleJSON>,
},
PREC_LEFT {
value: i32,
value: PrecedenceJSON,
content: Box<RuleJSON>,
},
PREC_RIGHT {
value: i32,
value: PrecedenceJSON,
content: Box<RuleJSON>,
},
PREC {
value: i32,
value: PrecedenceJSON,
content: Box<RuleJSON>,
},
TOKEN {
@ -63,6 +63,13 @@ enum RuleJSON {
},
}
#[derive(Deserialize)]
#[serde(untagged)]
enum PrecedenceJSON {
Integer(i32),
Name(String),
}
#[derive(Deserialize)]
pub(crate) struct GrammarJSON {
pub(crate) name: String,
@ -133,9 +140,13 @@ fn parse_rule(json: RuleJSON) -> Rule {
RuleJSON::REPEAT { content } => {
Rule::choice(vec![Rule::repeat(parse_rule(*content)), Rule::Blank])
}
RuleJSON::PREC { value, content } => Rule::prec(value, parse_rule(*content)),
RuleJSON::PREC_LEFT { value, content } => Rule::prec_left(value, parse_rule(*content)),
RuleJSON::PREC_RIGHT { value, content } => Rule::prec_right(value, parse_rule(*content)),
RuleJSON::PREC { value, content } => Rule::prec(value.into(), parse_rule(*content)),
RuleJSON::PREC_LEFT { value, content } => {
Rule::prec_left(value.into(), parse_rule(*content))
}
RuleJSON::PREC_RIGHT { value, content } => {
Rule::prec_right(value.into(), parse_rule(*content))
}
RuleJSON::PREC_DYNAMIC { value, content } => {
Rule::prec_dynamic(value, parse_rule(*content))
}
@ -144,6 +155,15 @@ fn parse_rule(json: RuleJSON) -> Rule {
}
}
impl Into<Precedence> for PrecedenceJSON {
fn into(self) -> Precedence {
match self {
PrecedenceJSON::Integer(i) => Precedence::Integer(i),
PrecedenceJSON::Name(i) => Precedence::Name(i),
}
}
}
#[cfg(test)]
mod tests {
use super::*;