Working parser

This commit is contained in:
howardwu 2020-03-13 10:02:39 -07:00
parent 6c4c621dd9
commit a143322f53
5 changed files with 1245 additions and 104 deletions

1123
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,3 +10,6 @@ lazy_static = "1.3.0"
pest = "2.0"
pest_derive = "2.0"
pest-ast = "0.3.3"
snarkos-gadgets = { path = "../snarkOS/gadgets" }
snarkos-models = { path = "../snarkOS/models" }

View File

@ -1 +1,2 @@
x = 5
x = 5 + 3
y = x * (x * 2)

View File

@ -3,9 +3,6 @@
file = { SOI ~ NEWLINE* ~ statement* ~ NEWLINE* ~ EOI }
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
WHITESPACE = _{ " " | "\t" ~ NEWLINE }
/// Visibility
visibility_public = { "public" }
@ -38,7 +35,7 @@ operation_mul = { "*" }
operation_div = { "/" }
operation_pow = { "**" }
operation_binary = {
operation_binary = _ {
operation_and | operation_or |
operation_eq | operation_neq |
operation_geq | operation_gt | operation_leq | operation_lt |
@ -73,15 +70,14 @@ variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHAN
/// Expressions
// Consider structs, conditionals, postfix, primary, inline array, array initializer, and unary
term = { value | variable | ("(" ~ expression ~ ")") }
expression_primitive = { value | variable }
expression_not = { operation_pre_not ~ expression_term }
expression_term = { expression_primitive | expression_not | ("(" ~ expression ~ ")") }
expression_not = { operation_pre_not ~ term }
expression_increment = { term ~ operation_post_increment }
expression_decrement = { term ~ operation_post_decrement }
expression = { expression_term ~ (operation_binary ~ expression_term)* }
expression_binary = { term ~ (operation_binary ~ term)* }
expression = { expression_not | expression_increment | expression_decrement | expression_binary }
// expression_increment = { expression ~ operation_post_increment }
// expression_decrement = { expression ~ operation_post_decrement }
expression_tuple = _{ (expression ~ ("," ~ expression)*)? }
@ -90,7 +86,13 @@ expression_tuple = _{ (expression ~ ("," ~ expression)*)? }
statement_assign = { variable ~ "=" ~ expression }
statement_return = { "return" ~ expression_tuple }
statement = { statement_assign | statement_return }
statement = { (statement_return | (statement_assign) ~ NEWLINE) ~ NEWLINE* }
/// Utilities
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
WHITESPACE = _{ " " | "\t" ~ NEWLINE }
// /// Conditionals
//

View File

@ -9,7 +9,6 @@ extern crate pest_ast;
#[macro_use]
extern crate lazy_static;
use pest::Parser;
use std::fs;
@ -53,7 +52,65 @@ mod ast {
])
}
fn binary_expression_rule<'ast>(
fn parse_term(pair: Pair<Rule>) -> Box<Expression> {
Box::new(match pair.as_rule() {
Rule::expression_term => {
let clone = pair.clone();
let next = clone.into_inner().next().unwrap();
match next.as_rule() {
Rule::expression_primitive => {
let next = next.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 => unreachable!("`expression_primitive` should contain one of [`value`, `variable`], found {:#?}", rule)
}
}
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_term(inner.next().unwrap());
Expression::Not(NotExpression { operation, expression, span })
},
Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case
// Rule::expression_increment => {
// let span = next.as_span();
// let mut inner = next.into_inner();
// let expression = parse_expression_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_expression_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_expression_term` should be invoked on `Rule::expression_term`, found {:#?}", rule),
})
}
fn binary_expression<'ast>(
lhs: Box<Expression<'ast>>,
pair: Pair<'ast, Rule>,
rhs: Box<Expression<'ast>>,
@ -80,57 +137,6 @@ mod ast {
})
}
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> {
@ -257,25 +263,25 @@ mod ast {
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_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(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)]
#[derive(Clone, Debug, PartialEq)]
pub struct BinaryExpression<'ast> {
pub operation: BinaryOperator,
pub left: Box<Expression<'ast>>,
@ -283,14 +289,15 @@ mod ast {
pub span: Span<'ast>,
}
#[derive(Debug, PartialEq, Clone)]
#[derive(Clone, Debug, PartialEq)]
pub enum Expression<'ast> {
Value(Value<'ast>),
Variable(Variable<'ast>),
Not(NotExpression<'ast>),
Increment(IncrementExpression<'ast>),
Decrement(DecrementExpression<'ast>),
Binary(BinaryExpression<'ast>),
// Increment(IncrementExpression<'ast>),
// Decrement(DecrementExpression<'ast>),
}
impl<'ast> Expression<'ast> {
@ -308,9 +315,10 @@ mod ast {
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,
// Expression::Increment(expression) => &expression.span,
// Expression::Decrement(expression) => &expression.span,
}
}
}
@ -320,14 +328,13 @@ mod ast {
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)?;
let mut clone = pest.clone();
let pair = clone.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))
*pest = clone;
Ok(*PRECEDENCE_CLIMBER.climb(pair.into_inner(), parse_term, binary_expression))
}
_ => Err(ConversionError::NoMatch),
}
@ -369,12 +376,31 @@ mod ast {
fn main() {
use crate::from_pest::FromPest;
use snarkos_gadgets::curves::edwards_bls12::FqGadget;
use snarkos_models::gadgets::{r1cs::{ConstraintSystem, TestConstraintSystem, Fr}, utilities::{alloc::AllocGadget, boolean::Boolean}};
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");
println!("{:?}", syntax_tree);
for statement in syntax_tree.statement {
match statement {
ast::Statement::Assign(statement) => {
println!("{:#?}", statement);
},
ast::Statement::Return(statement) => {
}
}
}
let mut cs = TestConstraintSystem::<Fr>::new();
Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true));
println!("\n\n number of constraints for input: {}", cs.num_constraints());
// for token in file.into_inner() {
// match token.as_rule() {
@ -406,8 +432,8 @@ fn main() {
// println!("Sum of fields: {}", field_sum);
// println!("Number of records: {}", record_count);
let successful_parse = LanguageParser::parse(Rule::value, "-273");
println!("{:?}", successful_parse);
// 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);