Enough work to hopefully make hello world parse and build AST.
This commit is contained in:
parent
63dec99cb5
commit
e3dc46e023
319
src/ast/build.rs
319
src/ast/build.rs
@ -1,6 +1,20 @@
|
||||
use crate::ast::{AssignStatement, BinaryExpression, BinaryOperator, BlockStatement, CallArgument, CallArguments, CallExpression, CallStatement, ClassConstructor, ClassConstructorParameter, ClassDeclaration, ClassLevelDeclaration, Closure, CompilationUnit, Expression, FieldDeclaration, ForStatement, FullyQualifiedName, FunctionBody, FunctionDefinition, FunctionModifier, FunctionTypeModifier, FunctionTypeUse, GenericArguments, GenericParameter, GenericParameters, Identifier, IfElseStatement, IfStatement, ImplementsList, InterfaceDeclaration, InterfaceFunctionDeclaration, InterfaceLevelDeclaration, InterfaceOperatorFunctionDeclaration, InterfaceOrClassTypeUse, Literal, ModuleDeclaration, ModuleLevelDeclaration, ObjectAccess, ObjectNavigation, ObjectNavigations, OperatorFunctionDefinition, Parameter, Parameters, PlatformFunctionDeclaration, PropertyDeclaration, Reference, References, ReturnStatement, ReturnType, Statement, SuffixExpression, SuffixUnaryOperator, TernaryExpression, TupleArguments, TupleTypeUse, TurboFish, TypeUse, UnarySuffixExpression, VariableDeclarationStatement, WhileStatement};
|
||||
use crate::ast::{
|
||||
AssignStatement, BinaryExpression, BinaryOperator, BlockStatement, CallArgument, CallArguments,
|
||||
CallExpression, CallStatement, ClassConstructor, ClassConstructorParameter, ClassDeclaration,
|
||||
ClassLevelDeclaration, Closure, CompilationUnit, Expression, FieldDeclaration, ForStatement,
|
||||
FullyQualifiedName, FunctionBody, FunctionDefinition, FunctionModifier, FunctionTypeModifier,
|
||||
FunctionTypeUse, GenericArguments, GenericParameter, GenericParameters, Identifier,
|
||||
IfElseStatement, IfStatement, ImplementsList, InterfaceDeclaration,
|
||||
InterfaceFunctionDeclaration, InterfaceLevelDeclaration, InterfaceOperatorFunctionDeclaration,
|
||||
InterfaceOrClassTypeUse, Literal, ModuleDeclaration, ModuleLevelDeclaration, ObjectAccess,
|
||||
ObjectNavigation, ObjectNavigations, OperatorFunctionDefinition, Parameter, Parameters,
|
||||
PlatformFunctionDeclaration, PrefixExpression, PrefixUnaryOperator, PropertyDeclaration,
|
||||
Reference, References, ReturnStatement, ReturnType, Statement, SuffixExpression,
|
||||
SuffixUnaryOperator, TernaryExpression, TupleArguments, TupleTypeUse, TurboFish, TypeUse,
|
||||
UnarySuffixExpression, VariableDeclarationStatement, WhileStatement,
|
||||
};
|
||||
use crate::parser::Rule;
|
||||
use pest::iterators::Pair;
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
|
||||
fn expect_and_use<T>(pair: Pair<Rule>, rule: Rule, f: fn(Pair<Rule>) -> T) -> T {
|
||||
if pair.as_rule() != rule {
|
||||
@ -702,15 +716,82 @@ fn build_statement(statement_pair: Pair<Rule>) -> Statement {
|
||||
fn build_variable_declaration(
|
||||
variable_declaration_pair: Pair<Rule>,
|
||||
) -> VariableDeclarationStatement {
|
||||
todo!()
|
||||
let mut is_mutable = false;
|
||||
let mut identifier = None;
|
||||
let mut declared_type = None;
|
||||
let mut initializer = None;
|
||||
|
||||
for inner_pair in variable_declaration_pair.into_inner() {
|
||||
match inner_pair.as_rule() {
|
||||
Rule::Let => {}
|
||||
Rule::Mut => {
|
||||
is_mutable = true;
|
||||
}
|
||||
Rule::Identifier => {
|
||||
identifier = Some(build_identifier(inner_pair));
|
||||
}
|
||||
Rule::TypeUse => {
|
||||
declared_type = Some(build_type_use(inner_pair));
|
||||
}
|
||||
Rule::Expression => {
|
||||
initializer = Some(build_expression(inner_pair));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
VariableDeclarationStatement {
|
||||
is_mutable,
|
||||
identifier: identifier.unwrap(),
|
||||
declared_type,
|
||||
initializer,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_assignment_statement(assignment_pair: Pair<Rule>) -> AssignStatement {
|
||||
todo!()
|
||||
let mut inner = assignment_pair.into_inner();
|
||||
let lhs = build_expression(inner.next().unwrap());
|
||||
let rhs = build_expression(inner.next().unwrap());
|
||||
AssignStatement { lhs, rhs }
|
||||
}
|
||||
|
||||
fn build_call_statement(call_statement_pair: Pair<Rule>) -> CallStatement {
|
||||
todo!()
|
||||
let mut inner = call_statement_pair.into_inner();
|
||||
let mut result = expect_and_use(
|
||||
inner.next().unwrap(),
|
||||
Rule::PrimaryExpression,
|
||||
build_primary_expression,
|
||||
);
|
||||
|
||||
while let Some(inner_pair) = inner.next() {
|
||||
match inner_pair.as_rule() {
|
||||
Rule::ObjectAccess => {
|
||||
result = Expression::Suffix(SuffixExpression::ObjectAccess(build_object_access(
|
||||
result, inner_pair,
|
||||
)));
|
||||
}
|
||||
Rule::ParenthesesCall => {
|
||||
result = Expression::Suffix(SuffixExpression::Call(build_call_expression(
|
||||
result, inner_pair,
|
||||
)));
|
||||
}
|
||||
Rule::PlusPlus => {
|
||||
result = Expression::Suffix(SuffixExpression::Unary(UnarySuffixExpression {
|
||||
expression: Box::new(result),
|
||||
operator: SuffixUnaryOperator::PlusPlus,
|
||||
}));
|
||||
}
|
||||
Rule::MinusMinus => {
|
||||
result = Expression::Suffix(SuffixExpression::Unary(UnarySuffixExpression {
|
||||
expression: Box::new(result),
|
||||
operator: SuffixUnaryOperator::MinusMinus,
|
||||
}));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
CallStatement(result)
|
||||
}
|
||||
|
||||
fn build_return_statement(return_statement_pair: Pair<Rule>) -> ReturnStatement {
|
||||
@ -734,63 +815,171 @@ fn build_for_statement(for_statement_pair: Pair<Rule>) -> ForStatement {
|
||||
}
|
||||
|
||||
fn build_expression(expression_pair: Pair<Rule>) -> Expression {
|
||||
let inner_pair = expression_pair.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
Rule::TernaryExpression => Expression::Ternary(build_ternary_expression(inner_pair)),
|
||||
_ => unreachable!(),
|
||||
expect_and_use(
|
||||
expression_pair.into_inner().next().unwrap(),
|
||||
Rule::TernaryExpression,
|
||||
build_ternary_expression,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_ternary_expression(ternary_pair: Pair<Rule>) -> Expression {
|
||||
let mut inner = ternary_pair.into_inner();
|
||||
if inner.len() == 3 {
|
||||
let condition = expect_and_use(
|
||||
inner.next().unwrap(),
|
||||
Rule::OrExpression,
|
||||
build_or_expression,
|
||||
);
|
||||
let true_expression =
|
||||
expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
|
||||
let false_expression =
|
||||
expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
|
||||
Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(condition),
|
||||
true_expression: Box::new(true_expression),
|
||||
false_expression: Box::new(false_expression),
|
||||
})
|
||||
} else {
|
||||
expect_and_use(
|
||||
inner.next().unwrap(),
|
||||
Rule::OrExpression,
|
||||
build_or_expression,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn build_ternary_expression(ternary_pair: Pair<Rule>) -> TernaryExpression {
|
||||
todo!()
|
||||
macro_rules! build_binary_expression {
|
||||
( $pair:ident, $left_rule:expr, $left_fn:expr, $( $pat:pat => $arm:expr ),* $(,)? ) => {{
|
||||
let mut inner: Pairs<Rule> = $pair.into_inner();
|
||||
if inner.len() == 3 {
|
||||
let left = expect_and_use(inner.next().unwrap(), $left_rule, $left_fn);
|
||||
let op = inner.next().unwrap(); // op
|
||||
let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
|
||||
Expression::Binary(BinaryExpression {
|
||||
left: Box::new(left),
|
||||
operator: match op.as_rule() {
|
||||
$( $pat => $arm, )*
|
||||
_ => unreachable!(),
|
||||
},
|
||||
right: Box::new(right),
|
||||
})
|
||||
} else {
|
||||
$left_fn(inner.next().unwrap())
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn build_or_expression(or_expression_pair: Pair<Rule>) -> Expression {
|
||||
let mut inner = or_expression_pair.into_inner();
|
||||
if inner.len() == 3 {
|
||||
let left = expect_and_use(
|
||||
inner.next().unwrap(),
|
||||
Rule::AndExpression,
|
||||
build_and_expression,
|
||||
);
|
||||
inner.next().unwrap(); // Or
|
||||
let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
|
||||
Expression::Binary(BinaryExpression {
|
||||
left: Box::new(left),
|
||||
operator: BinaryOperator::Or,
|
||||
right: Box::new(right),
|
||||
})
|
||||
} else {
|
||||
build_and_expression(inner.next().unwrap())
|
||||
}
|
||||
build_binary_expression!(
|
||||
or_expression_pair,
|
||||
Rule::AndExpression,
|
||||
build_and_expression,
|
||||
Rule::Or => BinaryOperator::Or,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_and_expression(and_expression_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn build_equality_expression(equality_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
build_binary_expression!(
|
||||
and_expression_pair,
|
||||
Rule::ComparisonExpression,
|
||||
build_comparison_expression,
|
||||
Rule::And => BinaryOperator::And,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_comparison_expression(comparison_expression_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
build_binary_expression!(
|
||||
comparison_expression_pair,
|
||||
Rule::ShiftExpression,
|
||||
build_shift_expression,
|
||||
Rule::Greater => BinaryOperator::Greater,
|
||||
Rule::Less => BinaryOperator::Less,
|
||||
Rule::GreaterEqual => BinaryOperator::GreaterEqual,
|
||||
Rule::LessEqual => BinaryOperator::LessEqual,
|
||||
Rule::EqualTo => BinaryOperator::EqualTo,
|
||||
Rule::NotEqualTo => BinaryOperator::NotEqualTo,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_shift_expression(shift_expression_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
build_binary_expression!(
|
||||
shift_expression_pair,
|
||||
Rule::AdditiveExpression,
|
||||
build_additive_expression,
|
||||
Rule::LeftShift => BinaryOperator::LeftShift,
|
||||
Rule::RightShift => BinaryOperator::RightShift,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_additive_expression(add_expression_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
build_binary_expression!(
|
||||
add_expression_pair,
|
||||
Rule::MultiplicativeExpression,
|
||||
build_multiplicative_expression,
|
||||
Rule::Add => BinaryOperator::Add,
|
||||
Rule::Subtract => BinaryOperator::Subtract,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_multiplicative_expression(multiplicative_expression_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
build_binary_expression!(
|
||||
multiplicative_expression_pair,
|
||||
Rule::PrefixExpression,
|
||||
build_prefix_expression,
|
||||
Rule::Multiply => BinaryOperator::Multiply,
|
||||
Rule::Divide => BinaryOperator::Divide,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_prefix_expression(prefix_pair: Pair<Rule>) -> Expression {
|
||||
todo!()
|
||||
let mut inner_rev = prefix_pair.into_inner().rev();
|
||||
let mut result = expect_and_use(
|
||||
inner_rev.next().unwrap(),
|
||||
Rule::SuffixExpression,
|
||||
build_suffix_expression,
|
||||
);
|
||||
while let Some(prefix_pair) = inner_rev.next() {
|
||||
match prefix_pair.as_rule() {
|
||||
Rule::Spread => {
|
||||
result = Expression::UnaryPrefix(PrefixExpression {
|
||||
operator: PrefixUnaryOperator::Spread,
|
||||
expression: Box::new(result),
|
||||
});
|
||||
}
|
||||
Rule::BorrowMut => {
|
||||
result = Expression::UnaryPrefix(PrefixExpression {
|
||||
operator: PrefixUnaryOperator::BorrowMut,
|
||||
expression: Box::new(result),
|
||||
})
|
||||
}
|
||||
Rule::Borrow => {
|
||||
result = Expression::UnaryPrefix(PrefixExpression {
|
||||
operator: PrefixUnaryOperator::Borrow,
|
||||
expression: Box::new(result),
|
||||
})
|
||||
}
|
||||
Rule::Mut => {
|
||||
result = Expression::UnaryPrefix(PrefixExpression {
|
||||
operator: PrefixUnaryOperator::Mut,
|
||||
expression: Box::new(result),
|
||||
})
|
||||
}
|
||||
Rule::Not => {
|
||||
result = Expression::UnaryPrefix(PrefixExpression {
|
||||
operator: PrefixUnaryOperator::Not,
|
||||
expression: Box::new(result),
|
||||
})
|
||||
}
|
||||
Rule::Negative => {
|
||||
result = Expression::UnaryPrefix(PrefixExpression {
|
||||
operator: PrefixUnaryOperator::Negative,
|
||||
expression: Box::new(result),
|
||||
})
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn build_suffix_expression(suffix_pair: Pair<Rule>) -> Expression {
|
||||
@ -870,7 +1059,9 @@ fn build_call_expression(callee: Expression, parentheses_call_pair: Pair<Rule>)
|
||||
}
|
||||
|
||||
fn build_turbo_fish(turbo_fish_pair: Pair<Rule>) -> TurboFish {
|
||||
TurboFish(build_generic_arguments(turbo_fish_pair.into_inner().next().unwrap()))
|
||||
TurboFish(build_generic_arguments(
|
||||
turbo_fish_pair.into_inner().next().unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
fn build_primary_expression(primary_expression_pair: Pair<Rule>) -> Expression {
|
||||
@ -905,10 +1096,52 @@ fn build_object_access(receiver: Expression, navigations_pair: Pair<Rule>) -> Ob
|
||||
}
|
||||
}
|
||||
|
||||
fn build_literal(literal_pair: Pair<Rule>) -> Literal {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn build_closure(closure_pair: Pair<Rule>) -> Closure {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn build_literal(literal_pair: Pair<Rule>) -> Literal {
|
||||
let inner_pair = literal_pair.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
Rule::NumberLiteral => build_number_literal(inner_pair),
|
||||
Rule::StringLiteral => build_string_literal(inner_pair),
|
||||
Rule::BooleanLiteral => build_boolean_literal(inner_pair),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_number_literal(pair: Pair<Rule>) -> Literal {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn build_string_literal(pair: Pair<Rule>) -> Literal {
|
||||
let inner_pair = pair.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
Rule::SingleQuoteString => build_single_quote_string(inner_pair),
|
||||
Rule::DoubleQuoteString => build_double_quote_string(inner_pair),
|
||||
Rule::BacktickString => build_backtick_string(inner_pair),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_boolean_literal(pair: Pair<Rule>) -> Literal {
|
||||
let inner_pair = pair.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
Rule::True => Literal::BooleanLiteral(true),
|
||||
Rule::False => Literal::BooleanLiteral(false),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_single_quote_string(pair: Pair<Rule>) -> Literal {
|
||||
let inner_pair = pair.into_inner().next().unwrap();
|
||||
Literal::StringLiteral(inner_pair.to_string())
|
||||
}
|
||||
|
||||
fn build_double_quote_string(pair: Pair<Rule>) -> Literal {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn build_backtick_string(pair: Pair<Rule>) -> Literal {
|
||||
todo!()
|
||||
}
|
||||
|
@ -34,8 +34,9 @@ pub enum BinaryOperator {
|
||||
#[derive(Debug)]
|
||||
pub enum PrefixUnaryOperator {
|
||||
Spread,
|
||||
Borrow,
|
||||
BorrowMut,
|
||||
Borrow,
|
||||
Mut,
|
||||
Not,
|
||||
Negative,
|
||||
}
|
||||
@ -418,10 +419,7 @@ pub struct AssignStatement {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallStatement {
|
||||
pub callee: Expression,
|
||||
pub arguments: CallArguments,
|
||||
}
|
||||
pub struct CallStatement(pub Expression);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReturnStatement(pub Option<Expression>);
|
||||
@ -472,8 +470,8 @@ pub enum Expression {
|
||||
#[derive(Debug)]
|
||||
pub struct TernaryExpression {
|
||||
pub condition: Box<Expression>,
|
||||
pub true_block: Box<Expression>,
|
||||
pub false_block: Box<Expression>,
|
||||
pub true_expression: Box<Expression>,
|
||||
pub false_expression: Box<Expression>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -28,6 +28,8 @@ For = { "for" }
|
||||
In = { "in" }
|
||||
Move = { "move" }
|
||||
Alias = { "alias" }
|
||||
True = { "true" }
|
||||
False = { "false" }
|
||||
|
||||
// Keywords as a rule (for preventing identifiers with keywords, etc.)
|
||||
Keyword = {
|
||||
@ -60,6 +62,8 @@ Keyword = {
|
||||
| In
|
||||
| Move
|
||||
| Alias
|
||||
| True
|
||||
| False
|
||||
}
|
||||
|
||||
// Symbols
|
||||
@ -611,7 +615,7 @@ MultiplicativeExpression = {
|
||||
PrefixExpression = {
|
||||
(
|
||||
Spread
|
||||
| ( Borrow ~ Mut )
|
||||
| BorrowMut
|
||||
| Borrow
|
||||
| Mut
|
||||
| Not
|
||||
@ -620,6 +624,10 @@ PrefixExpression = {
|
||||
~ SuffixExpression
|
||||
}
|
||||
|
||||
BorrowMut = {
|
||||
Borrow ~ Mut
|
||||
}
|
||||
|
||||
SuffixExpression = {
|
||||
PrimaryExpression
|
||||
~ (
|
||||
@ -748,16 +756,57 @@ HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }
|
||||
|
||||
HexadecimalDigit = { '0'..'9' | 'a'..'f' }
|
||||
|
||||
StringLiteral = ${ "\"" ~ StringInner ~ "\"" }
|
||||
StringLiteral = {
|
||||
SingleQuoteString
|
||||
| DoubleQuoteString
|
||||
| BacktickString
|
||||
}
|
||||
|
||||
SingleQuoteString = ${ "'" ~ StringInner ~ "'" }
|
||||
|
||||
DoubleQuoteString = {
|
||||
"\""
|
||||
~ ( DStringInner? ~ DStringExpression )*
|
||||
~ DStringInner?
|
||||
~ "\""
|
||||
}
|
||||
|
||||
StringInner = @{ StringChar* }
|
||||
|
||||
StringChar = {
|
||||
!( "\"" | "\\" ) ~ ANY
|
||||
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" )
|
||||
!( "\"" | "\\" ) ~ ANY
|
||||
| "\\" ~ ( "'" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" )
|
||||
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
|
||||
}
|
||||
|
||||
BooleanLiteral = { "true" | "false" }
|
||||
DStringInner = @{ DStringChar+ }
|
||||
|
||||
DStringChar = {
|
||||
!( "\"" | "\\" ) ~ ANY
|
||||
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
|
||||
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
|
||||
}
|
||||
|
||||
DStringExpression = {
|
||||
"$"
|
||||
~ BlockStatement
|
||||
}
|
||||
|
||||
BacktickString = {
|
||||
"`"
|
||||
~ ( DStringInner? ~ DStringExpression )*
|
||||
~ DStringInner?
|
||||
~ "`"
|
||||
}
|
||||
|
||||
BacktickInner = @{ BacktickStringChar+ }
|
||||
|
||||
BacktickStringChar = {
|
||||
!( "\"" | "\\" ) ~ ANY
|
||||
| "\\" ~ ( "`" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
|
||||
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
|
||||
}
|
||||
|
||||
BooleanLiteral = { True | False }
|
||||
|
||||
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }
|
||||
|
Loading…
Reference in New Issue
Block a user