From ba1a9b1d5259f022e298c385841a39f420ce4155 Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Fri, 20 Nov 2020 16:22:38 +0000 Subject: Implement context traits for Vec --- src/ast/mod.rs | 10 ++--- src/ast/typed.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 125 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 10054fc..280a646 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -390,11 +390,11 @@ impl Type for Variable { } fn first_set(&self, context: &mut C) -> Option { - context.get_first_set(self.index) + context.get_first_set(self.index).cloned() } fn flast_set(&self, context: &mut C) -> Option { - context.get_flast_set(self.index) + context.get_flast_set(self.index).cloned() } fn well_typed(self, context: &mut C) -> Result { @@ -587,15 +587,15 @@ pub struct Typed { impl Typed { pub fn is_nullable(&self) -> bool { - todo!() + self.nullable } pub fn first_set(&self) -> &FirstSet { - todo!() + &self.first_set } pub fn flast_set(&self) -> &FlastSet { - todo!() + &self.flast_set } } diff --git a/src/ast/typed.rs b/src/ast/typed.rs index e277cbb..dee13be 100644 --- a/src/ast/typed.rs +++ b/src/ast/typed.rs @@ -87,10 +87,67 @@ pub trait NullContext { fn push_nullable R, R>(&mut self, nullable: bool, f: F) -> R; } +impl NullContext for Vec { + type PushNull = Self; + + fn get_depth(&self) -> usize { + self.len() + } + + fn get_nullable(&self, index: usize) -> Option { + self.get(self.len() - index - 1).copied() + } + + fn push_nullable R, R>(&mut self, nullable: bool, f: F) -> R { + self.push(nullable); + let res = f(self); + self.pop(); + res + } +} + +impl NullContext for Vec<(bool, FirstSet)> { + type PushNull = Self; + + fn get_depth(&self) -> usize { + self.len() + } + + fn get_nullable(&self, index: usize) -> Option { + self.get(self.len() - index - 1).map(|(null, _)| null).copied() + } + + fn push_nullable R, R>(&mut self, nullable: bool, f: F) -> R { + self.push((nullable, FirstSet::new())); + let res = f(self); + self.pop(); + res + } +} + +impl NullContext for Vec<(bool, FirstSet, FlastSet)> { + type PushNull = Self; + + fn get_depth(&self) -> usize { + self.len() + } + + fn get_nullable(&self, index: usize) -> Option { + self.get(self.len() - index - 1).map(|(null, _, _)| null).copied() + } + + fn push_nullable R, R>(&mut self, nullable: bool, f: F) -> R { + self.push((nullable, FirstSet::new(), FlastSet::new())); + let res = f(self); + self.pop(); + res + } +} + pub trait FirstSetContext: NullContext { type PushFirstSet: FirstSetContext; - fn get_first_set(&self, index: usize) -> Option; + fn get_first_set(&self, index: usize) -> Option<&FirstSet>; fn push_first_set R, R>( &mut self, @@ -100,10 +157,50 @@ pub trait FirstSetContext: NullContext { ) -> R; } +impl FirstSetContext for Vec<(bool, FirstSet)> { + type PushFirstSet = Self; + + fn get_first_set(&self, index: usize) -> Option<&FirstSet> { + self.get(self.len() - index - 1).map(|(_, first_set)| first_set) + } + + fn push_first_set R, R>( + &mut self, + nullable: bool, + first_set: FirstSet, + f: F, + ) -> R { + self.push((nullable, first_set)); + let res = f(self); + self.pop(); + res + } +} + +impl FirstSetContext for Vec<(bool, FirstSet, FlastSet)> { + type PushFirstSet = Self; + + fn get_first_set(&self, index: usize) -> Option<&FirstSet> { + self.get(self.len() - index - 1).map(|(_, first_set, _)| first_set) + } + + fn push_first_set R, R>( + &mut self, + nullable: bool, + first_set: FirstSet, + f: F, + ) -> R { + self.push((nullable, first_set, FlastSet::new())); + let res = f(self); + self.pop(); + res + } +} + pub trait FlastSetContext: FirstSetContext { type PushFlastSet: FlastSetContext; - fn get_flast_set(&self, index: usize) -> Option; + fn get_flast_set(&self, index: usize) -> Option<&FlastSet>; fn push_flast_set R, R>( &mut self, @@ -114,6 +211,27 @@ pub trait FlastSetContext: FirstSetContext { ) -> R; } +impl FlastSetContext for Vec<(bool, FirstSet, FlastSet)> { + type PushFlastSet = Self; + + fn get_flast_set(&self, index: usize) -> Option<&FlastSet> { + self.get(self.len() - index - 1).map(|(_, _, flast_set)| flast_set) + } + + fn push_flast_set R, R>( + &mut self, + nullable: bool, + first_set: FirstSet, + flast_set: FlastSet, + f: F, + ) -> R { + self.push((nullable, first_set, flast_set)); + let res = f(self); + self.pop(); + res + } +} + pub trait Type { type Err: Display; -- cgit v1.2.3