use TerminalLiteral instead of TerminalString where appropriate

This avoids a lot of unwraps and panics. I did copy the precedence code
but I plan to refactor that shortly.
This commit is contained in:
Niko Matsakis 2017-03-28 23:46:45 -06:00
parent 9c1317508e
commit 61c2ce1522
6 changed files with 32 additions and 32 deletions

View File

@ -108,7 +108,7 @@ impl MatchItem {
} }
} }
pub type MatchSymbol = TerminalString; pub type MatchSymbol = TerminalLiteral;
pub type MatchMapping = TerminalString; pub type MatchMapping = TerminalString;
/// Intern tokens are not typed by the user: they are synthesized in /// Intern tokens are not typed by the user: they are synthesized in
@ -119,7 +119,7 @@ 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<TerminalString, TerminalString>>, pub match_to_user_name_map: Option<Map<TerminalLiteral, TerminalString>>,
pub dfa: DFA pub dfa: DFA
} }
@ -340,6 +340,16 @@ impl TerminalLiteral {
TerminalLiteral::Regex(_, p) => p, TerminalLiteral::Regex(_, p) => p,
} }
} }
pub fn with_match_precedence(self, p: usize) -> TerminalLiteral {
// Multiply times two since we still want to distinguish
// between quoted and regex precedence
let base_precedence = p * 2;
match self {
TerminalLiteral::Quoted(i, _) => TerminalLiteral::Quoted(i, base_precedence+1),
TerminalLiteral::Regex(i, _) => TerminalLiteral::Regex(i, base_precedence+0),
}
}
} }
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
@ -383,17 +393,6 @@ impl TerminalString {
pub fn regex(i: InternedString) -> TerminalString { pub fn regex(i: InternedString) -> TerminalString {
TerminalString::Literal(TerminalLiteral::Regex(i, 0)) TerminalString::Literal(TerminalLiteral::Regex(i, 0))
} }
pub fn with_match_precedence(self, p: usize) -> TerminalString {
let base_precedence = p * 2; // Multiply times two since we still want to distinguish between quoted and regex precedence
match self {
TerminalString::Literal(TerminalLiteral::Quoted(i, _)) =>
TerminalString::Literal(TerminalLiteral::Quoted(i, base_precedence+1)),
TerminalString::Literal(TerminalLiteral::Regex(i, _)) =>
TerminalString::Literal(TerminalLiteral::Regex(i, base_precedence+0)),
_ => panic!("cannot set match precedence for {:?}", self)
}
}
} }
impl Into<Box<Content>> for TerminalString { impl Into<Box<Content>> for TerminalString {

View File

@ -91,7 +91,7 @@ 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(ref mm) = data.match_to_user_name_map {
if let Some(m) = mm.get(&TerminalString::Literal(literal)) { if let Some(m) = mm.get(&literal) {
return (m.clone(), pattern); return (m.clone(), pattern);
} }
} }

View File

@ -36,8 +36,8 @@ 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, sym); match_to_user.insert(precedence_sym, TerminalString::Literal(sym));
user_to_match.insert(sym, precedence_sym); user_to_match.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);
@ -94,7 +94,7 @@ 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, TerminalString>>, user_name_to_match_map: Option<Map<TerminalString, TerminalLiteral>>,
match_catch_all: Option<bool>, match_catch_all: Option<bool>,
} }
@ -175,9 +175,8 @@ impl<'grammar> Validator<'grammar> {
// 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 {
Some(ref m) => { Some(ref m) => {
if let Some(v) = m.get(&term) { 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
let vl = v.as_literal().expect("must map to a literal");
self.all_literals.entry(vl).or_insert(span); self.all_literals.entry(vl).or_insert(span);
} else { } else {
return_err!(span, "terminal `{}` does not have a match mapping defined for it", return_err!(span, "terminal `{}` does not have a match mapping defined for it",
@ -197,9 +196,8 @@ impl<'grammar> Validator<'grammar> {
TerminalString::Literal(l) => match self.user_name_to_match_map { TerminalString::Literal(l) => match self.user_name_to_match_map {
Some(ref m) => { Some(ref m) => {
if let Some(v) = m.get(&term) { 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
let vl = v.as_literal().expect("must map to a literal");
self.all_literals.entry(vl).or_insert(span); self.all_literals.entry(vl).or_insert(span);
} else { } else {
// Unwrap should be safe as we shouldn't have match_catch_all without user_name_to_match_map // Unwrap should be safe as we shouldn't have match_catch_all without user_name_to_match_map
@ -229,7 +227,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<TerminalString, TerminalString>>) -> NormResult<()> { pub fn construct(grammar: &mut Grammar, literals_map: Map<TerminalLiteral, Span>, match_to_user_name_map: Option<Map<TerminalLiteral, TerminalString>>) -> NormResult<()> {
let mut literals: Vec<TerminalLiteral> = let mut literals: Vec<TerminalLiteral> =
literals_map.keys() literals_map.keys()
.cloned() .cloned()

View File

@ -80,12 +80,11 @@ impl<'grammar> TypeInferencer<'grammar> {
let mut types = Types::new(&grammar.prefix, Some(loc_type), error_type, enum_type); let mut types = Types::new(&grammar.prefix, Some(loc_type), error_type, enum_type);
for &literal in &intern_token.literals { for &literal in &intern_token.literals {
let terminal_string = TerminalString::Literal(literal);
let user_name = intern_token.match_to_user_name_map let user_name = intern_token.match_to_user_name_map
.as_ref() .as_ref()
.and_then(|it| it.get(&terminal_string)) .and_then(|it| it.get(&literal))
.cloned() .cloned()
.unwrap_or(terminal_string); .unwrap_or(TerminalString::Literal(literal));
types.add_term_type(user_name, input_str.clone()); types.add_term_type(user_name, input_str.clone());
} }

View File

@ -251,7 +251,7 @@ MatchItem: MatchItem = {
} }
}; };
MatchSymbol = QuotedTerminal; MatchSymbol = QuotedLiteral;
pub MatchMapping = Terminal; pub MatchMapping = Terminal;
@ -340,8 +340,12 @@ Terminal: TerminalString = {
}; };
QuotedTerminal: TerminalString = { QuotedTerminal: TerminalString = {
<s:StringLiteral> => TerminalString::quoted(s), QuotedLiteral => TerminalString::Literal(<>),
<s:RegexLiteral> => TerminalString::regex(s), };
QuotedLiteral: TerminalLiteral = {
<s:StringLiteral> => TerminalLiteral::Quoted(s, 1),
<s:RegexLiteral> => TerminalLiteral::Regex(s, 0),
}; };
StringLiteral: InternedString = StringLiteral: InternedString =

View File

@ -49,7 +49,7 @@ fn match_complex() {
let item00 = contents0.items.get(0).unwrap(); let item00 = contents0.items.get(0).unwrap();
match *item00 { match *item00 {
MatchItem::Mapped(ref sym, ref mapping, _) => { MatchItem::Mapped(ref sym, ref mapping, _) => {
assert_eq!(format!("{:?}", sym), "r#\"(?i)begin\"#"); assert_eq!(format!("{:?}", sym), "r#\"(?i)begin\"#+0");
assert_eq!(format!("{}", mapping), "\"BEGIN\""); assert_eq!(format!("{}", mapping), "\"BEGIN\"");
}, },
_ => panic!("expected MatchItem::Mapped, but was: {:?}", item00) _ => panic!("expected MatchItem::Mapped, but was: {:?}", item00)
@ -58,7 +58,7 @@ fn match_complex() {
let item01 = contents0.items.get(1).unwrap(); let item01 = contents0.items.get(1).unwrap();
match *item01 { match *item01 {
MatchItem::Mapped(ref sym, ref mapping, _) => { MatchItem::Mapped(ref sym, ref mapping, _) => {
assert_eq!(format!("{:?}", sym), "r#\"(?i)end\"#"); assert_eq!(format!("{:?}", sym), "r#\"(?i)end\"#+0");
assert_eq!(format!("{}", mapping), "\"END\""); assert_eq!(format!("{}", mapping), "\"END\"");
}, },
_ => panic!("expected MatchItem::Mapped, but was: {:?}", item00) _ => panic!("expected MatchItem::Mapped, but was: {:?}", item00)
@ -69,7 +69,7 @@ fn match_complex() {
let item10 = contents1.items.get(0).unwrap(); let item10 = contents1.items.get(0).unwrap();
match *item10 { match *item10 {
MatchItem::Mapped(ref sym, ref mapping, _) => { MatchItem::Mapped(ref sym, ref mapping, _) => {
assert_eq!(format!("{:?}", sym), "r#\"[a-zA-Z_][a-zA-Z0-9_]*\"#"); assert_eq!(format!("{:?}", sym), "r#\"[a-zA-Z_][a-zA-Z0-9_]*\"#+0");
assert_eq!(format!("{}", mapping), "IDENTIFIER"); assert_eq!(format!("{}", mapping), "IDENTIFIER");
}, },
_ => panic!("expected MatchItem::Mapped, but was: {:?}", item10) _ => panic!("expected MatchItem::Mapped, but was: {:?}", item10)
@ -80,7 +80,7 @@ fn match_complex() {
let item20 = contents2.items.get(0).unwrap(); let item20 = contents2.items.get(0).unwrap();
match *item20 { match *item20 {
MatchItem::Unmapped(ref sym, _) => { MatchItem::Unmapped(ref sym, _) => {
assert_eq!(format!("{:?}", sym), "\"other\""); assert_eq!(format!("{:?}", sym), "\"other\"+1");
}, },
_ => panic!("expected MatchItem::Unmapped, but was: {:?}", item20) _ => panic!("expected MatchItem::Unmapped, but was: {:?}", item20)
}; };