Skip to content
Snippets Groups Projects
Commit 999469ba authored by Federico Lolli's avatar Federico Lolli
Browse files

Semantic analysis complete, first parse ready

parent ba98dbee
Branches
No related tags found
No related merge requests found
use syntax::CachedLexer;
mod semantics;
mod syntax;
mod tokens;
use syntax::CachedLexer;
use crate::semantics::Executor;
// use logos::Logos;
// use self::tokens::Token;
......@@ -15,6 +18,8 @@ fn main() {
// println!("{:?}", token.0.as_ref().unwrap());
// }
let p = CachedLexer::new(&input).parse_program();
dbg!(p);
let p = CachedLexer::new(&input).parse_program().unwrap();
dbg!(&p);
let traj = Executor::new(p).run().unwrap();
dbg!(traj);
}
use crate::syntax::{
Blocks, GeneratorKind, GroupExpr, Operation, Operator, Program, SettingKind, TimeAnchorBlock,
TimeExpr,
};
pub struct Executor {
initial_coordinates: (f64, f64, f64),
last_timeref: Option<f64>,
generator: Option<PositionParametricGenerator>,
trajectory: Trajectory,
execution: ProgramExecution,
}
impl Executor {
pub fn new(program: Program) -> Self {
Self {
initial_coordinates: (0.0, 0.0, 0.0),
last_timeref: None,
generator: None,
trajectory: Trajectory { points: vec![] },
execution: ProgramExecution::from(program),
}
}
/// Validate the program execution order
fn validate(&self) -> bool {
let execution = self.execution.clone();
let mut in_settings = true;
let mut started_first_time_ref = false;
let mut waiting_generator = false;
for block in execution {
match block {
Blocks::Setting(_) => {
// check that settings are at the beginning
if !in_settings {
return false;
}
}
Blocks::TimeDefinition(_) => {
// not allowed if waiting for generator
if waiting_generator {
return false;
}
// allow generator after the first time reference
if !started_first_time_ref {
started_first_time_ref = true;
}
// disable settings after the first time reference
in_settings = false;
// wait for generator
waiting_generator = true;
}
Blocks::Generator(_) => {
// check that generator is after the first time reference
if !waiting_generator {
return false;
}
// disable generator after it's been used
waiting_generator = false;
}
}
}
true
}
pub fn run(mut self) -> Result<Trajectory, String> {
if !self.validate() {
return Err("Invalid program".to_string());
}
for block in self.execution {
match block {
Blocks::Setting(setting) => match setting.kind {
SettingKind::GPS => {
self.initial_coordinates = (
**setting.get("latitude").unwrap(),
**setting.get("longitude").unwrap(),
**setting.get("altitude").unwrap(),
);
}
},
Blocks::Generator(generator) => match generator.kind {
GeneratorKind::PositionParametric => {
let x = generator.get("x").unwrap();
let y = generator.get("y").unwrap();
let z = generator.get("z").unwrap();
self.generator = Some(PositionParametricGenerator::new(
x.clone(),
y.clone(),
z.clone(),
));
}
},
Blocks::TimeDefinition(TimeAnchorBlock { timeref, freq, .. }) => {
match self.last_timeref {
Some(init_t) => {
let generator = self.generator.as_ref().unwrap();
// get the frequency
let freq = freq.ok_or("Missing frequency.")?;
// set last position as the initial position
let starting_pos = if self.trajectory.points.is_empty() {
let (ix, iy, iz) = self.initial_coordinates;
Point::new(ix, iy, iz, init_t)
} else {
self.trajectory.points.last().unwrap().clone()
};
let end_t = *timeref;
if end_t > init_t {
let mut prev_t = init_t;
let mut t = prev_t;
while t < end_t {
let (x, y, z) = generator.generate(t - init_t);
let mut p = Point::new(x, y, z, t);
p.absolute_from(&starting_pos);
self.trajectory.push(p);
// update time reference
prev_t = t;
t = prev_t + freq
}
self.last_timeref = Some(t);
} else {
return Err("Invalid time reference".to_string());
}
}
None => {
self.last_timeref = Some(*timeref);
}
}
}
}
}
Ok(self.trajectory)
}
}
#[derive(Debug, Clone)]
pub struct Trajectory {
points: Vec<Point>,
}
impl Trajectory {
fn push(&mut self, point: Point) {
self.points.push(point);
}
}
#[derive(Debug, Clone)]
struct Point {
x: f64,
y: f64,
z: f64,
time: f64,
}
impl Point {
fn new(x: f64, y: f64, z: f64, time: f64) -> Self {
Self { x, y, z, time }
}
fn absolute_from(&mut self, other: &Point) {
self.x += other.x;
self.y += other.y;
self.z += other.z;
}
}
#[derive(Debug, Clone)]
struct ProgramExecution {
blocks: Vec<Blocks>,
}
impl From<Program> for ProgramExecution {
fn from(program: Program) -> Self {
let Program(mut blocks) = program;
blocks.reverse();
Self { blocks }
}
}
impl Iterator for ProgramExecution {
type Item = Blocks;
fn next(&mut self) -> Option<Self::Item> {
self.blocks.pop()
}
}
impl TimeExpr {
fn eval(&self, t: f64) -> f64 {
match self {
TimeExpr::Group(group) => group.eval(t),
TimeExpr::Num(num) => num.value,
TimeExpr::Op(op) => op.eval(t),
TimeExpr::TimeVar(_) => t,
}
}
}
impl Operation {
fn eval(&self, t: f64) -> f64 {
let (l, r) = (self.lhs.eval(t), self.rhs.eval(t));
match self.op {
Operator::Add => l + r,
Operator::Sub => l - r,
Operator::Mul => l * r,
Operator::Div => l / r,
Operator::Pow => l.powf(r),
}
}
}
impl GroupExpr {
fn eval(&self, t: f64) -> f64 {
self.value.eval(t)
}
}
struct PositionParametricGenerator {
x: TimeExpr,
y: TimeExpr,
z: TimeExpr,
}
impl PositionParametricGenerator {
fn new(x: TimeExpr, y: TimeExpr, z: TimeExpr) -> Self {
Self { x, y, z }
}
fn generate(&self, t: f64) -> (f64, f64, f64) {
(self.x.eval(t), self.y.eval(t), self.z.eval(t))
}
}
......@@ -44,6 +44,15 @@ pub struct GeneratorBlock {
pub parameters: Vec<ExprParameter>,
}
impl GeneratorBlock {
pub fn get(&self, name: &str) -> Option<&TimeExpr> {
self.parameters
.iter()
.find(|p| p.name == name)
.map(|p| &p.value)
}
}
#[derive(Debug, Clone)]
pub struct NumberParameter {
span: Range<usize>,
......@@ -55,7 +64,7 @@ pub struct NumberParameter {
pub struct ExprParameter {
span: Range<usize>,
name: String,
value: TimeExpr,
pub value: TimeExpr,
}
#[derive(Debug, Clone)]
......@@ -80,15 +89,15 @@ impl TimeExpr {
#[derive(Debug, Clone)]
pub struct GroupExpr {
span: Range<usize>,
value: Box<TimeExpr>,
pub value: Box<TimeExpr>,
}
#[derive(Debug, Clone)]
pub struct Operation {
span: Range<usize>,
op: Operator,
lhs: Box<TimeExpr>,
rhs: Box<TimeExpr>,
pub op: Operator,
pub lhs: Box<TimeExpr>,
pub rhs: Box<TimeExpr>,
}
#[derive(Debug, Clone)]
......@@ -103,7 +112,7 @@ pub enum Operator {
#[derive(Debug, Clone)]
pub struct Number {
span: Range<usize>,
value: f64,
pub value: f64,
}
impl Deref for Number {
......
= [GPS]
\ x: 0
\ y: 0
\ z: 0
\ latitude: 0
\ longitude: 0
\ altitude: 0
|
@ T+0
|
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment