restructure parsing and typing modules
* parsing backend submodules * move typing to its own module
This commit is contained in:
parent
43df8c4b0a
commit
99434748fa
16 changed files with 1315 additions and 316 deletions
|
|
@ -1,181 +0,0 @@
|
|||
use lazy_static;
|
||||
use pest::error::Error;
|
||||
use pest::iterators::Pair;
|
||||
use pest::pratt_parser::PrattParser;
|
||||
use pest::Parser;
|
||||
|
||||
use crate::ast::*;
|
||||
|
||||
#[derive(pest_derive::Parser)]
|
||||
#[grammar = "parsing/grammar.pest"]
|
||||
struct KrParser;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref PRATT_PARSER: PrattParser<Rule> = {
|
||||
use pest::pratt_parser::{Assoc::*, Op};
|
||||
use Rule::*;
|
||||
|
||||
// Precedence is defined lowest to highest
|
||||
PrattParser::new()
|
||||
// Addition and subtract have equal precedence
|
||||
.op(Op::infix(add, Left) | Op::infix(subtract, Left))
|
||||
.op(Op::infix(multiply, Left) | Op::infix(divide, Left))
|
||||
};
|
||||
}
|
||||
|
||||
pub fn parse(source: &str) -> Result<Ast, Error<Rule>> {
|
||||
let mut definitions: Vec<Ast> = vec![];
|
||||
|
||||
let pairs = KrParser::parse(Rule::source_file, source)?;
|
||||
for pair in pairs {
|
||||
match pair.as_rule() {
|
||||
Rule::source_file => {
|
||||
let pairs = pair.into_inner();
|
||||
for pair in pairs {
|
||||
match pair.as_rule() {
|
||||
Rule::definition => {
|
||||
let definition = parse_definition(pair.into_inner().next().unwrap());
|
||||
definitions.push(definition);
|
||||
}
|
||||
Rule::EOI => {}
|
||||
_ => panic!("unexpected rule in source_file: {:?}", pair.as_rule()),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => eprintln!("unexpected top-level rule {:?}", pair.as_rule()),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Ast::Module(definitions))
|
||||
}
|
||||
|
||||
fn parse_block(pair: Pair<Rule>) -> Block {
|
||||
let mut statements = vec![];
|
||||
let mut value = None;
|
||||
|
||||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
Rule::statement => statements.push(parse_statement(pair)),
|
||||
Rule::expr => value = Some(parse_expression(pair)),
|
||||
_ => panic!("unexpected rule {:?} in block", pair.as_rule()),
|
||||
}
|
||||
}
|
||||
|
||||
Block { statements, value }
|
||||
}
|
||||
|
||||
fn parse_statement(pair: Pair<Rule>) -> Statement {
|
||||
let pair = pair.into_inner().next().unwrap();
|
||||
match pair.as_rule() {
|
||||
Rule::assign_statement => {
|
||||
let mut pairs = pair.into_inner();
|
||||
let identifier = pairs.next().unwrap().as_str().to_string();
|
||||
let expr = parse_expression(pairs.next().unwrap());
|
||||
Statement::AssignStatement(identifier, expr)
|
||||
}
|
||||
Rule::return_statement => {
|
||||
let expr = if let Some(pair) = pair.into_inner().next() {
|
||||
Some(parse_expression(pair))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Statement::ReturnStatement(expr)
|
||||
}
|
||||
Rule::call_statement => {
|
||||
let call = parse_call(pair.into_inner().next().unwrap());
|
||||
Statement::CallStatement(call)
|
||||
}
|
||||
_ => unreachable!("unexpected rule '{:?}' in parse_statement", pair.as_rule()),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_call(pair: Pair<Rule>) -> Call {
|
||||
let mut pairs = pair.into_inner();
|
||||
// TODO: support calls on more than identifiers (needs grammar change)
|
||||
let callee = Expr::Identifier(pairs.next().unwrap().as_str().to_string());
|
||||
let args: Vec<Expr> = pairs
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.map(parse_expression)
|
||||
.collect();
|
||||
Call { callee, args }
|
||||
}
|
||||
|
||||
fn parse_expression(pair: Pair<Rule>) -> Expr {
|
||||
let pairs = pair.into_inner();
|
||||
PRATT_PARSER
|
||||
.map_primary(|primary| match primary.as_rule() {
|
||||
Rule::integer_literal => Expr::IntegerLiteral(primary.as_str().parse().unwrap()),
|
||||
Rule::float_literal => Expr::FloatLiteral(primary.as_str().parse().unwrap()),
|
||||
Rule::string_literal => Expr::StringLiteral(
|
||||
primary
|
||||
.into_inner()
|
||||
.next()
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
),
|
||||
Rule::ident => Expr::Identifier(primary.as_str().to_string()),
|
||||
Rule::expr => parse_expression(primary),
|
||||
Rule::call => Expr::Call(Box::new(parse_call(primary))),
|
||||
_ => unreachable!(
|
||||
"Unexpected rule '{:?}' in primary expression",
|
||||
primary.as_rule()
|
||||
),
|
||||
})
|
||||
.map_infix(|lhs, op, rhs| {
|
||||
let operator = match op.as_rule() {
|
||||
Rule::add => BinaryOperator::Add,
|
||||
Rule::subtract => BinaryOperator::Sub,
|
||||
Rule::multiply => BinaryOperator::Mul,
|
||||
Rule::divide => BinaryOperator::Div,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Expr::BinaryExpression(Box::new(lhs), operator, Box::new(rhs))
|
||||
})
|
||||
.parse(pairs)
|
||||
}
|
||||
|
||||
fn parse_parameter(pair: Pair<Rule>) -> Parameter {
|
||||
assert!(pair.as_rule() == Rule::parameter);
|
||||
let mut pair = pair.into_inner();
|
||||
let name: String = pair.next().unwrap().as_str().to_string();
|
||||
let typ = Type::from(pair.next().unwrap().as_str());
|
||||
Parameter { name, typ }
|
||||
}
|
||||
|
||||
fn parse_definition(pair: Pair<Rule>) -> Ast {
|
||||
match pair.as_rule() {
|
||||
Rule::func_def => {
|
||||
let mut pairs = pair.into_inner();
|
||||
let name = pairs.next().unwrap().as_str().to_string();
|
||||
let parameters: Vec<Parameter> = pairs
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.map(parse_parameter)
|
||||
.collect();
|
||||
let pair = pairs.next().unwrap();
|
||||
// Before the block there is an optional return type
|
||||
let (return_type, pair) = match pair.as_rule() {
|
||||
Rule::ident => (Some(Type::from(pair.as_str())), pairs.next().unwrap()),
|
||||
Rule::block => (None, pair),
|
||||
_ => unreachable!(
|
||||
"Unexpected rule '{:?}' in function definition, expected return type or block",
|
||||
pair.as_rule()
|
||||
),
|
||||
};
|
||||
let body = parse_block(pair);
|
||||
let body = Box::new(body);
|
||||
Ast::FunctionDefinition(FunctionDefinition {
|
||||
name,
|
||||
parameters,
|
||||
return_type,
|
||||
body,
|
||||
})
|
||||
}
|
||||
_ => panic!("unexpected node for definition: {:?}", pair.as_rule()),
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue