This commit is contained in:
howardwu 2020-03-11 14:56:54 -07:00
parent bc4c60712b
commit 078db23fa6
4 changed files with 619 additions and 74 deletions

193
Cargo.lock generated
View File

@ -1,5 +1,27 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # 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]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.7.3" version = "0.7.3"
@ -33,6 +55,18 @@ version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 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]] [[package]]
name = "digest" name = "digest"
version = "0.8.1" version = "0.8.1"
@ -42,12 +76,50 @@ dependencies = [
"generic-array", "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]] [[package]]
name = "fake-simd" name = "fake-simd"
version = "0.1.2" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 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]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.12.3" version = "0.12.3"
@ -57,14 +129,38 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "itertools"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
dependencies = [
"either",
]
[[package]] [[package]]
name = "language" name = "language"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"from-pest",
"lazy_static",
"pest", "pest",
"pest-ast",
"pest_derive", "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]] [[package]]
name = "maplit" name = "maplit"
version = "1.0.2" version = "1.0.2"
@ -86,6 +182,19 @@ dependencies = [
"ucd-trie", "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]] [[package]]
name = "pest_derive" name = "pest_derive"
version = "2.1.0" version = "2.1.0"
@ -104,9 +213,9 @@ checksum = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a"
dependencies = [ dependencies = [
"pest", "pest",
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2 1.0.9",
"quote", "quote 1.0.3",
"syn", "syn 1.0.16",
] ]
[[package]] [[package]]
@ -120,13 +229,31 @@ dependencies = [
"sha-1", "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]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.9" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
dependencies = [ 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]] [[package]]
@ -135,9 +262,15 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
dependencies = [ 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]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.8.2" version = "0.8.2"
@ -150,15 +283,47 @@ dependencies = [
"opaque-debug", "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]] [[package]]
name = "syn" name = "syn"
version = "1.0.16" version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.9",
"quote", "quote 1.0.3",
"unicode-xid", "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]] [[package]]
@ -173,8 +338,20 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"

View File

@ -5,5 +5,8 @@ authors = ["howardwu <howardwu@berkeley.edu>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
from-pest = "0.3.1"
lazy_static = "1.3.0"
pest = "2.0" pest = "2.0"
pest_derive = "2.0" pest_derive = "2.0"
pest-ast = "0.3.3"

View File

@ -6,28 +6,57 @@ file = { SOI ~ NEWLINE* ~ statement* ~ NEWLINE* ~ EOI }
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) } COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
WHITESPACE = _{ " " | "\t" ~ NEWLINE } WHITESPACE = _{ " " | "\t" ~ NEWLINE }
/// Visibility /// Visibility
visibility_public = { "public" } visibility_public = { "public" }
visibility_private = { "private" } visibility_private = { "private" }
visibility = { visibility_public | visibility_private } visibility = { visibility_public | visibility_private }
// /// Conditionals /// Unary Operations
//
// conditional_if = { "if" } operation_pre_not = { "!" }
// conditional_else = { "else" }
// operation_post_increment = { "++" }
// conditional_for = { "for" } operation_post_decrement = { "--" }
//
// conditional = { conditional_if | conditional_else | conditional_for } /// 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 /// Values
value_boolean = { "true" | "false" } value_boolean = { "true" | "false" }
value_field = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) } value_field = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) }
// TODO: Boolean array, field array
value = { value_boolean | value_field } value = { value_boolean | value_field }
/// Variables /// Variables
@ -41,60 +70,37 @@ protected_name = { visibility | value_boolean | "return" }
variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } 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 /// Expressions
expression_unary = { operation_unary ~ (value | variable) } // Consider structs, conditionals, postfix, primary, inline array, array initializer, and unary
expression_binary = { (value | variable) ~ (operation_binary ~ (value | variable))* } 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 /// Statements
statement_assign = { variable ~ "=" ~ expression } statement_assign = { variable ~ "=" ~ expression }
statement_return = { "return" ~ expression } statement_return = { "return" ~ expression_tuple }
statement = { statement_assign | statement_return } statement = { statement_assign | statement_return }
// /// Conditionals
//
// conditional_if = { "if" }
// conditional_else = { "else" }
//
// conditional_for = { "for" }
//
// conditional = { conditional_if | conditional_else | conditional_for }
// /// Helpers // /// Helpers
// //
// helper_range = { expression+ ~ ".." ~ expression+ } // Confirm that '+' is the correct repetition // helper_range = { expression+ ~ ".." ~ expression+ } // Confirm that '+' is the correct repetition

View File

@ -2,6 +2,14 @@ extern crate pest;
#[macro_use] #[macro_use]
extern crate pest_derive; extern crate pest_derive;
extern crate from_pest;
#[macro_use]
extern crate pest_ast;
#[macro_use]
extern crate lazy_static;
use pest::Parser; use pest::Parser;
use std::fs; use std::fs;
@ -9,23 +17,374 @@ use std::fs;
#[grammar = "language.pest"] #[grammar = "language.pest"]
pub struct LanguageParser; 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() { fn main() {
use crate::from_pest::FromPest;
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file"); 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) println!("{:?}", syntax_tree);
.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);
// }
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 field_sum: f64 = 0.0;
// let mut record_count: u64 = 0; // let mut record_count: u64 = 0;