diff --git a/on-host/arpist-traject/Cargo.toml b/on-host/arpist-traject/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..377145392d63ffafdaae3cde44800dabdb8efb27
--- /dev/null
+++ b/on-host/arpist-traject/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "arpist-traject"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+logos = "0.14.0"
diff --git a/on-host/arpist-traject/grammar.txt b/on-host/arpist-traject/grammar.txt
new file mode 100644
index 0000000000000000000000000000000000000000..99bd024116d9c89612f8f1bf914d03ea376eb79c
--- /dev/null
+++ b/on-host/arpist-traject/grammar.txt
@@ -0,0 +1,26 @@
+TRAJECTORY <- TIME_DEF (FILLER* GENERATOR PARAMETER+ FILLER* TIME_DEF)+
+
+TIME_DEF <- "@" SPACE+ "T" POS_NUM SPACE* NEWLINE
+GENERATOR <- "=" SPACE+ "[" GENERATOR_KIND "]" SPACE* NEWLINE
+PARAMETER <- "#" SPACE+ COORDINATE SPACE* ":" SPACE* EQUATION SPACE* NEWLINE
+FILLER <- "|" SPACE* NEWLINE
+
+GENERATOR_KIND <- "parametric"
+COORDINATE <- [xyz]
+
+EXPR <- SUM
+SUM <- PRODUCT (SPACE* (SUM_OP / SUB_OP) SPACE* PRODUCT)*
+PRODUCT <- POWER (SPACE* (PRODUCT_OP / DIV_OP) SPACE* POWER)*
+POWER <- VALUE (SPACE* POWER_OP SPACE* VALUE)*
+VALUE <- NUM / "(" EXPR ")"
+NUM <- POS_NUM / NEG_NUM
+NEG_NUM <- "-" NUM
+POS_NUM <- ("+")? [0-9]+ ("." [0-9]+)?
+
+SUM_OP <- "+"
+SUB_OP <- "-"
+PRODUCT_OP <- "*"
+POWER_OP <- "^"
+DIV_OP <- "/"
+NEWLINE <- [\n\r]
+SPACE <- [ \t]
diff --git a/on-host/arpist-traject/src/main.rs b/on-host/arpist-traject/src/main.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9818c45a37a8292b6435c1fe0748bacd0415d5e7
--- /dev/null
+++ b/on-host/arpist-traject/src/main.rs
@@ -0,0 +1,15 @@
+mod tokens;
+
+use logos::Logos;
+
+use self::tokens::Token;
+
+fn main() {
+    let input = std::fs::read_to_string("test.txt").unwrap();
+    let lex = Token::lexer(&input);
+    let tokens = lex.spanned().collect::<Vec<_>>();
+    for token in &tokens {
+        println!("{:?}", token.0.as_ref().unwrap());
+    }
+    // dbg!(tokens);
+}
diff --git a/on-host/arpist-traject/src/tokens.rs b/on-host/arpist-traject/src/tokens.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2654f3103c00acfdccd4980c56f119cbeef39664
--- /dev/null
+++ b/on-host/arpist-traject/src/tokens.rs
@@ -0,0 +1,73 @@
+use logos::Logos;
+
+#[derive(Debug, PartialEq, Logos)]
+pub enum Token {
+    #[regex("[ \t]+")]
+    Spaces,
+
+    #[regex("[\n\r]")]
+    Newline,
+
+    #[regex("[0-9]+(\\.[0-9]+)?", |lex| lex.slice().parse().ok())]
+    Num(f64),
+
+    #[token("+")]
+    OpAdd,
+
+    #[token("-")]
+    OpSub,
+
+    #[token("*")]
+    OpMul,
+
+    #[token("/")]
+    OpDiv,
+
+    #[token("^")]
+    OpPow,
+
+    #[token("(")]
+    LParen,
+
+    #[token(")")]
+    RParen,
+
+    #[token("[")]
+    LBracket,
+
+    #[token("]")]
+    RBracket,
+
+    #[token("t")]
+    Time,
+
+    #[token("T")]
+    TimeRef,
+
+    #[token("x")]
+    PositionX,
+
+    #[token("y")]
+    PositionY,
+
+    #[token("z")]
+    PositionZ,
+
+    #[token(":")]
+    Colon,
+
+    #[token("parametric")]
+    ParametricGenerator,
+
+    #[token("|")]
+    FillerLine,
+
+    #[token("@")]
+    AtTimeLine,
+
+    #[token("=")]
+    GeneratorLine,
+
+    #[token("#")]
+    ParameterLine,
+}
diff --git a/on-host/arpist-traject/test.txt b/on-host/arpist-traject/test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e95c6ef9b51c733662203446879833cac9e5703a
--- /dev/null
+++ b/on-host/arpist-traject/test.txt
@@ -0,0 +1,8 @@
+@ T+0
+|
+= [parametric]
+# x: 0.03*t
+# y: 0.02*t
+# z: 3*t^2
+|
+@ T+10