Changeset - 61bb6b04e20b
[Not reviewed]
0 4 1
MH - 4 years ago 2021-12-10 00:04:00
contact@maxhenger.nl
Refactoring ParserType parser in anticipation of tuples
5 files changed with 141 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/protocol/ast.rs
Show inline comments
 
@@ -372,6 +372,10 @@ pub enum ParserTypeVariant {
 
    Array,
 
    Input,
 
    Output,
 
    // Tuple: expecting any number of elements. Note that the parser type can
 
    // have one-valued tuples, these will be filtered out later during type
 
    // checking.
 
    Tuple(u32), // u32 = number of subsequent types
 
    // User-defined types
 
    PolymorphicArgument(DefinitionId, u32), // u32 = index into polymorphic variables
 
    Definition(DefinitionId, u32), // u32 = number of subsequent types in the type tree.
 
@@ -391,7 +395,7 @@ impl ParserTypeVariant {
 
                0,
 
            ArrayLike | InputOrOutput | Array | Input | Output =>
 
                1,
 
            Definition(_, num) => *num as usize,
 
            Definition(_, num) | Tuple(num) => *num as usize,
 
        }
 
    }
 
}
src/protocol/parser/mod.rs
Show inline comments
 
@@ -6,6 +6,7 @@ pub(crate) mod pass_tokenizer;
 
pub(crate) mod pass_symbols;
 
pub(crate) mod pass_imports;
 
pub(crate) mod pass_definitions;
 
pub(crate) mod pass_definitions_types;
 
pub(crate) mod pass_validation_linking;
 
pub(crate) mod pass_typing;
 
mod visitor;
src/protocol/parser/pass_definitions.rs
Show inline comments
 
@@ -460,8 +460,8 @@ impl PassDefinitions {
 
                self.consume_labeled_statement(module, iter, ctx, section)?;
 
            } else {
 
                // Two fallback possibilities: the first one is a memory
 
                // declaration, the other one is to parse it as a regular
 
                // expression. This is a bit ugly
 
                // declaration, the other one is to parse it as a normal
 
                // expression. This is a bit ugly.
 
                if let Some((memory_stmt_id, assignment_stmt_id)) = self.maybe_consume_memory_statement(module, iter, ctx)? {
 
                    section.push(memory_stmt_id.upcast().upcast());
 
                    section.push(assignment_stmt_id.upcast());
 
@@ -1709,7 +1709,7 @@ fn consume_parser_type(
 
        depth: i32,
 
    }
 

	
 
    // After parsing the array modified "[]", we need to insert an array type
 
    // After parsing the array modifier "[]", we need to insert an array type
 
    // before the most recently parsed type.
 
    fn insert_array_before(elements: &mut Vec<Entry>, depth: i32, span: InputSpan) {
 
        let index = elements.iter().rposition(|e| e.depth == depth).unwrap();
src/protocol/parser/pass_definitions_types.rs
Show inline comments
 
new file 100644
 
use crate::protocol::*;
 
use crate::protocol::parser::*;
 

	
 
struct Entry {
 
    element: ParserTypeElement,
 
    depth: i32,
 
}
 

	
 
#[derive(Copy, Clone)]
 
enum DepthKind {
 
    Tuple, // because we had a `(` token
 
    PolyArgs, // because we had a `<` token
 
}
 

	
 
struct DepthElement {
 
    kind: DepthKind,
 
    pos: InputPosition,
 
}
 

	
 
/// Temporarily keep the error around in unevaluated format because sometimes
 
/// when we evaluate a `ParserType`, we perform some backtracking if it fails.
 
enum ParserTypeError {
 
    ExpectedAType(InputPosition),
 
    MessageAt(InputPosition, &'static str),
 
    TwoMessageAt(InputPosition, &'static str, InputPosition, &'static str),
 
}
 

	
 
/// Parsers tokens into `ParserType` instances (yes, the name of the struct is
 
/// silly). Essentially a little state machine with its own temporary storage.
 
pub(crate) struct ParserTypeParser {
 
    entries: Vec<Entry>,
 
    depths: Vec<DepthElement>,
 
    first_pos: InputPosition,
 
    last_pos: InputPosition,
 
}
 

	
 
impl ParserTypeParser {
 
    pub(crate) fn consume_parser_type(
 
        &mut self,
 
        source: &InputSource, iter: &mut TokenIter,
 
        symbols: &SymbolTable, heap: &Heap, poly_vars: &[Identifier],
 
        cur_scope: SymbolScope, wrapping_definition: DefinitionId,
 
        allow_inference: bool, inside_angular_bracket: Option<InputPosition>,
 
    ) -> Result<ParserType, ParserTypeError> {
 
        // Make sure we start in an empty state
 
        debug_assert!(self.entries.is_empty());
 
        debug_assert!(self.depths.is_empty());
 

	
 
        // Setup processing
 
        if let Some(bracket_pos) = inside_angular_bracket {
 
            self.push_depth(DepthKind::PolyArgs, bracket_pos);
 
        }
 

	
 
        let first_element = match iter.next() {
 
            Some(TokenKind::Ident) => {
 

	
 
            },
 
            Some(TokenKind::OpenParen) => {
 
                let tuple_start_pos = iter.next_start_position();
 
                self.push_depth(DepthKind::Tuple, tuple_start_pos);
 
                self.entries.push(Entry{
 
                    element: ParserTypeElement{
 
                        element_span: InputSpan::from_positions(tuple_start_pos, tuple_start_pos),
 
                        variant: ParserTypeVariant::Tuple(0),
 
                    },
 
                    depth: self.cur_depth(),
 
                });
 
                iter.consume();
 
            },
 
            _ => return Err(ParserTypeError::MessageAt(iter.last_valid_pos(), "expected a type")),
 
        };
 

	
 
        // Convert the results from parsing into the `ParserType`
 
        let mut elements = Vec::with_capacity(self.entries.len());
 
        debug_assert!(!self.entries.is_empty());
 

	
 
        for entry in self.entries.drain(..) {
 
            elements.push(entry.element)
 
        }
 

	
 
        return Ok(ParserType{
 
            elements,
 
            full_span: InputSpan::from_positions(self.first_pos, self.last_pos),
 
        });
 
    }
 

	
 
    /// Consumes an identifier that should resolve to some kind of type. There
 
    /// may be trailing '::' tokens, commas, or polymorphic arguments.
 
    fn consume_parser_type_ident(
 
        &self, iter: &mut TokenIter, symbols: &SymbolTable, poly_vars: &[Identifier],
 
        allow_inference: bool,
 
    ) -> Result<ParserTypeElement, ParserTypeError> {
 

	
 
    }
 

	
 
    #[inline]
 
    fn push_depth(&mut self, kind: DepthKind, pos: InputPosition) {
 
        self.depths.push(DepthElement{ kind, pos });
 
    }
 

	
 
    #[inline]
 
    fn pop_depth(&mut self, kind: DepthKind, pos: InputPosition) -> Result<(), ParserTypeError> {
 
        if self.depths.is_empty() {
 
            // More closing parens than opening ones
 
            let message = match kind {
 
                DepthKind::Tuple => "unmatched ')'",
 
                DepthKind::PolyArgs => "unmatched '>'",
 
            };
 
            return Err(ParserTypeError::MessageAt(pos, message))
 
        }
 

	
 
        let last = *self.depths.last().unwrap();
 
        if last != kind {
 
            // Wrong kind of paren
 
            let (message_second) = match kind {
 
                DepthKind::Tuple => "unexpected closing"
 
            }
 
        }
 
    }
 

	
 
    #[inline]
 
    fn cur_depth(&self) -> i32 {
 
        return self.depths.len() as i32;
 
    }
 
}
 
\ No newline at end of file
src/protocol/parser/tokens.rs
Show inline comments
 
@@ -298,6 +298,13 @@ impl<'a> TokenIter<'a> {
 
        };
 
    }
 

	
 
    /// Assumes the token is not at the end and returns the starting position
 
    /// belonging to the token returned by `next`.
 
    pub(crate) fn next_start_position(&self) -> InputPosition {
 
        debug_assert!(self.cur < self.end);
 
        return self.tokens[self.cur].pos;
 
    }
 

	
 
    /// Returns the token range belonging to the token returned by `next`. This
 
    /// assumes that we're not at the end of the range we're iterating over.
 
    pub(crate) fn next_positions(&self) -> (InputPosition, InputPosition) {
0 comments (0 inline, 0 general)