summaryrefslogtreecommitdiff
path: root/src/parsers/semantic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parsers/semantic.rs')
-rw-r--r--src/parsers/semantic.rs352
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()
- }
-}
-