Skip to content

Commit

Permalink
implement If statement
Browse files Browse the repository at this point in the history
  • Loading branch information
dhilipsiva committed Apr 15, 2023
1 parent 341679b commit c0d55ee
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 10 deletions.
59 changes: 59 additions & 0 deletions examples/02-syntaxes.oduraja
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This is a single line comment.

###
This is a multi
line comment
###

# A very basic log statement

Log |"Hello, World!"|

###
As you will see, a statement is a plain english sentence with zero or more parameters.
parametes are expressions/literals enclosed within pipe symbol `|`.
Each line is a single statment. And all statements are case-insensitive (but the variables used inside parameters are still case-sensitive).
Statements (except assignment) cannot begin with parameters.
Statements cannot also begin with reserved keywords like (if, for, while, else, return, continue, etc).
But it can still contain the reserved keyworkds in the middle of the statement
They also cannot contain curly-braces "{", "}", pound sign "#", or new lines.
Every statement will always return a Literal (None, Bool, Int, Float, String, Array, Map)
###

# Here are some different ways you can write the same `Log` statement in
# They all do the same as the Log statement above

log |"Hello, World!"|
LOG |"Hello, World!"|
Log|"Hello, World!"|
Log |"Hello, World!"|
Log |"Hello, World!"|


# Assignment statments: It always starts with a parameter followed by `=`
# The RHS can be a parameter or a sentence.

|a| = |(4 + 5) * 6|
log |a + 10|


# IF statments

|a| = |10|
|b| = |11|

If | a>b | {
Log |"This will never get logged!"|
}

If | a>b | {
Log |"a is greater"|
} else {
Log |"b is greater"|
}

If | b>a | {
Log |"b is greater again"|
} else {
Log |"a is greater"|
}
13 changes: 7 additions & 6 deletions src/main.pest
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ comment_line = @{ "#" ~ (!NEWLINE ~ ANY)* }
part = { (!("|" | "{" | "}" | "\r" | "\n" | "#") ~ ANY)+ }
statements = _{ stmt_if | stmt_for | stmt_while | stmt_try | stmt_define | stmt_assign | stmt_invoke | NEWLINE }
stmt_assign = { param_define ~ "=" ~ (stmt_invoke | param_invoke) }
stmt_if = { IF ~ param_invoke ~ "{" ~ statements* ~ "}" ~ stmt_else? }
stmt_else = { ELSE ~ (("{" ~ statements* ~ "}") | stmt_if) }
stmt_if = { IF ~ param_invoke ~ stmt_block ~ stmt_else? }
stmt_else = { ELSE ~ ( stmt_block | stmt_if) }
stmt_for = { FOR ~ param_define ~ IN ~ param_invoke ~ "{" ~ statements* ~ "}" }
stmt_while = { WHILE ~ param_invoke ~ "{" ~ statements* ~ "}" }
stmt_try = { TRY ~ "{" ~ statements* ~ "}" ~ (stmt_catch)? }
stmt_catch = { CATCH ~ "{" ~ statements* ~ "}" }
stmt_define = { !reserved_parts ~ part ~ (param_define | part)* ~ "{" ~ statements* ~ "}" }
stmt_while = { WHILE ~ param_invoke ~ stmt_block }
stmt_try = { TRY ~ stmt_block ~ (stmt_catch)? }
stmt_catch = { CATCH ~ stmt_block }
stmt_define = { !reserved_parts ~ part ~ (param_define | part)* ~ stmt_block }
stmt_block = { "{" ~ statements* ~ "}" }
stmt_invoke = { !reserved_parts ~ part ~ (param_invoke | part)* }
stmt_break = { BREAK }
stmt_continue = { CONTINUE }
Expand Down
43 changes: 39 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ impl Context {
}
}

/*
fn contains_variable(&self, name: &String) -> bool {
self.variables.contains_key(name)
}
*/

fn set_variable(&mut self, name: String, literal: Literal) -> Option<Literal> {
self.variables.insert(name, literal)
Expand Down Expand Up @@ -361,6 +363,38 @@ fn ident(pair: Pair<Rule>, globals: &mut Context) -> LiteralResult {
globals.get_variable(&ident)
}

fn stmt_if(pair: Pair<Rule>, globals: &mut Context) -> LiteralResult {
let mut inner = pair.clone().into_inner();
let condition = inner
.next()
.ok_or(ORErr::ParsingError("Getting condition failed".into()))?;
let block = inner
.next()
.ok_or(ORErr::ParsingError("Getting true block failed".into()))?;
let condition = oduraja(condition, globals)?;
if let Literal::Bool(is_true) = condition {
if is_true {
oduraja(block, globals)
} else {
match inner.next() {
Some(block) => oduraja(block, globals),
None => no_op(pair, globals),
}
}
} else {
Err(ORErr::OperationIncompatibleError(
"The conditional expression in `If` should always evaluvate to boolean value".into(),
))
}
}
fn stmt_block(pair: Pair<Rule>, globals: &mut Context) -> LiteralResult {
let block = pair
.into_inner()
.next()
.ok_or(ORErr::ParsingError("Getting else block failed".into()))?;
oduraja(block, globals)
}

fn oduraja(pair: Pair<Rule>, globals: &mut Context) -> LiteralResult {
let op = match pair.as_rule() {
Rule::EOI => no_op,
Expand Down Expand Up @@ -424,8 +458,8 @@ fn oduraja(pair: Pair<Rule>, globals: &mut Context) -> LiteralResult {
Rule::WHILE => todo!(),
Rule::TRY => todo!(),
Rule::CATCH => todo!(),
Rule::stmt_if => todo!(),
Rule::stmt_else => todo!(),
Rule::stmt_if => stmt_if,
Rule::stmt_else => stmt_block,
Rule::reserved_parts => todo!(),
Rule::IN => todo!(),
Rule::stmt_for => todo!(),
Expand All @@ -436,13 +470,14 @@ fn oduraja(pair: Pair<Rule>, globals: &mut Context) -> LiteralResult {
Rule::stmt_continue => todo!(),
Rule::stmt_return => todo!(),
Rule::primary => todo!(),
Rule::seperator => todo!(),
Rule::seperator => no_op,
Rule::stmt_block => stmt_block,
};
op(pair, globals)
}

fn main() {
let source = read_to_string("examples/01-expressions.oduraja").unwrap();
let source = read_to_string("examples/02-syntaxes.oduraja").unwrap();
match parser::Parser::parse(Rule::oduraja, &source) {
Ok(tree) => {
let mut context = Context::default();
Expand Down

0 comments on commit c0d55ee

Please sign in to comment.