diff options
Diffstat (limited to 'src/parsers/semantic.rs')
-rw-r--r-- | src/parsers/semantic.rs | 352 |
1 files changed, 0 insertions, 352 deletions
diff --git a/src/parsers/semantic.rs b/src/parsers/semantic.rs deleted file mode 100644 index 00cfc80..0000000 --- a/src/parsers/semantic.rs +++ /dev/null @@ -1,352 +0,0 @@ -use crate::*; -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: &SyntacticToken) -> bool { - match token.variant { $variant => true, _ => false, } - } } }; } -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 struct SemanticParser { - tokens: Tokens, - macro_definitions: IndexMap<String, MacroDefinition>, - label_definitions: IndexMap<String, LabelDefinition>, - body: Vec<SemanticToken>, -} - -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), - macro_definitions: IndexMap::new(), - label_definitions, - body: Vec::new(), - } - } - - pub fn parse(mut self) -> SemanticProgram { - while let Some(syn) = self.tokens.pop() { - match syn.variant { - SynVar::MacroDefinition(name) => { - let Ok(definition_tokens) = self.tokens.pull_until(is_terminator) else { - let variant = SemanticParseErrorVariant::UnterminatedMacroDefinition(name); - let error = SemanticParseError { source: syn.source, variant }; - self.body.push(SemanticToken::Error(error)); - break; - }; - 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::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 invocation = InvocationParser::new(name, syn.source, &mut self.tokens).parse(); - self.body.push(SemanticToken::Invocation(invocation)); - } - SynVar::PackedBinaryLiteral(pbl) => { - self.body.push(SemanticToken::Word(pbl)); - } - _ => { - let variant = SemanticParseErrorVariant::InvalidToken; - let error = SemanticParseError { source: syn.source, variant }; - self.body.push(SemanticToken::Error(error)); - } - } - } - - SemanticProgram { - macro_definitions: self.macro_definitions, - label_definitions: self.label_definitions, - body: self.body, - } - } -} - - -pub struct MacroDefinitionParser { - source: SourceSpan, - tokens: Tokens, - arguments: Vec<ArgumentDefinition>, - errors: Vec<SemanticParseError>, -} - -impl MacroDefinitionParser { - pub fn new(source: SourceSpan, tokens: Tokens) -> Self { - Self { - tokens, - source, - arguments: Vec::new(), - errors: Vec::new(), - } - } - - pub fn parse(mut self) -> MacroDefinition { - while let Some(definition) = self.parse_argument_definition() { - self.arguments.push(definition) - } - MacroDefinition { - value: self.parse_body(), - source: self.source, - arguments: self.arguments, - errors: self.errors, - } - } - - fn parse_argument_definition(&mut self) -> Option<ArgumentDefinition> { - // Only continue if the first token is a separator. - self.tokens.pop_if(is_separator)?; - - // Pop argument tokens. - let is_block = match self.tokens.pop_if(is_block_open) { - Some(_) => true, - None => false, - }; - let token = self.tokens.pop(); - if is_block { - self.tokens.pop_if(is_block_close); - } - // Parse argument token. - let token = token?; - let source = token.source; - if let SynVar::Symbol(name) = token.variant { - let variant = match is_block { - true => ArgumentVariant::Block, - false => ArgumentVariant::Integer, - }; - Some(ArgumentDefinition { name, source, variant }) - } else { - let variant = SemanticParseErrorVariant::InvalidToken; - self.errors.push(SemanticParseError { source, variant}); - None - } - } - - 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::IntegerLiteral(value) => { - let integer = TrackedInteger { source: token.source, value }; - return Value::Integer(Integer::Literal(integer)); - } - SynVar::Expression(expr) => { - return Value::Integer(Integer::Expression(expr)); - } - _ => (), - } - self.tokens.unpop(token); - } - // 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); - } -} - - -/// Parse an entire block, excluding delimiters. -pub struct BlockParser { - tokens: Tokens, - semantic_tokens: Vec<SemanticToken>, -} - -impl BlockParser { - pub fn new(tokens: Tokens) -> Self { - Self { tokens, semantic_tokens: Vec::new() } - } - - 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 invocation = InvocationParser::new(name, source, &mut self.tokens).parse(); - self.semantic_tokens.push(SemanticToken::Invocation(invocation)); - } - SynVar::PackedBinaryLiteral(pbl) => { - 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 = SemanticParseErrorVariant::InvalidToken; - let error = SemanticParseError { source, variant }; - self.semantic_tokens.push(SemanticToken::Error(error)); - } - } - } - return self.semantic_tokens; - } -} - - -struct InvocationParser<'a> { - name: String, - source: SourceSpan, - tokens: &'a mut Tokens, - arguments: Vec<ArgumentInvocation>, - errors: Vec<SemanticParseError>, -} - -impl<'a> InvocationParser<'a> { - 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 { - while let Some(argument) = self.parse_invocation_argument() { - self.arguments.push(argument); - } - Invocation { - name: self.name, - source: self.source, - arguments: self.arguments, - errors: self.errors, - } - } - - 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: &SyntacticToken| { - match token.variant { - SyntacticTokenVariant::BlockOpen => { - depth += 1; false } - 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(ArgumentInvocation { source, value: Value::Block(block) }) - } else { - let variant = SemanticParseErrorVariant::UnterminatedBlock; - self.errors.push(SemanticParseError { source, variant }); - None - } - } else { - let token = self.tokens.pop()?; - let source = token.source; - match token.variant { - SynVar::Symbol(name) => { - 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::IntegerLiteral(value) => { - let integer = TrackedInteger { source: source.clone(), value }; - let value = Value::Integer(Integer::Literal(integer)); - Some(ArgumentInvocation { source, value }) - } - SynVar::String(string) => { - let value = Value::Integer(Integer::String(string)); - Some(ArgumentInvocation { source, value }) - } - SynVar::Expression(expr) => { - let value = Value::Integer(Integer::Expression(expr)); - Some(ArgumentInvocation { source, value }) - } - _ => { - 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() - } -} - |