From cc155debd777bc1045067b39fd76f349f80cafdc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 17 Jun 2015 06:16:44 -0400 Subject: [PATCH] Various bits of cleanup; add some routines to compute type repr from parse-tree given types table --- src/grammar/parse_tree.rs | 38 ++++++++++++++++++++++++++++++++++- src/grammar/repr.rs | 10 +++++++-- src/normalize/mod.rs | 3 ++- src/normalize/tyinfer/mod.rs | 12 +++++------ src/normalize/tyinfer/test.rs | 19 +----------------- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/grammar/parse_tree.rs b/src/grammar/parse_tree.rs index 3d0c342..3116aa2 100644 --- a/src/grammar/parse_tree.rs +++ b/src/grammar/parse_tree.rs @@ -60,7 +60,7 @@ grammar Type<'input, T> { */ use intern::{intern, InternedString}; -use grammar::repr::TypeRepr; +use grammar::repr::{Types, TypeRepr}; use std::fmt::{Display, Formatter, Error}; use util::Sep; @@ -222,6 +222,20 @@ impl Symbol { pub fn canonical_form(&self) -> String { format!("{}", self) } + + pub fn type_repr(&self, types: &Types) -> TypeRepr { + match *self { + Symbol::Terminal(_) => types.terminal_type().clone(), + Symbol::Nonterminal(id) => types.nt_type(id).unwrap().clone(), + Symbol::Choose(ref s) => s.type_repr(types), + Symbol::Name(_, ref s) => s.type_repr(types), + Symbol::Repeat(ref r) => r.op.type_repr(r.symbol.type_repr(types)), + + Symbol::Expr(..) | Symbol::Macro(..) => { + unreachable!("symbol {} should have been expanded away", self) + } + } + } } impl Display for Symbol { @@ -326,3 +340,25 @@ impl RepeatOp { TypeRepr::Nominal { path: path, types: vec![symbol_type] } } } + +impl TypeRef { + // Converts a TypeRef to a TypeRepr, assuming no inference is + // required etc. This is safe for all types a user can directly + // type, but not safe for the result of expanding macros. + pub fn type_repr(&self) -> TypeRepr { + match *self { + TypeRef::Tuple(ref types) => + TypeRepr::Tuple(types.iter().map(TypeRef::type_repr).collect()), + TypeRef::Nominal { ref path, ref types } => + TypeRepr::Nominal { path: path.clone(), + types: types.iter().map(TypeRef::type_repr).collect() }, + TypeRef::Lifetime(id) => + TypeRepr::Lifetime(id), + TypeRef::Id(id) => + TypeRepr::Nominal { path: vec![id], + types: vec![] }, + TypeRef::OfSymbol(_) => + unreachable!("OfSymbol produced by parser") + } + } +} diff --git a/src/grammar/repr.rs b/src/grammar/repr.rs index b944134..441b413 100644 --- a/src/grammar/repr.rs +++ b/src/grammar/repr.rs @@ -26,18 +26,24 @@ pub enum TypeRepr { #[derive(Debug)] pub struct Types { + terminal_type: TypeRepr, nonterminal_types: HashMap } impl Types { - pub fn new() -> Types { - Types { nonterminal_types: HashMap::new() } + pub fn new(terminal_type: TypeRepr) -> Types { + Types { terminal_type: terminal_type, + nonterminal_types: HashMap::new() } } pub fn add_type(&mut self, nt_id: InternedString, ty: TypeRepr) { assert!(self.nonterminal_types.insert(nt_id, ty).is_none()); } + pub fn terminal_type(&self) -> &TypeRepr { + &self.terminal_type + } + pub fn nt_type(&self, nt_id: InternedString) -> Option<&TypeRepr> { self.nonterminal_types.get(&nt_id) } diff --git a/src/normalize/mod.rs b/src/normalize/mod.rs index fc40820..53e3c30 100644 --- a/src/normalize/mod.rs +++ b/src/normalize/mod.rs @@ -42,7 +42,8 @@ mod macro_expand; // Computes types where the user omitted them (or from macro // byproducts). // -// AFTER THIS POINT: All explicit types, no `OfSymbol` types. +// AFTER THIS POINT: there is a separate `repr::Types` table +// providing all nonterminals with an explicit type. mod tyinfer; // Synthesizes action code for all nonterminals. diff --git a/src/normalize/tyinfer/mod.rs b/src/normalize/tyinfer/mod.rs index efead4f..9ac0d22 100644 --- a/src/normalize/tyinfer/mod.rs +++ b/src/normalize/tyinfer/mod.rs @@ -16,7 +16,6 @@ pub fn infer_types(grammar: &Grammar) -> NormResult { } struct TypeInferencer<'grammar> { - token_type: &'grammar TypeRef, stack: Vec, nonterminals: HashMap>, types: Types, @@ -29,7 +28,7 @@ struct NT<'grammar> { alternatives: &'grammar Vec, } -fn extract_token_type(grammar: &Grammar) -> NormResult<&TypeRef> { +fn extract_token_type(grammar: &Grammar) -> NormResult { let mut token_types = grammar.items .iter() @@ -50,7 +49,7 @@ fn extract_token_type(grammar: &Grammar) -> NormResult<&TypeRef> { return_err!(grammar.span, "multiple token types specified"); } - Ok(token_type) + Ok(token_type.type_repr()) } impl<'grammar> TypeInferencer<'grammar> { @@ -73,10 +72,9 @@ impl<'grammar> TypeInferencer<'grammar> { }) .collect(); - Ok(TypeInferencer { token_type: token_type, - stack: vec![], + Ok(TypeInferencer { stack: vec![], nonterminals: nonterminals, - types: Types::new() }) + types: Types::new(token_type) }) } fn infer_types(mut self) -> NormResult { @@ -197,7 +195,7 @@ impl<'grammar> TypeInferencer<'grammar> { fn symbol_type(&mut self, symbol: &Symbol) -> NormResult { match *symbol { - Symbol::Terminal(_) => self.type_ref(self.token_type), + Symbol::Terminal(_) => Ok(self.types.terminal_type().clone()), Symbol::Nonterminal(id) => self.nonterminal_type(id), Symbol::Choose(ref s) => self.symbol_type(s), Symbol::Name(_, ref s) => self.symbol_type(s), diff --git a/src/normalize/tyinfer/test.rs b/src/normalize/tyinfer/test.rs index 85b5a0d..0aa2f22 100644 --- a/src/normalize/tyinfer/test.rs +++ b/src/normalize/tyinfer/test.rs @@ -7,24 +7,7 @@ use grammar::repr::TypeRepr; fn type_repr(s: &str) -> TypeRepr { let type_ref = parser::parse_type_ref(s).unwrap(); - return convert(type_ref); - - fn convert(t: TypeRef) -> TypeRepr { - match t { - TypeRef::Tuple(types) => - TypeRepr::Tuple(types.into_iter().map(convert).collect()), - TypeRef::Nominal { path, types } => - TypeRepr::Nominal { path: path, - types: types.into_iter().map(convert).collect() }, - TypeRef::Lifetime(id) => - TypeRepr::Lifetime(id), - TypeRef::Id(id) => - TypeRepr::Nominal { path: vec![id], - types: vec![] }, - TypeRef::OfSymbol(_) => - unreachable!("OfSymbol produced by parser") - } - } + return type_ref.type_repr(); } fn compare(g1: &str, expected: Vec<(&'static str, &'static str)>) {