diff --git a/on-host/arpist-traject/src/syntax.rs b/on-host/arpist-traject/src/syntax.rs index 8f6a1cf2f2d9d2b16d9d99509bebf6debc64036e..a48bf781ef365841f67feb3735afb782d1e8b633 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 a6a8309c0f6887bcb9123b8b483831bd0ab710c6..2ef12618cecbb15edad0eeedfbfa0edca7da9226 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 927535043f06019d02bc1c3da1f372f09b2c6282..bc8e39d164c6130424443eed2be9a641448b4ccb 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 a1532724cf30d21d1f4b6d9eb496be5d7b66dc0b..d2e9fa60490bf2bf72a1975ad9ca7848a4a453a0 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