mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-22 17:51:39 +03:00
AST WIP
This commit is contained in:
parent
bc4c60712b
commit
078db23fa6
193
Cargo.lock
generated
193
Cargo.lock
generated
@ -1,5 +1,27 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8"
|
||||
dependencies = [
|
||||
"backtrace-sys",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
@ -33,6 +55,18 @@ version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
@ -42,12 +76,50 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "from-pest"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aba9389cedcba1fb3a2aa2ed00f584f2606bce8e0106614a17327a24513bc60f"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.3"
|
||||
@ -57,14 +129,38 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "language"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"from-pest",
|
||||
"lazy_static",
|
||||
"pest",
|
||||
"pest-ast",
|
||||
"pest_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
@ -86,6 +182,19 @@ dependencies = [
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest-ast"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fbf404899169771dd6a32c84248b83cd67a26cc7cc957aac87661490e1227e4"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"single",
|
||||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.1.0"
|
||||
@ -104,9 +213,9 @@ checksum = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -120,13 +229,31 @@ dependencies = [
|
||||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -135,9 +262,15 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 1.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.8.2"
|
||||
@ -150,15 +283,47 @@ dependencies = [
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "single"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5add732a1ab689845591a1b50339cf5310b563e08dc5813c65991f30369ea2"
|
||||
dependencies = [
|
||||
"failure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.16",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -173,8 +338,20 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
@ -5,5 +5,8 @@ authors = ["howardwu <howardwu@berkeley.edu>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
from-pest = "0.3.1"
|
||||
lazy_static = "1.3.0"
|
||||
pest = "2.0"
|
||||
pest_derive = "2.0"
|
||||
pest-ast = "0.3.3"
|
||||
|
@ -6,28 +6,57 @@ 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 }
|
||||
/// Unary Operations
|
||||
|
||||
operation_pre_not = { "!" }
|
||||
|
||||
operation_post_increment = { "++" }
|
||||
operation_post_decrement = { "--" }
|
||||
|
||||
/// Binary Operations
|
||||
|
||||
operation_and = { "&&" }
|
||||
operation_or = { "||" }
|
||||
|
||||
operation_eq = { "==" }
|
||||
operation_neq = { "!=" }
|
||||
|
||||
operation_geq = { ">=" }
|
||||
operation_gt = { ">" }
|
||||
operation_leq = { "<=" }
|
||||
operation_lt = { "<" }
|
||||
|
||||
operation_add = { "+" }
|
||||
operation_sub = { "-" }
|
||||
operation_mul = { "*" }
|
||||
operation_div = { "/" }
|
||||
operation_pow = { "**" }
|
||||
|
||||
operation_binary = {
|
||||
operation_and | operation_or |
|
||||
operation_eq | operation_neq |
|
||||
operation_geq | operation_gt | operation_leq | operation_lt |
|
||||
operation_add | operation_sub | operation_mul | operation_div | operation_pow
|
||||
}
|
||||
|
||||
// operation_add_assign = { "+=" }
|
||||
// operation_sub_assign = { "-=" }
|
||||
// operation_mul_assign = { "*=" }
|
||||
// operation_div_assign = { "/=" }
|
||||
|
||||
/// Values
|
||||
|
||||
value_boolean = { "true" | "false" }
|
||||
|
||||
value_field = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) }
|
||||
|
||||
// TODO: Boolean array, field array
|
||||
|
||||
value = { value_boolean | value_field }
|
||||
|
||||
/// Variables
|
||||
@ -41,60 +70,37 @@ protected_name = { visibility | value_boolean | "return" }
|
||||
|
||||
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))* }
|
||||
// Consider structs, conditionals, postfix, primary, inline array, array initializer, and unary
|
||||
term = { value | variable | ("(" ~ expression ~ ")") }
|
||||
|
||||
expression = { expression_unary | expression_binary }
|
||||
expression_not = { operation_pre_not ~ term }
|
||||
expression_increment = { term ~ operation_post_increment }
|
||||
expression_decrement = { term ~ operation_post_decrement }
|
||||
|
||||
expression_binary = { term ~ (operation_binary ~ term)* }
|
||||
|
||||
expression = { expression_not | expression_increment | expression_decrement | expression_binary }
|
||||
|
||||
expression_tuple = _{ (expression ~ ("," ~ expression)*)? }
|
||||
|
||||
/// Statements
|
||||
|
||||
statement_assign = { variable ~ "=" ~ expression }
|
||||
statement_return = { "return" ~ expression }
|
||||
statement_return = { "return" ~ expression_tuple }
|
||||
|
||||
statement = { statement_assign | statement_return }
|
||||
|
||||
// /// Conditionals
|
||||
//
|
||||
// conditional_if = { "if" }
|
||||
// conditional_else = { "else" }
|
||||
//
|
||||
// conditional_for = { "for" }
|
||||
//
|
||||
// conditional = { conditional_if | conditional_else | conditional_for }
|
||||
|
||||
// /// Helpers
|
||||
//
|
||||
// helper_range = { expression+ ~ ".." ~ expression+ } // Confirm that '+' is the correct repetition
|
||||
|
383
src/main.rs
383
src/main.rs
@ -2,6 +2,14 @@ extern crate pest;
|
||||
#[macro_use]
|
||||
extern crate pest_derive;
|
||||
|
||||
extern crate from_pest;
|
||||
#[macro_use]
|
||||
extern crate pest_ast;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
|
||||
use pest::Parser;
|
||||
use std::fs;
|
||||
|
||||
@ -9,23 +17,374 @@ use std::fs;
|
||||
#[grammar = "language.pest"]
|
||||
pub struct LanguageParser;
|
||||
|
||||
// pub struct Statement
|
||||
mod ast {
|
||||
use from_pest::ConversionError;
|
||||
use from_pest::FromPest;
|
||||
use from_pest::Void;
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
use pest::prec_climber::{Assoc, Operator, PrecClimber};
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use super::Rule;
|
||||
|
||||
fn span_into_string(span: Span) -> String {
|
||||
span.as_str().to_string()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref PRECEDENCE_CLIMBER: PrecClimber<Rule> = precedence_climber();
|
||||
}
|
||||
|
||||
fn precedence_climber() -> PrecClimber<Rule> {
|
||||
PrecClimber::new(vec![
|
||||
Operator::new(Rule::operation_or, Assoc::Left),
|
||||
Operator::new(Rule::operation_and, Assoc::Left),
|
||||
Operator::new(Rule::operation_eq, Assoc::Left)
|
||||
| Operator::new(Rule::operation_neq, Assoc::Left),
|
||||
Operator::new(Rule::operation_geq, Assoc::Left)
|
||||
| Operator::new(Rule::operation_gt, Assoc::Left)
|
||||
| Operator::new(Rule::operation_leq, Assoc::Left)
|
||||
| Operator::new(Rule::operation_lt, Assoc::Left),
|
||||
Operator::new(Rule::operation_add, Assoc::Left)
|
||||
| Operator::new(Rule::operation_sub, Assoc::Left),
|
||||
Operator::new(Rule::operation_mul, Assoc::Left)
|
||||
| Operator::new(Rule::operation_div, Assoc::Left),
|
||||
Operator::new(Rule::operation_pow, Assoc::Left),
|
||||
])
|
||||
}
|
||||
|
||||
fn binary_expression_rule<'ast>(
|
||||
lhs: Box<Expression<'ast>>,
|
||||
pair: Pair<'ast, Rule>,
|
||||
rhs: Box<Expression<'ast>>,
|
||||
) -> Box<Expression<'ast>> {
|
||||
let (start, _) = lhs.span().clone().split();
|
||||
let (_, end) = rhs.span().clone().split();
|
||||
let span = start.span(&end);
|
||||
|
||||
Box::new(match pair.as_rule() {
|
||||
Rule::operation_or => Expression::binary(BinaryOperator::Or, lhs, rhs, span),
|
||||
Rule::operation_and => Expression::binary(BinaryOperator::And, lhs, rhs, span),
|
||||
Rule::operation_eq => Expression::binary(BinaryOperator::Eq, lhs, rhs, span),
|
||||
Rule::operation_neq => Expression::binary(BinaryOperator::Neq, lhs, rhs, span),
|
||||
Rule::operation_geq => Expression::binary(BinaryOperator::Geq, lhs, rhs, span),
|
||||
Rule::operation_gt => Expression::binary(BinaryOperator::Gt, lhs, rhs, span),
|
||||
Rule::operation_leq => Expression::binary(BinaryOperator::Leq, lhs, rhs, span),
|
||||
Rule::operation_lt => Expression::binary(BinaryOperator::Lt, lhs, rhs, span),
|
||||
Rule::operation_add => Expression::binary(BinaryOperator::Add, lhs, rhs, span),
|
||||
Rule::operation_sub => Expression::binary(BinaryOperator::Sub, lhs, rhs, span),
|
||||
Rule::operation_mul => Expression::binary(BinaryOperator::Mul, lhs, rhs, span),
|
||||
Rule::operation_div => Expression::binary(BinaryOperator::Div, lhs, rhs, span),
|
||||
Rule::operation_pow => Expression::binary(BinaryOperator::Pow, lhs, rhs, span),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_rule_term(pair: Pair<Rule>) -> Box<Expression> {
|
||||
Box::new(match pair.as_rule() {
|
||||
Rule::term => {
|
||||
let clone = pair.clone();
|
||||
let next = clone.into_inner().next().unwrap();
|
||||
match next.as_rule() {
|
||||
Rule::value => Expression::Value(
|
||||
Value::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap()
|
||||
),
|
||||
Rule::variable => Expression::Variable(
|
||||
Variable::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
|
||||
),
|
||||
Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case
|
||||
|
||||
Rule::expression_not => {
|
||||
let span = next.as_span();
|
||||
let mut inner = next.into_inner();
|
||||
let operation = match inner.next().unwrap().as_rule() {
|
||||
Rule::operation_pre_not => Not::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
|
||||
rule => unreachable!("`expression_not` should yield `operation_pre_not`, found {:#?}", rule)
|
||||
};
|
||||
let expression = parse_rule_term(inner.next().unwrap());
|
||||
Expression::Not(NotExpression { operation, expression, span })
|
||||
},
|
||||
Rule::expression_increment => {
|
||||
let span = next.as_span();
|
||||
let mut inner = next.into_inner();
|
||||
let expression = parse_rule_term(inner.next().unwrap());
|
||||
let operation = match inner.next().unwrap().as_rule() {
|
||||
Rule::operation_post_increment => Increment::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
|
||||
rule => unreachable!("`expression_increment` should yield `operation_post_increment`, found {:#?}", rule)
|
||||
};
|
||||
Expression::Increment(IncrementExpression { operation, expression, span })
|
||||
},
|
||||
Rule::expression_decrement => {
|
||||
let span = next.as_span();
|
||||
let mut inner = next.into_inner();
|
||||
let expression = parse_rule_term(inner.next().unwrap());
|
||||
let operation = match inner.next().unwrap().as_rule() {
|
||||
Rule::operation_post_decrement => Decrement::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
|
||||
rule => unreachable!("`expression_decrement` should yield `operation_post_decrement`, found {:#?}", rule)
|
||||
};
|
||||
Expression::Decrement(DecrementExpression { operation, expression, span })
|
||||
},
|
||||
rule => unreachable!("`term` should contain one of ['value', 'variable', 'expression', 'expression_not', 'expression_increment', 'expression_decrement'], found {:#?}", rule)
|
||||
}
|
||||
}
|
||||
rule => unreachable!("`parse_rule_term` should be invoked on `Rule::term`, found {:#?}", rule),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::file))]
|
||||
pub struct File<'ast> {
|
||||
pub statement: Vec<Statement<'ast>>,
|
||||
pub eoi: EOI,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
// Visibility
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::visibility_public))]
|
||||
pub struct Public {}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::visibility_private))]
|
||||
pub struct Private {}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::visibility))]
|
||||
pub enum Visibility {
|
||||
Public(Public),
|
||||
Private(Private),
|
||||
}
|
||||
|
||||
// Unary Operations
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::operation_pre_not))]
|
||||
pub struct Not<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::operation_post_increment))]
|
||||
pub struct Increment<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::operation_post_decrement))]
|
||||
pub struct Decrement<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
// Binary Operations
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum BinaryOperator {
|
||||
Or,
|
||||
And,
|
||||
Eq,
|
||||
Neq,
|
||||
Geq,
|
||||
Gt,
|
||||
Leq,
|
||||
Lt,
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Pow,
|
||||
}
|
||||
|
||||
// Values
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::value_boolean))]
|
||||
pub struct Boolean<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
pub value: String,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::value_field))]
|
||||
pub struct Field<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
pub value: String,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::value))]
|
||||
pub enum Value<'ast> {
|
||||
Boolean(Boolean<'ast>),
|
||||
Field(Field<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> Value<'ast> {
|
||||
pub fn span(&self) -> &Span<'ast> {
|
||||
match self {
|
||||
Value::Boolean(value) => &value.span,
|
||||
Value::Field(value) => &value.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variables
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::variable))]
|
||||
pub struct Variable<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
pub value: String,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
// Expressions
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::expression_not))]
|
||||
pub struct NotExpression<'ast> {
|
||||
pub operation: Not<'ast>,
|
||||
pub expression: Box<Expression<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::expression_increment))]
|
||||
pub struct IncrementExpression<'ast> {
|
||||
pub expression: Box<Expression<'ast>>,
|
||||
pub operation: Increment<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::expression_decrement))]
|
||||
pub struct DecrementExpression<'ast> {
|
||||
pub expression: Box<Expression<'ast>>,
|
||||
pub operation: Decrement<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct BinaryExpression<'ast> {
|
||||
pub operation: BinaryOperator,
|
||||
pub left: Box<Expression<'ast>>,
|
||||
pub right: Box<Expression<'ast>>,
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Expression<'ast> {
|
||||
Value(Value<'ast>),
|
||||
Variable(Variable<'ast>),
|
||||
Not(NotExpression<'ast>),
|
||||
Increment(IncrementExpression<'ast>),
|
||||
Decrement(DecrementExpression<'ast>),
|
||||
Binary(BinaryExpression<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> Expression<'ast> {
|
||||
pub fn binary(
|
||||
operation: BinaryOperator,
|
||||
left: Box<Expression<'ast>>,
|
||||
right: Box<Expression<'ast>>,
|
||||
span: Span<'ast>,
|
||||
) -> Self {
|
||||
Expression::Binary(BinaryExpression { operation, left, right, span })
|
||||
}
|
||||
|
||||
pub fn span(&self) -> &Span<'ast> {
|
||||
match self {
|
||||
Expression::Value(expression) => &expression.span(),
|
||||
Expression::Variable(expression) => &expression.span,
|
||||
Expression::Not(expression) => &expression.span,
|
||||
Expression::Increment(expression) => &expression.span,
|
||||
Expression::Decrement(expression) => &expression.span,
|
||||
Expression::Binary(expression) => &expression.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> FromPest<'ast> for Expression<'ast> {
|
||||
type Rule = Rule;
|
||||
type FatalError = Void;
|
||||
|
||||
fn from_pest(pest: &mut Pairs<'ast, Rule>) -> Result<Self, ConversionError<Void>> {
|
||||
let mut pairs = pest.clone();
|
||||
println!("{:?}\n", pairs);
|
||||
let pair = pairs.next().ok_or(::from_pest::ConversionError::NoMatch)?;
|
||||
match pair.as_rule() {
|
||||
Rule::expression => {
|
||||
// Transfer iterated state to pest.
|
||||
*pest = pairs;
|
||||
Ok(*PRECEDENCE_CLIMBER.climb(pair.into_inner(), parse_rule_term, binary_expression_rule))
|
||||
}
|
||||
_ => Err(ConversionError::NoMatch),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Statements
|
||||
|
||||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::statement_assign))]
|
||||
pub struct AssignStatement<'ast> {
|
||||
pub variable: Variable<'ast>,
|
||||
pub expression: Expression<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::statement_return))]
|
||||
pub struct ReturnStatement<'ast> {
|
||||
pub expressions: Vec<Expression<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::statement))]
|
||||
pub enum Statement<'ast> {
|
||||
Assign(AssignStatement<'ast>),
|
||||
Return(ReturnStatement<'ast>),
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::EOI))]
|
||||
pub struct EOI;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use crate::from_pest::FromPest;
|
||||
|
||||
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file");
|
||||
let mut file = LanguageParser::parse(Rule::file, &unparsed_file).expect("unsuccessful parse");
|
||||
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
||||
|
||||
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
|
||||
println!("{:?}", syntax_tree);
|
||||
|
||||
// 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);
|
||||
// }
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user