From bc4c60712be15606e18352ddb7ecc359a556170f Mon Sep 17 00:00:00 2001 From: howardwu Date: Mon, 9 Mar 2020 20:55:41 -0700 Subject: [PATCH] Initial commit --- .gitignore | 2 + Cargo.lock | 180 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 +++ numbers.csv | 5 ++ simple.program | 1 + src/csv.pest | 3 + src/csv_main.rs | 44 ++++++++++++ src/language.pest | 100 ++++++++++++++++++++++++++ src/main.rs | 55 ++++++++++++++ 9 files changed, 399 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 numbers.csv create mode 100644 simple.program create mode 100644 src/csv.pest create mode 100644 src/csv_main.rs create mode 100644 src/language.pest create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..697aa0ddb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**.idea/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..547f243c72 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,180 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "language" +version = "0.1.0" +dependencies = [ + "pest", + "pest_derive", +] + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +dependencies = [ + "maplit", + "pest", + "sha-1", +] + +[[package]] +name = "proc-macro2" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "syn" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "ucd-trie" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..a537aa7cf8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "language" +version = "0.1.0" +authors = ["howardwu "] +edition = "2018" + +[dependencies] +pest = "2.0" +pest_derive = "2.0" diff --git a/numbers.csv b/numbers.csv new file mode 100644 index 0000000000..20a98c958e --- /dev/null +++ b/numbers.csv @@ -0,0 +1,5 @@ +65279,1179403647,1463895090 +3.1415927,2.7182817,1.618034 +-40,-273.15 +13,42 +65537 diff --git a/simple.program b/simple.program new file mode 100644 index 0000000000..fed79d05f4 --- /dev/null +++ b/simple.program @@ -0,0 +1 @@ +x = 5 diff --git a/src/csv.pest b/src/csv.pest new file mode 100644 index 0000000000..bb9af516ff --- /dev/null +++ b/src/csv.pest @@ -0,0 +1,3 @@ +field = { (ASCII_DIGIT | "." | "-")+ } +record = { field ~ ("," ~ field)* } +file = { SOI ~ (record ~ ("\r\n" | "\n"))* ~ EOI } diff --git a/src/csv_main.rs b/src/csv_main.rs new file mode 100644 index 0000000000..13cd808d0d --- /dev/null +++ b/src/csv_main.rs @@ -0,0 +1,44 @@ +extern crate pest; +#[macro_use] +extern crate pest_derive; + +use pest::Parser; +use std::fs; + +#[derive(Parser)] +#[grammar = "csv.pest"] +pub struct CSVParser; + +fn main() { + let unparsed_file = fs::read_to_string("numbers.csv").expect("cannot read file"); + + let file = CSVParser::parse(Rule::file, &unparsed_file) + .expect("unsuccessful parse") // unwrap the parse result + .next().unwrap(); // get and unwrap the `file` rule; never fails + + let mut field_sum: f64 = 0.0; + let mut record_count: u64 = 0; + + for record in file.into_inner() { + match record.as_rule() { + Rule::record => { + record_count += 1; + + for field in record.into_inner() { + field_sum += field.as_str().parse::().unwrap(); + } + } + Rule::EOI => (), + _ => unreachable!(), + } + } + + println!("Sum of fields: {}", field_sum); + println!("Number of records: {}", record_count); + + // let successful_parse = CSVParser::parse(Rule::field, "-273.15"); + // println!("{:?}", successful_parse); + // + // let unsuccessful_parse = CSVParser::parse(Rule::field, "this is not a number"); + // println!("{:?}", unsuccessful_parse); +} diff --git a/src/language.pest b/src/language.pest new file mode 100644 index 0000000000..82ec21e6d1 --- /dev/null +++ b/src/language.pest @@ -0,0 +1,100 @@ +// file = { SOI ~ NEWLINE* ~ import_section* ~ NEWLINE* ~ ty_struct_definition* ~ NEWLINE* ~ function_definition* ~ EOI } +// file = { SOI ~ NEWLINE* ~ import_section* ~ NEWLINE* ~ EOI } + +file = { SOI ~ NEWLINE* ~ statement* ~ NEWLINE* ~ EOI } + +COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) } +WHITESPACE = _{ " " | "\t" ~ NEWLINE } + + +/// Visibility + +visibility_public = { "public" } +visibility_private = { "private" } +visibility = { visibility_public | visibility_private } + +// /// Conditionals +// +// conditional_if = { "if" } +// conditional_else = { "else" } +// +// conditional_for = { "for" } +// +// conditional = { conditional_if | conditional_else | conditional_for } + +/// Values + +value_boolean = { "true" | "false" } + +value_field = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) } + +value = { value_boolean | value_field } + +/// Variables + +// TODO: Include "import" and "conditional" + +protected_name = { visibility | value_boolean | "return" } + +// keyword = @{ "as" | "in" | "return" | "export" | "false" | +// "def" | "in" | "return" | "struct" | "true" } + +variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } + +/// Unary Operations + +operation_not = { "!" } + +operation_increment = { "++" } +operation_decrement = { "--" } + +operation_unary = { + operation_not | + operation_increment | operation_decrement +} + +/// Binary Operations + +operation_and = { "&&" } +operation_or = { "||" } + +operation_eq = { "==" } +operation_geq = { ">=" } +operation_leq = { "<=" } +operation_neq = { "!=" } + +operation_add = { "+" } +operation_sub = { "-" } +operation_mul = { "*" } +operation_div = { "/" } +operation_pow = { "**" } + +// operation_assign = { "=" } +// operation_add_assign = { "+=" } +// operation_sub_assign = { "-=" } +// operation_mul_assign = { "*=" } +// operation_div_assign = { "/=" } + +operation_binary = { + operation_and | operation_or | + operation_eq | operation_geq | operation_leq | operation_neq | + operation_add | operation_sub | operation_mul | operation_div | operation_pow +} + +/// Expressions + +expression_unary = { operation_unary ~ (value | variable) } +expression_binary = { (value | variable) ~ (operation_binary ~ (value | variable))* } + +expression = { expression_unary | expression_binary } + +/// Statements + +statement_assign = { variable ~ "=" ~ expression } +statement_return = { "return" ~ expression } + +statement = { statement_assign | statement_return } + +// /// Helpers +// +// helper_range = { expression+ ~ ".." ~ expression+ } // Confirm that '+' is the correct repetition diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000000..f346ab0f24 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,55 @@ +extern crate pest; +#[macro_use] +extern crate pest_derive; + +use pest::Parser; +use std::fs; + +#[derive(Parser)] +#[grammar = "language.pest"] +pub struct LanguageParser; + +// pub struct Statement + +fn main() { + let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file"); + + let file = LanguageParser::parse(Rule::file, &unparsed_file) + .expect("unsuccessful parse") // unwrap the parse result + .next().unwrap(); // get and unwrap the `file` rule; never fails + + for token in file.into_inner() { + match token.as_rule() { + Rule::statement => println!("{:?}", token.into_inner()), + Rule::EOI => println!("END"), + _ => println!("{:?}", token.into_inner()), + } + // println!("{:?}", token); + } + + // let mut field_sum: f64 = 0.0; + // let mut record_count: u64 = 0; + // + // for record in file.into_inner() { + // match record.as_rule() { + // Rule::record => { + // record_count += 1; + // + // for field in record.into_inner() { + // field_sum += field.as_str().parse::().unwrap(); + // } + // } + // Rule::EOI => (), + // _ => unreachable!(), + // } + // } + + // println!("Sum of fields: {}", field_sum); + // println!("Number of records: {}", record_count); + + let successful_parse = LanguageParser::parse(Rule::value, "-273"); + println!("{:?}", successful_parse); + + // let unsuccessful_parse = CSVParser::parse(Rule::field, "this is not a number"); + // println!("{:?}", unsuccessful_parse); +}