diff --git a/Cargo.lock b/Cargo.lock index 4745d31..d4dcd86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,6 +282,18 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lexical-core" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.62" @@ -382,6 +394,16 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nom" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num" version = "0.1.42" @@ -729,6 +751,14 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "1.0.0" @@ -754,6 +784,7 @@ dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "radix_trie 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "schala-lang-codegen 0.1.0", "schala-repl 0.1.0", @@ -846,6 +877,11 @@ name = "smallvec" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "static_assertions" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stopwatch" version = "0.0.7" @@ -1040,6 +1076,7 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum linefeed 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28715d08e35c6c074f9ae6b2e6a2420bac75d050c66ecd669d7d5b98e2caa036" "checksum llvm-sys 70.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e9fc46a848cf4170694144102ec07f6eada790d8b3d7e92ffa9cc7416fc869" @@ -1052,6 +1089,7 @@ dependencies = [ "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum nom 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c433f4d505fe6ce7ff78523d2fa13a0b9f2690e181fc26168bcbe5ccc5d14e07" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" "checksum num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" @@ -1091,6 +1129,7 @@ dependencies = [ "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -1100,6 +1139,7 @@ dependencies = [ "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum smallstr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6aa65bb4d5b2bbc90d36af64e29802f788aa614783fa1d0df011800ddcec6e8e" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" "checksum stopwatch 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3d04b5ebc78da44d3a456319d8bc2783e7d8cc7ccbb5cb4dc3f54afbd93bf728" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" diff --git a/schala-lang/language/Cargo.toml b/schala-lang/language/Cargo.toml index 3a71603..8f0d88c 100644 --- a/schala-lang/language/Cargo.toml +++ b/schala-lang/language/Cargo.toml @@ -15,6 +15,7 @@ stopwatch = "0.0.7" derivative = "1.0.3" colored = "1.8" radix_trie = "0.1.5" +nom = "5.1.0" schala-lang-codegen = { path = "../codegen" } schala-repl = { path = "../../schala-repl" } diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index b1cc40f..9cd19e6 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -17,7 +17,7 @@ pub struct ItemId { } impl ItemId { - fn new(n: u32) -> ItemId { + pub fn new(n: u32) -> ItemId { ItemId { idx: n } } } diff --git a/schala-lang/language/src/lib.rs b/schala-lang/language/src/lib.rs index dfc32de..c4c983f 100644 --- a/schala-lang/language/src/lib.rs +++ b/schala-lang/language/src/lib.rs @@ -32,6 +32,7 @@ mod debugging; mod tokenizing; mod ast; +mod parser; mod parsing; #[macro_use] mod symbol_table; diff --git a/schala-lang/language/src/parser.rs b/schala-lang/language/src/parser.rs new file mode 100644 index 0000000..fef059d --- /dev/null +++ b/schala-lang/language/src/parser.rs @@ -0,0 +1,129 @@ +extern crate nom; + +use std::rc::Rc; +use std::str::FromStr; + +use nom::IResult; +use nom::bytes::complete::{tag, take_while}; +use nom::combinator::{map_res, value, opt}; +use nom::multi::many1; +//use nom::error::{ParseError, ErrorKind}; +use nom::branch::alt; + +use crate::ast::*; +use crate::builtin::Builtin; + + +/* +#[derive(Debug, Clone)] +enum Prefix { + Plus, + Minus, + Bang, +} +*/ + +const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|"; + +fn parse_operator(input: &str) -> IResult<&str, BinOp> { + use nom::character::complete::one_of; + let (rest, op): (_, Vec) = many1(one_of(OPERATOR_CHARS))(input)?; + let sigil: String = op.into_iter().collect(); + Ok((rest, BinOp::from_sigil(&sigil))) +} + + +fn parse_bool_literal(input: &str) -> IResult<&str, ExpressionKind> { + let (rest, value) = alt(( + value(true, tag("true")), + value(false, tag("false")) + ))(input)?; + Ok((rest, ExpressionKind::BoolLiteral(value))) +} + +fn parse_binary_literal(input: &str) -> IResult<&str, ExpressionKind> { + let (rest, _) = tag("0b")(input)?; + let (rest, n): (&str, u64) = map_res( + take_while(|c: char| c == '0' || c == '1'), + |hex_str: &str| u64::from_str_radix(hex_str, 2) + )(rest)?; + let expr = ExpressionKind::NatLiteral(n); + Ok((rest, expr)) +} + +fn parse_hex_literal(input: &str) -> IResult<&str, ExpressionKind> { + let (rest, _) = tag("0x")(input)?; + let (rest, n): (&str, u64) = map_res( + take_while(|c: char| c.is_digit(16)), + |hex_str: &str| u64::from_str_radix(hex_str, 16) + )(rest)?; + let expr = ExpressionKind::NatLiteral(n); + Ok((rest, expr)) +} + +fn parse_string_literal(input: &str) -> IResult<&str, ExpressionKind> { + let (rest, _) = nom::character::complete::char('"')(input)?; + let (rest, string_output) = nom::bytes::complete::take_until("\"")(rest)?; + let (rest, _) = nom::character::complete::char('"')(rest)?; + let expr = ExpressionKind::StringLiteral(Rc::new(string_output.to_string())); + Ok((rest, expr)) +} + +fn parse_literal(input: &str) -> IResult<&str, ExpressionKind> { + alt(( + parse_string_literal, + parse_hex_literal, + parse_binary_literal, + parse_bool_literal + ))(input) +} + +fn paren_expr(input: &str) -> IResult<&str, ExpressionKind> { + let (rest, _) = nom::character::complete::char('(')(input)?; + let (rest, inner) = expression_kind(rest)?; + let (rest, _) = nom::character::complete::char(')')(rest)?; + Ok((rest, inner)) +} + +fn prefix_op(input: &str) -> IResult<&str, PrefixOp> { + use nom::character::complete::char; + let (rest, sigil) = alt(( + char('+'), + char('-'), + char('!') + ))(input)?; + let op = PrefixOp::from_str(&sigil.to_string()).unwrap(); + Ok((rest, op)) + + /* + alt(( + value(Plus, char('+')), + value(Minus, char('-')), + value(Bang, char('!')) + ))(input) + */ +} + +fn prefix_expr(input: &str) -> IResult<&str, ExpressionKind> { + let (rest, pfx) = opt(prefix_op)(input)?; + let (rest, result) = alt(( + paren_expr, + parse_literal + ))(rest)?; + match pfx { + None => Ok((rest, result)), + Some(pfx) => { + let exp = Expression { id: ItemId::new(0), kind: result, type_anno: None }; + Ok((rest, ExpressionKind::PrefixExp(pfx, Box::new(exp)))) + } + } +} + +fn expression_kind(input: &str) -> IResult<&str, ExpressionKind> { + prefix_expr(input) +} + +pub fn perform_parsing(input: &str) -> Result { + let output = expression_kind(input); + Ok(format!("{:?}", output)) +} diff --git a/schala-lang/language/src/schala.rs b/schala-lang/language/src/schala.rs index a5a41e2..e8d6b35 100644 --- a/schala-lang/language/src/schala.rs +++ b/schala-lang/language/src/schala.rs @@ -10,7 +10,7 @@ use schala_repl::{ProgrammingLanguageInterface, ComputationRequest, ComputationResponse, LangMetaRequest, LangMetaResponse, GlobalOutputStats, DebugResponse, DebugAsk}; -use crate::{ast, reduced_ast, tokenizing, parsing, eval, typechecking, symbol_table, source_map}; +use crate::{ast, reduced_ast, tokenizing, parsing, parser, eval, typechecking, symbol_table, source_map}; pub type SymbolTableHandle = Rc>; pub type SourceMapHandle = Rc>; @@ -319,6 +319,8 @@ impl ProgrammingLanguageInterface for Schala { total_duration, stage_durations }; + let main_output = parser::perform_parsing(source); + ComputationResponse { main_output, global_output_stats,