From ba98dbeeac6cf5d57e2c301a12550882fa5dbc0e Mon Sep 17 00:00:00 2001 From: Federico Lolli <federico.lolli@skywarder.eu> Date: Sun, 17 Mar 2024 00:54:49 +0100 Subject: [PATCH] Added frequency sampling to syntax --- on-host/arpist-traject/src/syntax.rs | 56 +++++++++++++++++---- on-host/arpist-traject/src/syntax/parser.rs | 37 +++++++++++--- on-host/arpist-traject/src/tokens.rs | 3 ++ on-host/test.txt | 2 +- 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/on-host/arpist-traject/src/syntax.rs b/on-host/arpist-traject/src/syntax.rs index 8f6a1cf..a48bf78 100644 --- a/on-host/arpist-traject/src/syntax.rs +++ b/on-host/arpist-traject/src/syntax.rs @@ -1,38 +1,54 @@ -use std::ops::Range; +use std::ops::{Deref, Range}; mod parser; pub use parser::CachedLexer; #[derive(Debug, Clone)] -pub struct Program(Vec<Blocks>); +pub struct Program(pub Vec<Blocks>); #[derive(Debug, Clone)] pub enum Blocks { - TimeDefinition(TimeRef), + TimeDefinition(TimeAnchorBlock), Generator(GeneratorBlock), Setting(SettingBlock), } +#[derive(Debug, Clone)] +pub struct TimeAnchorBlock { + span: Range<usize>, + pub timeref: TimeRef, + pub freq: Option<f64>, +} + #[derive(Debug, Clone)] pub struct SettingBlock { span: Range<usize>, - name: Setting, - settings: Vec<NumberParameter>, + pub kind: SettingKind, + pub settings: Vec<NumberParameter>, +} + +impl SettingBlock { + pub fn get(&self, name: &str) -> Option<&Number> { + self.settings + .iter() + .find(|p| p.name == name) + .map(|p| &p.value) + } } #[derive(Debug, Clone)] pub struct GeneratorBlock { span: Range<usize>, - generator: Generator, - parameters: Vec<ExprParameter>, + pub kind: GeneratorKind, + pub parameters: Vec<ExprParameter>, } #[derive(Debug, Clone)] pub struct NumberParameter { span: Range<usize>, - name: String, - value: Number, + pub name: String, + pub value: Number, } #[derive(Debug, Clone)] @@ -90,6 +106,14 @@ pub struct Number { value: f64, } +impl Deref for Number { + type Target = f64; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + #[derive(Debug, Clone)] pub struct Generator { span: Range<usize>, @@ -118,6 +142,20 @@ pub struct TimeRef { offset: f64, } +#[derive(Debug, Clone)] +pub struct TimeStepFreq { + span: Range<usize>, + freq: f64, +} + +impl Deref for TimeRef { + type Target = f64; + + fn deref(&self) -> &Self::Target { + &self.offset + } +} + #[derive(Debug, Clone)] pub struct TimeVar { span: Range<usize>, diff --git a/on-host/arpist-traject/src/syntax/parser.rs b/on-host/arpist-traject/src/syntax/parser.rs index a6a8309..2ef1261 100644 --- a/on-host/arpist-traject/src/syntax/parser.rs +++ b/on-host/arpist-traject/src/syntax/parser.rs @@ -130,7 +130,7 @@ fn parse_program(mut view: LexerView<'_>) -> Option<Program> { blocks.push(Blocks::Setting(parse_setting_block(view.view())?)); } Token::AtTimeLine => { - blocks.push(Blocks::TimeDefinition(parse_timedef_block(view.view())?)); + blocks.push(Blocks::TimeDefinition(parse_timeanchor_block(view.view())?)); } Token::FillerLine => { consume_filler_lines(view.view()); @@ -142,16 +142,39 @@ fn parse_program(mut view: LexerView<'_>) -> Option<Program> { Some(Program(blocks)) } -fn parse_timedef_block(mut view: LexerView<'_>) -> Option<TimeRef> { +fn parse_timeanchor_block(mut view: LexerView<'_>) -> Option<TimeAnchorBlock> { let (Token::AtTimeLine, s) = view.next()? else { return None; }; let timeref = parse_time_ref(view.view())?; + let freq = if let (Token::TimeStepFreq(f), _) = view.peek()? { + view.next(); + // f is of format "1Hz" or "1kHz" + let scale = f.chars().skip_while(|c| c.is_numeric()).collect::<String>(); + let freq = f + .chars() + .take_while(|c| c.is_numeric()) + .collect::<String>() + .parse::<f64>() + .ok()?; + let freq = match scale.as_str() { + "Hz" => freq, + "kHz" => freq * 1e3, + "MHz" => freq * 1e6, + "GHz" => freq * 1e9, + "THz" => freq * 1e12, + _ => return None, + }; + Some(freq) + } else { + None + }; consume_new_line(view.view()); view.commit(); - Some(TimeRef { - span: s.start..timeref.span.end, - offset: timeref.offset, + Some(TimeAnchorBlock { + span: s.start..s.end, + timeref, + freq, }) } @@ -170,7 +193,7 @@ fn parse_generator_block(mut view: LexerView<'_>) -> Option<GeneratorBlock> { view.commit(); Some(GeneratorBlock { span: s.start..parameters.last().unwrap().span.end, - generator, + kind: generator.kind, parameters, }) } @@ -190,7 +213,7 @@ fn parse_setting_block(mut view: LexerView<'_>) -> Option<SettingBlock> { view.commit(); Some(SettingBlock { span: s.start..settings.last().unwrap().span.end, - name: setting, + kind: setting.name, settings, }) } diff --git a/on-host/arpist-traject/src/tokens.rs b/on-host/arpist-traject/src/tokens.rs index 9275350..bc8e39d 100644 --- a/on-host/arpist-traject/src/tokens.rs +++ b/on-host/arpist-traject/src/tokens.rs @@ -38,6 +38,9 @@ pub enum Token { #[regex("T[+-]?[0-9]+(\\.[0-9]+)?", |lex| lex.slice()[1..].parse::<f64>().ok())] TimeRef(f64), + #[regex(" ~ [0-9]+(\\.[0-9]+)?(Hz|kHz|MHz|GHz|THz)", |lex| lex.slice()[3..].to_string())] + TimeStepFreq(String), + #[regex("[a-z]+ *: *", |lex| lex.slice().trim().trim_end_matches(':').trim().to_string())] Parameter(String), diff --git a/on-host/test.txt b/on-host/test.txt index a153272..d2e9fa6 100644 --- a/on-host/test.txt +++ b/on-host/test.txt @@ -10,4 +10,4 @@ \ y : 0.02*t \ z : 3*t^2 | -@ T+10 +@ T+10 ~ 1Hz -- GitLab