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.rs339
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()
+ }
+}
+