summaryrefslogtreecommitdiff
path: root/src/stages/compiler.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2025-02-14 09:36:52 +1300
committerBen Bridle <ben@derelict.engineering>2025-03-18 12:23:27 +1300
commit7d4dd52b8cfc865ae1b975ca3b6a3e72a812ebb9 (patch)
tree14ca9fa0ddcdd8c5155ddeaac241cd4f55486b6e /src/stages/compiler.rs
parentf69a8f8c312ded212446082682bcabba8e3a9c9f (diff)
downloadbedrock-asm-7d4dd52b8cfc865ae1b975ca3b6a3e72a812ebb9.zip
Rewrite library
Diffstat (limited to 'src/stages/compiler.rs')
-rw-r--r--src/stages/compiler.rs80
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;
+ }
+}