mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-03-28 06:01:02 +00:00
make the map/catch-all non-optional in validator
This commit is contained in:
parent
61c2ce1522
commit
b75669c8d6
@ -119,7 +119,11 @@ pub struct InternToken {
|
|||||||
/// Set of `r"foo"` and `"foo"` literals extracted from the
|
/// Set of `r"foo"` and `"foo"` literals extracted from the
|
||||||
/// grammar. Sorted by order of increasing precedence.
|
/// grammar. Sorted by order of increasing precedence.
|
||||||
pub literals: Vec<TerminalLiteral>,
|
pub literals: Vec<TerminalLiteral>,
|
||||||
pub match_to_user_name_map: Option<Map<TerminalLiteral, TerminalString>>,
|
|
||||||
|
/// For each item remapped in a `match` block, map from the
|
||||||
|
/// regex we match to the name the user wants to use.
|
||||||
|
pub match_to_user_name_map: Map<TerminalLiteral, TerminalString>,
|
||||||
|
|
||||||
pub dfa: DFA
|
pub dfa: DFA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +90,8 @@ impl<'s> LowerState<'s> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: This should be cleaner
|
// FIXME: This should be cleaner
|
||||||
if let Some(ref mm) = data.match_to_user_name_map {
|
if let Some(&m) = data.match_to_user_name_map.get(&literal) {
|
||||||
if let Some(m) = mm.get(&literal) {
|
return (m, pattern);
|
||||||
return (m.clone(), pattern);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(TerminalString::Literal(literal), pattern)
|
(TerminalString::Literal(literal), pattern)
|
||||||
|
@ -23,11 +23,11 @@ pub fn validate(mut grammar: Grammar) -> NormResult<Grammar> {
|
|||||||
let (has_enum_token, all_literals, match_to_user_name_map) = {
|
let (has_enum_token, all_literals, match_to_user_name_map) = {
|
||||||
let opt_match_token = grammar.match_token();
|
let opt_match_token = grammar.match_token();
|
||||||
|
|
||||||
let (match_to_user_name_map, user_name_to_match_map, match_catch_all) = if let Some(mt) = opt_match_token {
|
let mut match_to_user_name_map = map();
|
||||||
let mut match_to_user = map();
|
let mut user_name_to_match_map = map();
|
||||||
let mut user_to_match = map();
|
let mut match_catch_all = false;
|
||||||
let mut catch_all = false;
|
|
||||||
|
|
||||||
|
if let Some(mt) = opt_match_token {
|
||||||
// FIXME: This should probably move _inside_ the Validator
|
// FIXME: This should probably move _inside_ the Validator
|
||||||
for (idx, mc) in mt.contents.iter().enumerate() {
|
for (idx, mc) in mt.contents.iter().enumerate() {
|
||||||
let precedence = &mt.contents.len() - idx;
|
let precedence = &mt.contents.len() - idx;
|
||||||
@ -36,23 +36,22 @@ pub fn validate(mut grammar: Grammar) -> NormResult<Grammar> {
|
|||||||
match *item {
|
match *item {
|
||||||
MatchItem::Unmapped(sym, _) => {
|
MatchItem::Unmapped(sym, _) => {
|
||||||
let precedence_sym = sym.with_match_precedence(precedence);
|
let precedence_sym = sym.with_match_precedence(precedence);
|
||||||
match_to_user.insert(precedence_sym, TerminalString::Literal(sym));
|
match_to_user_name_map.insert(precedence_sym, TerminalString::Literal(sym));
|
||||||
user_to_match.insert(TerminalString::Literal(sym), precedence_sym);
|
user_name_to_match_map.insert(TerminalString::Literal(sym), precedence_sym);
|
||||||
},
|
},
|
||||||
MatchItem::Mapped(sym, mapping, _) => {
|
MatchItem::Mapped(sym, mapping, _) => {
|
||||||
let precedence_sym = sym.with_match_precedence(precedence);
|
let precedence_sym = sym.with_match_precedence(precedence);
|
||||||
match_to_user.insert(precedence_sym, mapping);
|
match_to_user_name_map.insert(precedence_sym, mapping);
|
||||||
user_to_match.insert(mapping, precedence_sym);
|
user_name_to_match_map.insert(mapping, precedence_sym);
|
||||||
},
|
},
|
||||||
MatchItem::CatchAll(_) => { catch_all = true; }
|
MatchItem::CatchAll(_) => { match_catch_all = true; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some(match_to_user), Some(user_to_match), Some(catch_all))
|
|
||||||
} else {
|
} else {
|
||||||
(None, None, None)
|
// no match block is equivalent to `match { _ }`
|
||||||
};
|
match_catch_all = true;
|
||||||
|
}
|
||||||
|
|
||||||
let opt_enum_token = grammar.enum_token();
|
let opt_enum_token = grammar.enum_token();
|
||||||
let conversions = opt_enum_token.map(|et| {
|
let conversions = opt_enum_token.map(|et| {
|
||||||
@ -94,8 +93,8 @@ struct Validator<'grammar> {
|
|||||||
grammar: &'grammar Grammar,
|
grammar: &'grammar Grammar,
|
||||||
all_literals: Map<TerminalLiteral, Span>,
|
all_literals: Map<TerminalLiteral, Span>,
|
||||||
conversions: Option<Set<TerminalString>>,
|
conversions: Option<Set<TerminalString>>,
|
||||||
user_name_to_match_map: Option<Map<TerminalString, TerminalLiteral>>,
|
user_name_to_match_map: Map<TerminalString, TerminalLiteral>,
|
||||||
match_catch_all: Option<bool>,
|
match_catch_all: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'grammar> Validator<'grammar> {
|
impl<'grammar> Validator<'grammar> {
|
||||||
@ -173,15 +172,10 @@ impl<'grammar> Validator<'grammar> {
|
|||||||
// the terminal literals ("class", r"[a-z]+") into a set.
|
// the terminal literals ("class", r"[a-z]+") into a set.
|
||||||
None => match term {
|
None => match term {
|
||||||
// FIMXE: Should not allow undefined literals if no CatchAll
|
// FIMXE: Should not allow undefined literals if no CatchAll
|
||||||
TerminalString::Bare(c) => match self.user_name_to_match_map {
|
TerminalString::Bare(c) => match self.user_name_to_match_map.get(&term) {
|
||||||
Some(ref m) => {
|
Some(&vl) => {
|
||||||
if let Some(&vl) = m.get(&term) {
|
// FIXME: I don't think this span here is correct
|
||||||
// FIXME: I don't think this span here is correct
|
self.all_literals.entry(vl).or_insert(span);
|
||||||
self.all_literals.entry(vl).or_insert(span);
|
|
||||||
} else {
|
|
||||||
return_err!(span, "terminal `{}` does not have a match mapping defined for it",
|
|
||||||
term);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
@ -194,24 +188,20 @@ impl<'grammar> Validator<'grammar> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
TerminalString::Literal(l) => match self.user_name_to_match_map {
|
TerminalString::Literal(l) => match self.user_name_to_match_map.get(&term) {
|
||||||
Some(ref m) => {
|
Some(&vl) => {
|
||||||
if let Some(&vl) = m.get(&term) {
|
// FIXME: I don't think this span here is correct
|
||||||
// FIXME: I don't think this span here is correct
|
self.all_literals.entry(vl).or_insert(span);
|
||||||
self.all_literals.entry(vl).or_insert(span);
|
}
|
||||||
} else {
|
|
||||||
// Unwrap should be safe as we shouldn't have match_catch_all without user_name_to_match_map
|
|
||||||
if self.match_catch_all.unwrap() {
|
|
||||||
// FIXME: I don't think this span here is correct
|
|
||||||
self.all_literals.entry(l).or_insert(span);
|
|
||||||
} else {
|
|
||||||
return_err!(span, "terminal `{}` does not have a match mapping defined for it",
|
|
||||||
term);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
None => {
|
||||||
|
if self.match_catch_all {
|
||||||
|
self.all_literals.entry(l).or_insert(span);
|
||||||
|
} else {
|
||||||
|
return_err!(span, "terminal `{}` does not have a match mapping defined for it",
|
||||||
|
term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => { self.all_literals.entry(l).or_insert(span); }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Error is a builtin terminal that always exists
|
// Error is a builtin terminal that always exists
|
||||||
@ -227,7 +217,7 @@ impl<'grammar> Validator<'grammar> {
|
|||||||
// Construction phase -- if we are constructing a tokenizer, this
|
// Construction phase -- if we are constructing a tokenizer, this
|
||||||
// phase builds up an internal token DFA.
|
// phase builds up an internal token DFA.
|
||||||
|
|
||||||
pub fn construct(grammar: &mut Grammar, literals_map: Map<TerminalLiteral, Span>, match_to_user_name_map: Option<Map<TerminalLiteral, TerminalString>>) -> NormResult<()> {
|
pub fn construct(grammar: &mut Grammar, literals_map: Map<TerminalLiteral, Span>, match_to_user_name_map: Map<TerminalLiteral, TerminalString>) -> NormResult<()> {
|
||||||
let mut literals: Vec<TerminalLiteral> =
|
let mut literals: Vec<TerminalLiteral> =
|
||||||
literals_map.keys()
|
literals_map.keys()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -81,8 +81,7 @@ impl<'grammar> TypeInferencer<'grammar> {
|
|||||||
|
|
||||||
for &literal in &intern_token.literals {
|
for &literal in &intern_token.literals {
|
||||||
let user_name = intern_token.match_to_user_name_map
|
let user_name = intern_token.match_to_user_name_map
|
||||||
.as_ref()
|
.get(&literal)
|
||||||
.and_then(|it| it.get(&literal))
|
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(TerminalString::Literal(literal));
|
.unwrap_or(TerminalString::Literal(literal));
|
||||||
types.add_term_type(user_name, input_str.clone());
|
types.add_term_type(user_name, input_str.clone());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user