diff options
Diffstat (limited to 'src/parsers/semantic.rs')
-rw-r--r-- | src/parsers/semantic.rs | 339 |
1 files changed, 176 insertions, 163 deletions
diff --git a/src/parsers/semantic.rs b/src/parsers/semantic.rs index 7ef4a4a..a58fb5f 100644 --- a/src/parsers/semantic.rs +++ b/src/parsers/semantic.rs @@ -1,136 +1,106 @@ use crate::*; - -use syntactic as syn; -use syn::TokenVariant as SynVar; -use semantic::*; +use SyntacticTokenVariant as SynVar; use std::collections::VecDeque; +use indexmap::IndexMap; + macro_rules! fn_is_syn_variant { ($name:ident, $variant:ty) => { paste::paste! { - fn [< is_ $name >](token: &syn::Token) -> bool { + fn [< is_ $name >](token: &SyntacticToken) -> bool { match token.variant { $variant => true, _ => false, } } } }; } -fn_is_syn_variant!(block_open, syn::TokenVariant::BlockOpen); -fn_is_syn_variant!(block_close, syn::TokenVariant::BlockClose); -fn_is_syn_variant!(separator, syn::TokenVariant::Separator); -fn_is_syn_variant!(terminator, syn::TokenVariant::MacroDefinitionTerminator); - - -pub struct Tokens { - tokens: VecDeque<syn::Token>, -} - -impl Tokens { - pub fn new<T: Into<VecDeque<syn::Token>>>(tokens: T) -> Self { - Self { tokens: tokens.into() } - } - - pub fn pop(&mut self) -> Option<syn::Token> { - self.tokens.pop_front() - } +fn_is_syn_variant!(block_open, SyntacticTokenVariant::BlockOpen); +fn_is_syn_variant!(block_close, SyntacticTokenVariant::BlockClose); +fn_is_syn_variant!(separator, SyntacticTokenVariant::Separator); +fn_is_syn_variant!(terminator, SyntacticTokenVariant::MacroDefinitionTerminator); - pub fn pop_if(&mut self, predicate: fn(&syn::Token) -> bool) -> Option<syn::Token> { - match predicate(self.tokens.front()?) { - true => self.tokens.pop_front(), - false => None, - } - } - pub fn unpop(&mut self, token: syn::Token) { - self.tokens.push_front(token); - } - - /// Pull tokens until the predicate returns true, otherwise return Err. - pub fn pull_until(&mut self, mut predicate: impl FnMut(&syn::Token) -> bool) -> Result<Self, ()> { - let mut output = VecDeque::new(); - while let Some(token) = self.tokens.pop_front() { - match predicate(&token) { - true => return Ok(Self::new(output)), - false => output.push_back(token), - }; - } - return Err(()); - } - - pub fn take(&mut self) -> Self { - Self { tokens: std::mem::take(&mut self.tokens) } - } - - pub fn len(&self) -> usize { - self.tokens.len() - } -} - - -pub struct ProgramParser { +pub struct SemanticParser { tokens: Tokens, - definitions: Vec<Definition>, - invocations: Vec<Invocation>, - errors: Vec<ParseError>, + macro_definitions: IndexMap<String, MacroDefinition>, + label_definitions: IndexMap<String, LabelDefinition>, + body: Vec<SemanticToken>, } -impl ProgramParser { - pub fn new(syntactic_tokens: Vec<syn::Token>) -> Self { +impl SemanticParser { + pub fn new(syntactic_tokens: Vec<SyntacticToken>) -> Self { + // Gather all labels ahead of time. + let mut label_definitions = IndexMap::new(); + for token in &syntactic_tokens { + if let SyntacticTokenVariant::LabelDefinition(name) = &token.variant { + let definition = LabelDefinition { + source: token.source.clone(), + name: name.clone(), + }; + let None = label_definitions.insert(name.to_string(), definition) else { + unreachable!("Duplicate definition for label {name:?}"); + }; + } + } Self { tokens: Tokens::new(syntactic_tokens), - definitions: Vec::new(), - invocations: Vec::new(), - errors: Vec::new(), + macro_definitions: IndexMap::new(), + label_definitions, + body: Vec::new(), } } - pub fn parse(mut self) -> Program { + pub fn parse(mut self) -> SemanticProgram { while let Some(syn) = self.tokens.pop() { match syn.variant { SynVar::MacroDefinition(name) => { - // Collect all tokens up to the next definition terminator. let Ok(definition_tokens) = self.tokens.pull_until(is_terminator) else { - let variant = ParseErrorVariant::UnterminatedMacroDefinition(name); - self.errors.push(ParseError { source: syn.source, variant}); + let variant = SemanticParseErrorVariant::UnterminatedMacroDefinition(name); + let error = SemanticParseError { source: syn.source, variant }; + self.body.push(SemanticToken::Error(error)); break; }; - // Parse macro definition arguments. - match DefinitionParser::new(name, syn.source, definition_tokens).parse() { - Ok(definition) => self.definitions.push(definition), - Err(errors) => self.errors.extend(errors), + let definition = MacroDefinitionParser::new(syn.source, definition_tokens).parse(); + let None = self.macro_definitions.insert(name.clone(), definition) else { + unreachable!("Duplicate definition for macro {name}"); }; } - SynVar::Comment(_) => (), + SynVar::LabelDefinition(name) => { + let label_definition = LabelDefinition { source: syn.source, name }; + self.body.push(SemanticToken::LabelDefinition(label_definition)); + } + SynVar::PinnedAddress(address) => { + let pinned_address = PinnedAddress { source: syn.source, address }; + self.body.push(SemanticToken::PinnedAddress(pinned_address)); + } SynVar::Symbol(name) => { - let parser = InvocationParser::new(name, &mut self.tokens); - self.invocations.push(parser.parse()); + let invocation = InvocationParser::new(name, syn.source, &mut self.tokens).parse(); + self.body.push(SemanticToken::Invocation(invocation)); } _ => { - let variant = ParseErrorVariant::InvalidToken; - self.errors.push(ParseError { source: syn.source, variant}); - break; + let variant = SemanticParseErrorVariant::InvalidToken; + let error = SemanticParseError { source: syn.source, variant }; + self.body.push(SemanticToken::Error(error)); } } } - Program { - definitions: self.definitions, - invocations: self.invocations, - errors: self.errors, + SemanticProgram { + macro_definitions: self.macro_definitions, + label_definitions: self.label_definitions, + body: self.body, } } } -pub struct DefinitionParser { - name: String, +pub struct MacroDefinitionParser { source: SourceSpan, tokens: Tokens, arguments: Vec<ArgumentDefinition>, - errors: Vec<ParseError>, + errors: Vec<SemanticParseError>, } -impl DefinitionParser { - pub fn new(name: String, source: SourceSpan, tokens: Tokens) -> Self { +impl MacroDefinitionParser { + pub fn new(source: SourceSpan, tokens: Tokens) -> Self { Self { - name, tokens, source, arguments: Vec::new(), @@ -138,20 +108,15 @@ impl DefinitionParser { } } - pub fn parse(mut self) -> Result<Definition, Vec<ParseError>> { + pub fn parse(mut self) -> MacroDefinition { while let Some(definition) = self.parse_argument_definition() { self.arguments.push(definition) } - if self.errors.is_empty() { - let variant = self.parse_body(); - Ok(Definition { - name: self.name, - source: self.source, - arguments: self.arguments, - variant, - }) - } else { - Err(self.errors) + MacroDefinition { + value: self.parse_body(), + source: self.source, + arguments: self.arguments, + errors: self.errors, } } @@ -172,47 +137,45 @@ impl DefinitionParser { let token = token?; let source = token.source; if let SynVar::Symbol(name) = token.variant { - let variant = ArgumentDefinitionVariant::Integer; + let variant = match is_block { + true => ArgumentVariant::Block, + false => ArgumentVariant::Integer, + }; Some(ArgumentDefinition { name, source, variant }) } else { - let name = self.name.clone(); - let variant = ParseErrorVariant::InvalidArgumentDefinition(name); - self.errors.push(ParseError { source, variant}); + let variant = SemanticParseErrorVariant::InvalidToken; + self.errors.push(SemanticParseError { source, variant}); None } } - fn parse_body(&mut self) -> DefinitionVariant { - // Attempt to parse an IntegerDefinition. + fn parse_body(&mut self) -> Value { + // Attempt to parse an Integer. if self.tokens.len() == 1 { let token = self.tokens.pop().unwrap(); match token.variant { - SynVar::DecimalLiteral(value) | SynVar::HexadecimalLiteral(value) => { - return DefinitionVariant::Integer(IntegerDefinition { - source: token.source, - variant: IntegerDefinitionVariant::Literal(value), - }); + SynVar::IntegerLiteral(value) => { + let integer = TrackedInteger { source: token.source, value }; + return Value::Integer(Integer::Literal(integer)); } - SynVar::ConstantExpression(expr) => { - return DefinitionVariant::Integer(IntegerDefinition { - source: token.source, - variant: IntegerDefinitionVariant::Constant(expr), - }); - } - SynVar::Symbol(name) => { - return DefinitionVariant::Reference(ReferenceDefinition { - source: token.source, - name, - }); + SynVar::Expression(expr) => { + return Value::Integer(Integer::Expression(expr)); } _ => (), } self.tokens.unpop(token); } - - // Parse the remaining tokens as a BlockDefinition. - let block = BlockParser::new(self.tokens.take()).parse(); - return DefinitionVariant::Block(block); + // Parse a Block. + let mut block = BlockParser::new(self.tokens.take()).parse(); + // If the block contains a single invocation, unwrap it. + if block.len() == 1 { + match block.pop() { + Some(SemanticToken::Invocation(invocation)) => return Value::Invocation(invocation), + Some(other) => block.push(other), + None => (), + }; + } + return Value::Block(block); } } @@ -220,52 +183,52 @@ impl DefinitionParser { /// Parse an entire block, excluding delimiters. pub struct BlockParser { tokens: Tokens, - block_tokens: Vec<BlockToken>, - errors: Vec<ParseError>, + semantic_tokens: Vec<SemanticToken>, } impl BlockParser { pub fn new(tokens: Tokens) -> Self { - Self { tokens, block_tokens: Vec::new(), errors: Vec::new() } + Self { tokens, semantic_tokens: Vec::new() } } - pub fn parse(mut self) -> BlockDefinition { + pub fn parse(mut self) -> Vec<SemanticToken> { while let Some(token) = self.tokens.pop() { let source = token.source; match token.variant { SynVar::Symbol(name) => { - let parser = InvocationParser::new(name, &mut self.tokens); - let invocation = parser.parse(); - let variant = BlockTokenVariant::Invocation(invocation); - let block_token = BlockToken { source, variant }; - self.block_tokens.push(block_token); + let invocation = InvocationParser::new(name, source, &mut self.tokens).parse(); + self.semantic_tokens.push(SemanticToken::Invocation(invocation)); } SynVar::PackedBinaryLiteral(pbl) => { - let variant = BlockTokenVariant::Word(pbl); - let block_token = BlockToken { source, variant }; - self.block_tokens.push(block_token); + self.semantic_tokens.push(SemanticToken::Word(pbl)); + } + SynVar::LabelDefinition(name) => { + let label_definition = LabelDefinition { source, name }; + self.semantic_tokens.push(SemanticToken::LabelDefinition(label_definition)); } _ => { - let variant = ParseErrorVariant::InvalidToken; - self.errors.push(ParseError { source, variant }) + let variant = SemanticParseErrorVariant::InvalidToken; + let error = SemanticParseError { source, variant }; + self.semantic_tokens.push(SemanticToken::Error(error)); } } } - BlockDefinition { tokens: self.block_tokens, errors: self.errors } + return self.semantic_tokens; } } struct InvocationParser<'a> { name: String, + source: SourceSpan, tokens: &'a mut Tokens, - arguments: Vec<DefinitionVariant>, - errors: Vec<ParseError>, + arguments: Vec<ArgumentInvocation>, + errors: Vec<SemanticParseError>, } impl<'a> InvocationParser<'a> { - pub fn new(name: String, tokens: &'a mut Tokens) -> Self { - Self { name, tokens, arguments: Vec::new(), errors: Vec::new() } + pub fn new(name: String, source: SourceSpan, tokens: &'a mut Tokens) -> Self { + Self { name, source, tokens, arguments: Vec::new(), errors: Vec::new() } } pub fn parse(mut self) -> Invocation { @@ -274,33 +237,34 @@ impl<'a> InvocationParser<'a> { } Invocation { name: self.name, + source: self.source, arguments: self.arguments, errors: self.errors, } } - fn parse_invocation_argument(&mut self) -> Option<DefinitionVariant> { + fn parse_invocation_argument(&mut self) -> Option<ArgumentInvocation> { // Only continue if the first token is a separator. self.tokens.pop_if(is_separator)?; if let Some(block_open) = self.tokens.pop_if(is_block_open) { let source = block_open.source; let mut depth = 1; - let is_matching_block_close = |token: &syntactic::Token| { + let is_matching_block_close = |token: &SyntacticToken| { match token.variant { - syntactic::TokenVariant::BlockOpen => { + SyntacticTokenVariant::BlockOpen => { depth += 1; false } - syntactic::TokenVariant::BlockClose => { + SyntacticTokenVariant::BlockClose => { depth -= 1; depth == 0 } _ => false, } }; if let Ok(block_tokens) = self.tokens.pull_until(is_matching_block_close) { let block = BlockParser::new(block_tokens).parse(); - Some(DefinitionVariant::Block(block)) + Some(ArgumentInvocation { source, value: Value::Block(block) }) } else { - let variant = ParseErrorVariant::UnterminatedBlockDefinition; - self.errors.push(ParseError { source, variant }); + let variant = SemanticParseErrorVariant::UnterminatedBlock; + self.errors.push(SemanticParseError { source, variant }); None } } else { @@ -308,25 +272,74 @@ impl<'a> InvocationParser<'a> { let source = token.source; match token.variant { SynVar::Symbol(name) => { - let reference = ReferenceDefinition { source, name }; - Some(DefinitionVariant::Reference(reference)) + let arguments = Vec::new(); + let errors = Vec::new(); + let invocation = Invocation { source: source.clone(), name, arguments, errors }; + let value = Value::Invocation(invocation); + Some(ArgumentInvocation { source, value }) } - SynVar::DecimalLiteral(value) | SynVar::HexadecimalLiteral(value) => { - let variant = IntegerDefinitionVariant::Literal(value); - let integer = IntegerDefinition { source, variant }; - Some(DefinitionVariant::Integer(integer)) + SynVar::IntegerLiteral(value) => { + let integer = TrackedInteger { source: source.clone(), value }; + let value = Value::Integer(Integer::Literal(integer)); + Some(ArgumentInvocation { source, value }) } - SynVar::ConstantExpression(expr) => { - let variant = IntegerDefinitionVariant::Constant(expr); - let integer = IntegerDefinition { source, variant }; - Some(DefinitionVariant::Integer(integer)) + SynVar::Expression(expr) => { + let value = Value::Integer(Integer::Expression(expr)); + Some(ArgumentInvocation { source, value }) } _ => { - let variant = ParseErrorVariant::InvalidToken; - self.errors.push(ParseError { source, variant }); + let variant = SemanticParseErrorVariant::InvalidToken; + self.errors.push(SemanticParseError { source, variant }); None } } } } } + + +pub struct Tokens { + tokens: VecDeque<SyntacticToken>, +} + +impl Tokens { + pub fn new<T: Into<VecDeque<SyntacticToken>>>(tokens: T) -> Self { + Self { tokens: tokens.into() } + } + + pub fn pop(&mut self) -> Option<SyntacticToken> { + self.tokens.pop_front() + } + + pub fn pop_if(&mut self, predicate: fn(&SyntacticToken) -> bool) -> Option<SyntacticToken> { + match predicate(self.tokens.front()?) { + true => self.tokens.pop_front(), + false => None, + } + } + + pub fn unpop(&mut self, token: SyntacticToken) { + self.tokens.push_front(token); + } + + /// Pull tokens until the predicate returns true, otherwise return Err. + pub fn pull_until(&mut self, mut predicate: impl FnMut(&SyntacticToken) -> bool) -> Result<Self, ()> { + let mut output = VecDeque::new(); + while let Some(token) = self.tokens.pop_front() { + match predicate(&token) { + true => return Ok(Self::new(output)), + false => output.push_back(token), + }; + } + return Err(()); + } + + pub fn take(&mut self) -> Self { + Self { tokens: std::mem::take(&mut self.tokens) } + } + + pub fn len(&self) -> usize { + self.tokens.len() + } +} + |