From bdb5650904c8ee52b70824983eea8d375f2dce32 Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Fri, 13 Jun 2025 21:55:21 -0700 Subject: [PATCH] Write initial code for parsing stats into chunks --- Cargo.lock | 42 +++++++++ Cargo.toml | 1 + src/labels/mod.rs | 2 +- src/labels/{labels.rs => parse.rs} | 93 +++++++++++++++++-- ...labels__parse__test__label_detection.snap} | 2 +- src/main.rs | 2 +- 6 files changed, 133 insertions(+), 9 deletions(-) rename src/labels/{labels.rs => parse.rs} (75%) rename src/labels/snapshots/{zasm__labels__labels__test__label_detection.snap => zasm__labels__parse__test__label_detection.snap} (92%) diff --git a/Cargo.lock b/Cargo.lock index 31df6bc..65ce7d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,12 +14,28 @@ version = "0.1.0" dependencies = [ "anyhow", "codepage-437", + "compact_str", "insta", "nom", "peg_macro", "pest", ] +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + [[package]] name = "codepage-437" version = "0.1.0" @@ -29,6 +45,20 @@ dependencies = [ "csv", ] +[[package]] +name = "compact_str" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "console" version = "0.15.11" @@ -201,6 +231,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + [[package]] name = "ryu" version = "1.0.20" @@ -233,6 +269,12 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "2.0.101" diff --git a/Cargo.toml b/Cargo.toml index 0628280..b4d78b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ peg_macro = { path = "./peg_macro"} insta = "1.39.0" nom = "7.1.3" pest = "2.7.15" +compact_str = "0.9.0" [dev-dependencies] insta = "1.39.0" diff --git a/src/labels/mod.rs b/src/labels/mod.rs index 988d57b..ea86848 100644 --- a/src/labels/mod.rs +++ b/src/labels/mod.rs @@ -1 +1 @@ -pub mod labels; +pub mod parse; diff --git a/src/labels/labels.rs b/src/labels/parse.rs similarity index 75% rename from src/labels/labels.rs rename to src/labels/parse.rs index 286d910..df47083 100644 --- a/src/labels/labels.rs +++ b/src/labels/parse.rs @@ -1,4 +1,85 @@ -use crate::{peg::ParseState, world::Stat}; +use std::ops::Range; + +use compact_str::CompactString; +use grammar::Tag; + +use crate::{ + peg::{Capture, ParseState}, + world::Stat, +}; + +type ParsedStat = Vec; +enum Chunk { + Verbatim(String), + Label(LabelName), + Reference(LabelName), +} + +struct LabelName { + namespace: CompactString, + name: CompactString, + local: Option, +} + +fn parse_stat_labels(stat: &Stat) -> ParsedStat { + let code = &stat.code; + let mut parser = ParseState::new(code); + assert!( + grammar::program(&mut parser), + "Couldn't parse code: {:?}", + code + ); + + // Split code along capture group boundaries + let mut result = vec![]; + let mut offset = 0; + + let mut push_label = |cap: Capture<_>| { + let Range { start, end } = cap.span(); + if offset < start { + result.push(Chunk::Verbatim(code[offset..start].into())) + } + let mut label = LabelName { + namespace: CompactString::with_capacity(0), + name: CompactString::with_capacity(0), + local: None, + }; + for child in cap.children() { + match child.kind() { + Tag::Namespace => { + label.namespace = child.text().into(); + } + Tag::Global => { + label.name = child.text().into(); + } + Tag::Local => label.local = Some(child.text().into()), + _ => unimplemented!(), + } + } + result.push(Chunk::Label(label)); + offset = end; + }; + + for cap in parser.captures() { + match cap.kind() { + Tag::Label => { + push_label(cap); + } + Tag::Reference => { + for child in cap.children() { + if child.kind() == Tag::Label { + push_label(child); + } + } + } + _ => {} + } + } + if offset < code.len() { + result.push(Chunk::Verbatim(code[offset..code.len()].into())); + } + result +} pub fn print_labels(b: &Stat) { let code = &b.code; @@ -10,7 +91,7 @@ pub fn print_labels(b: &Stat) { ); for capture in parser.captures() { - if capture.kind() == grammar::Tag::Label { + if capture.kind() == Tag::Label { println!("- {}", capture.text()); } } @@ -106,7 +187,7 @@ mod grammar { "n" / "s" / "e" / "w" / "i" // short forms ) eow; - // Labels (defined locations in the code) + // Labels // Examples: foo, namespace~foo, foo.local, .local, @ label = #Label:(namespace? (label_name / #Anon:"@")); namespace = #Namespace:label_word "~"; @@ -115,9 +196,9 @@ mod grammar { label_local = "." #Local:label_word; label_word = word_char+; // labels can start with 0-9 - // Messages (references to labels) + // References to labels // Examples: foo, all:namespace~bar.baz, @b, @f - message = #Message:(recipient? message_name); + message = #Reference:(recipient? #Label:message_name); recipient = #Recipient:word ":"; message_name = namespace? (label_name / #Anon:anon_message); anon_message = "@" ("b" / "f"); @@ -216,7 +297,7 @@ mod test { let before = &input[last_index..group.span().start]; let inner = match group.kind() { Tag::Label => format!("({})", group.text()), - Tag::Message => format!("[{}]", group.text()), + Tag::Reference => format!("[{}]", group.text()), _ => group.text().into(), }; result.push_str(before); diff --git a/src/labels/snapshots/zasm__labels__labels__test__label_detection.snap b/src/labels/snapshots/zasm__labels__parse__test__label_detection.snap similarity index 92% rename from src/labels/snapshots/zasm__labels__labels__test__label_detection.snap rename to src/labels/snapshots/zasm__labels__parse__test__label_detection.snap index 19767a3..adcc7a2 100644 --- a/src/labels/snapshots/zasm__labels__labels__test__label_detection.snap +++ b/src/labels/snapshots/zasm__labels__parse__test__label_detection.snap @@ -1,5 +1,5 @@ --- -source: src/labels/labels.rs +source: src/labels/parse.rs expression: result --- ' diff --git a/src/main.rs b/src/main.rs index 8cf3487..32dd62e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ mod preprocess; mod world; use anyhow::anyhow; -use labels::labels::print_labels; +use labels::parse::print_labels; use preprocess::eval::Context; use std::{env, error::Error, fs, path::PathBuf, process::exit}; use world::World;