diff options
author | Ben Bridle <bridle.benjamin@gmail.com> | 2025-02-14 09:36:52 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-03-18 12:23:27 +1300 |
commit | 7d4dd52b8cfc865ae1b975ca3b6a3e72a812ebb9 (patch) | |
tree | 14ca9fa0ddcdd8c5155ddeaac241cd4f55486b6e /src/stages/compiler.rs | |
parent | f69a8f8c312ded212446082682bcabba8e3a9c9f (diff) | |
download | bedrock-asm-7d4dd52b8cfc865ae1b975ca3b6a3e72a812ebb9.zip |
Rewrite library
Diffstat (limited to 'src/stages/compiler.rs')
-rw-r--r-- | src/stages/compiler.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/stages/compiler.rs b/src/stages/compiler.rs new file mode 100644 index 0000000..7dad5e4 --- /dev/null +++ b/src/stages/compiler.rs @@ -0,0 +1,80 @@ +use crate::*; +use assembler::SymbolRole::*; +use assembler::DefinitionType::*; + + +pub fn new_compiler() -> Compiler { + Compiler::new(parse_symbols, push_code) +} + + +/// Parse all symbols from a source code string. +pub fn parse_symbols(source_code: &str, path: Option<&Path>) -> Option<Vec<Symbol>> { + let syntactic = match parse_syntactic(source_code, path) { + Ok(syntactic) => syntactic, + Err(_errors) => return None, + }; + Some(SymbolParser::new().parse(&syntactic)) +} + +/// Push source code to a source compilation string. +pub fn push_code(compilation: &mut String, source_file: &SourceFile) { + // Skip blank files. + let source_code = &source_file.source_code; + if source_code.chars().all(|c| c.is_whitespace()) { return; } + // Ensure that the previous section is followed by two newline characters. + if !compilation.is_empty() { + if !compilation.ends_with('\n') { compilation.push('\n'); } + if !compilation.ends_with("\n\n") { compilation.push('\n'); } + } + // Push a path comment and the source code. + let path_str = source_file.path.as_os_str().to_string_lossy(); + let path_comment = format!("(: {path_str} )\n"); + compilation.push_str(&path_comment); + compilation.push_str(&source_code); +} + + +// Extract symbol definitions from a list of semantic tokens. +pub struct SymbolParser { + pub symbols: Vec<Symbol>, +} + +impl SymbolParser { + pub fn new() -> Self { + Self { + symbols: Vec::new(), + } + } + + fn record_symbol(&mut self, name: &str, source: &SourceSpan, role: SymbolRole) { + let name = name.to_string(); + let namespace = Vec::new(); + let source = source.to_owned(); + self.symbols.push(Symbol { name, namespace, source, role }); + } + + pub fn parse(mut self, semantic: &[Tracked<SyntacticToken>]) -> Vec<Symbol> { + for token in semantic { + match &token.value { + SyntacticToken::MacroDefinition(definition) => { + self.record_symbol( + &definition.name, + &definition.name.source, + Definition(MustPrecedeReference), + ); + for token in &definition.body { + if let SyntacticToken::Invocation(name) = &token.value { + self.record_symbol(&name, &token.source, Reference); + } + } + } + SyntacticToken::LabelDefinition(name) => { + self.record_symbol(&name, &token.source, Definition(CanFollowReference)); + } + _ => (), + } + } + return self.symbols; + } +} |