Assignments, numbers, funcalls

This commit is contained in:
Dane Johnson 2022-01-31 14:03:47 -06:00
parent ddc4dcd97c
commit 85d13bc26e
5 changed files with 171 additions and 0 deletions

1
rust/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/*

61
rust/Cargo.lock generated Normal file
View File

@ -0,0 +1,61 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "deelang"
version = "0.1.0"
dependencies = [
"peg",
]
[[package]]
name = "peg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af728fe826811af3b38c37e93de6d104485953ea373d656eebae53d6987fcd2c"
dependencies = [
"peg-macros",
"peg-runtime",
]
[[package]]
name = "peg-macros"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4536be147b770b824895cbad934fccce8e49f14b4c4946eaa46a6e4a12fcdc16"
dependencies = [
"peg-runtime",
"proc-macro2",
"quote",
]
[[package]]
name = "peg-runtime"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9b0efd3ba03c3a409d44d60425f279ec442bcf0b9e63ff4e410da31c8b0f69f"
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"

9
rust/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "deelang"
version = "0.1.0"
edition = "2021"
[dependencies]
peg = "0.8.0"

5
rust/src/main.rs Normal file
View File

@ -0,0 +1,5 @@
mod parser;
fn main() {
println!("Hello, world!");
}

95
rust/src/parser.rs Normal file
View File

@ -0,0 +1,95 @@
#[derive(Debug,PartialEq)]
pub enum Statement {
Assignment(String, Expression),
Funcall(Funcall),
}
#[derive(Debug,PartialEq)]
pub enum Expression {
Id(String),
Num(f64),
Funcall(Funcall)
}
#[derive(Debug,PartialEq)]
pub struct Funcall {
id: String,
args: Vec<Expression>,
}
peg::parser! {
grammar deelang_parser() for str {
pub rule program() -> Vec<Statement>
= __* s:statement()* eof() { s }
pub rule statement() -> Statement
= i:id() "<-" _ e:expr() __* { Statement::Assignment(i, e) } /
f:funcall() __* { Statement::Funcall(f)}
rule expr() -> Expression
= f:funcall() _ { Expression::Funcall(f) } /
i:id() _ { Expression::Id(i) } /
n:num() _ { Expression::Num(n) }
rule id() -> String
= i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() }
rule num() -> f64
= n:$(digit()+ "."? digit()* / "." digit()+) _ { n.to_string().parse().unwrap() }
rule funcall() -> Funcall
= i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Funcall{id: i, args: e} }
rule letter()
= ['A'..='Z'] / ['a'..='z']
rule digit()
= ['0'..='9']
rule _ // Non-meaningful whitespace
= ['\t'|' ']*
rule __ // Blank lines and lines containing only comments
= comment() &eof() / comment() newline() / newline()
rule comment()
= "#" (!newline() [_])* &(newline() / eof())
rule newline()
= "\r\n" / "\r" / "\n"
rule eof()
= ![_]
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_comments() {
let expected = vec![];
let prgm = "## This is a comment";
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
}
#[test]
fn test_funcall() {
let expected = vec![
Statement::Funcall(Funcall{id: "pear".to_string(), args: vec![]}),
Statement::Funcall(Funcall {
id: "pear".to_string(),
args: vec![Expression::Id("x".to_string()), Expression::Id("y".to_string())],
})
];
let prgm = r"pear()
pear(x, y)";
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
}
#[test]
fn test_assignment() {
let prgm = r"apple <- 1
apple <- pear(x, y)";
let expected = vec![
Statement::Assignment("apple".to_string(),
Expression::Num(1.0)),
Statement::Assignment("apple".to_string(),
Expression::Funcall(Funcall {
id: "pear".to_string(),
args: vec![
Expression::Id("x".to_string()),
Expression::Id("y".to_string())
]}))];
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
}
}