Change grammar to incorporate binary operators
This commit is contained in:
parent
c02e1c1f8e
commit
c045721f46
@ -2,10 +2,8 @@
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- Parse multiple statements
|
|
||||||
- Parse binary operators
|
- Parse binary operators
|
||||||
- Parse more complex bindings
|
- Parse more complex bindings
|
||||||
- Parse block of code
|
|
||||||
- Watch mode
|
- Watch mode
|
||||||
- Improve error messages
|
- Improve error messages
|
||||||
- Parse other language constructions
|
- Parse other language constructions
|
||||||
@ -17,6 +15,8 @@
|
|||||||
|
|
||||||
|
|
||||||
## v0.0.8
|
## v0.0.8
|
||||||
|
|
||||||
|
- Parse block of code
|
||||||
- Parse multiple statements inside a block
|
- Parse multiple statements inside a block
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ impl Transpilable for Expression {
|
|||||||
Expression::Boolean(value) => String::from(if *value { "true" } else { "false" }),
|
Expression::Boolean(value) => String::from(if *value { "true" } else { "false" }),
|
||||||
Expression::Identifier(value) => format!("{}", *value),
|
Expression::Identifier(value) => format!("{}", *value),
|
||||||
Expression::FunctionCall(_) => todo!("FunctionCall codegen is not implemented yet"),
|
Expression::FunctionCall(_) => todo!("FunctionCall codegen is not implemented yet"),
|
||||||
|
Expression::BinaryOperator(_, _, _) => {
|
||||||
|
todo!("BinaryOperator codegen is not implemented yet")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,6 @@ pub enum Expression {
|
|||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Identifier(Box<String>),
|
Identifier(Box<String>),
|
||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
|
BinaryOperator(Box<Expression>, Box<Expression>, Box<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
src/syntax/expression/equality.rs
Normal file
8
src/syntax/expression/equality.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::{syntax::{ParseResult, ast::Expression}, lexic::token::Token};
|
||||||
|
|
||||||
|
|
||||||
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
||||||
|
//
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
36
src/syntax/expression/mod.rs
Normal file
36
src/syntax/expression/mod.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use super::{ast::Expression, functions::function_call, ParseResult};
|
||||||
|
use crate::lexic::token::{Token, TokenType};
|
||||||
|
|
||||||
|
mod equality;
|
||||||
|
mod primary;
|
||||||
|
|
||||||
|
/// Expression is defined in the grammar.
|
||||||
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
||||||
|
match function_call::try_parse(tokens, pos) {
|
||||||
|
super::ParseResult::Ok(function_call, next_pos) => {
|
||||||
|
return ParseResult::Ok::<_, ()>(Expression::FunctionCall(function_call), next_pos)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
match tokens.get(pos) {
|
||||||
|
Some(token) => match token.token_type {
|
||||||
|
TokenType::Number => {
|
||||||
|
ParseResult::Ok(Expression::Number(Box::new(token.value.clone())), pos + 1)
|
||||||
|
}
|
||||||
|
TokenType::String => {
|
||||||
|
ParseResult::Ok(Expression::String(Box::new(token.value.clone())), pos + 1)
|
||||||
|
}
|
||||||
|
TokenType::Identifier if token.value == "true" || token.value == "false" => {
|
||||||
|
ParseResult::Ok(Expression::Boolean(token.value == "true"), pos + 1)
|
||||||
|
}
|
||||||
|
TokenType::Identifier => ParseResult::Ok(
|
||||||
|
Expression::Identifier(Box::new(token.value.clone())),
|
||||||
|
pos + 1,
|
||||||
|
),
|
||||||
|
_ => ParseResult::Unmatched,
|
||||||
|
},
|
||||||
|
None => ParseResult::Unmatched,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,20 +1,23 @@
|
|||||||
use super::{ast::Expression, functions::function_call, ParseResult};
|
use crate::{
|
||||||
use crate::lexic::token::{Token, TokenType};
|
lexic::token::{Token, TokenType},
|
||||||
|
syntax::{ast::Expression, ParseResult},
|
||||||
|
};
|
||||||
|
|
||||||
/// An expression can be:
|
/// This grammar may not be up to date. Refer to the spec for the latest grammar.
|
||||||
///
|
///
|
||||||
/// - A number
|
/// ```ebnf
|
||||||
/// - A string
|
/// primary = number | string | boolean | identifier | ("(", expression, ")");
|
||||||
/// - A boolean
|
/// ```
|
||||||
/// - An identifier
|
|
||||||
/// - A function call
|
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
||||||
|
/*
|
||||||
|
TODO: Incorporate function_call into the grammar, figure out its precedence.
|
||||||
match function_call::try_parse(tokens, pos) {
|
match function_call::try_parse(tokens, pos) {
|
||||||
super::ParseResult::Ok(function_call, next_pos) => {
|
super::ParseResult::Ok(function_call, next_pos) => {
|
||||||
return ParseResult::Ok::<_, ()>(Expression::FunctionCall(function_call), next_pos)
|
return ParseResult::Ok::<_, ()>(Expression::FunctionCall(function_call), next_pos)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
Some(token) => match token.token_type {
|
Some(token) => match token.token_type {
|
||||||
@ -31,6 +34,7 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()>
|
|||||||
Expression::Identifier(Box::new(token.value.clone())),
|
Expression::Identifier(Box::new(token.value.clone())),
|
||||||
pos + 1,
|
pos + 1,
|
||||||
),
|
),
|
||||||
|
// TODO: Parse parenthesized expressions.
|
||||||
_ => ParseResult::Unmatched,
|
_ => ParseResult::Unmatched,
|
||||||
},
|
},
|
||||||
None => ParseResult::Unmatched,
|
None => ParseResult::Unmatched,
|
@ -9,6 +9,7 @@ A module is (commonly) a single source file.
|
|||||||
module = top level declaration*
|
module = top level declaration*
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Top level declaration
|
## Top level declaration
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
@ -19,18 +20,10 @@ top level declaration = function declaration
|
|||||||
## Function declaration
|
## Function declaration
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
function declaration = "fun", identifier, params list, return type?, block
|
function declaration = "fun", identifier, params list, return type?, block;
|
||||||
```
|
|
||||||
|
|
||||||
### Params list
|
params list = "(", ")";
|
||||||
|
|
||||||
```ebnf
|
|
||||||
params list = "(", ")"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Return type
|
|
||||||
|
|
||||||
```ebnf
|
|
||||||
return type = ;
|
return type = ;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -38,28 +31,63 @@ return type = ;
|
|||||||
### Block
|
### Block
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
block = "{", (statement, (new line, statement)*)?, "}"
|
block = "{", (statement, (new line, statement)*)?, "}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Statement
|
### Statement
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
statement = function call | binding
|
statement = binding
|
||||||
|
| function call
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Function call
|
## Function call
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
function call = identifier, arguments list
|
function call = identifier, arguments list;
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Arguments list
|
|
||||||
|
|
||||||
```ebnf
|
|
||||||
arguments list = "(", ")"
|
arguments list = "(", ")"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Binding
|
||||||
|
|
||||||
|
```ebnf
|
||||||
|
binding = ("val" | "var"), identifier, "=", expression
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Operator precedence
|
||||||
|
|
||||||
|
From highest to lowest:
|
||||||
|
|
||||||
|
- `== !=`, left associative
|
||||||
|
- `> >= < <=`, left associative
|
||||||
|
- `- +`, left associative
|
||||||
|
- `/ *`, left associative
|
||||||
|
- `! -`, left associative
|
||||||
|
|
||||||
|
## Expression
|
||||||
|
|
||||||
|
```ebnf
|
||||||
|
expression = equality;
|
||||||
|
|
||||||
|
equality = comparison, (("==" | "!="), comparison )*;
|
||||||
|
|
||||||
|
comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
||||||
|
|
||||||
|
term = factor, (("-" | "+"), factor)*;
|
||||||
|
|
||||||
|
factor = unary, (("/" | "*"), unary)*;
|
||||||
|
|
||||||
|
unary = ("!" | "-"), expression
|
||||||
|
| primary;
|
||||||
|
|
||||||
|
primary = number | string | boolean | identifier | ("(", expression, ")");
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user