Refactor AST location
This commit is contained in:
parent
c0b5dde9cf
commit
94f0b0c92d
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
target
|
@ -1,5 +1,5 @@
|
||||
use super::Transpilable;
|
||||
use crate::ast_types::Binding;
|
||||
use crate::syntax::ast::Binding;
|
||||
|
||||
impl Transpilable for Binding {
|
||||
/// Transpiles val and var bindings into JS.
|
||||
@ -22,7 +22,7 @@ impl Transpilable for Binding {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ast_types::{Binding, Expression, ValBinding};
|
||||
use crate::syntax::ast::{Binding, Expression, ValBinding};
|
||||
|
||||
#[test]
|
||||
fn binding_should_transpile() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::Transpilable;
|
||||
use crate::ast_types::Expression;
|
||||
use crate::syntax::ast::Expression;
|
||||
|
||||
impl Transpilable for Expression {
|
||||
/// Transpiles an Expression to JS
|
||||
@ -24,7 +24,7 @@ impl Transpilable for Expression {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ast_types::Expression;
|
||||
use crate::syntax::ast::Expression;
|
||||
|
||||
#[test]
|
||||
fn should_transpile_number() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::ast_types::ModuleAST;
|
||||
use crate::syntax::ast::ModuleAST;
|
||||
|
||||
mod binding;
|
||||
mod expression;
|
||||
@ -25,7 +25,7 @@ mod tests {
|
||||
fn should_codegen_1() {
|
||||
let input = String::from("val id = 322");
|
||||
let tokens = lexic::get_tokens(&input).unwrap();
|
||||
let mut ast = syntax::construct_ast(&tokens).unwrap();
|
||||
let ast = syntax::construct_ast(&tokens).unwrap();
|
||||
|
||||
let out_str = codegen(&ast);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::Transpilable;
|
||||
use crate::ast_types::ModuleAST;
|
||||
use crate::syntax::ast::ModuleAST;
|
||||
|
||||
impl Transpilable for ModuleAST {
|
||||
/// Transpiles the whole AST into JS, using this same trait on the
|
||||
@ -18,7 +18,7 @@ impl Transpilable for ModuleAST {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ast_types::{Binding, Expression, ValBinding};
|
||||
use crate::syntax::ast::{Binding, Expression, ValBinding};
|
||||
|
||||
#[test]
|
||||
fn module_ast_should_transpile() {
|
||||
|
@ -94,7 +94,7 @@ fn get_line(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
error_handling::{MistiError, PrintableError, SyntaxError},
|
||||
error_handling::{MistiError, PrintableError},
|
||||
lexic::get_tokens,
|
||||
syntax::construct_ast,
|
||||
};
|
||||
|
109
src/lexic/token.rs
Executable file
109
src/lexic/token.rs
Executable file
@ -0,0 +1,109 @@
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum TokenType {
|
||||
Identifier,
|
||||
Datatype,
|
||||
Number,
|
||||
String,
|
||||
Operator,
|
||||
LeftParen,
|
||||
RightParen,
|
||||
LeftBracket,
|
||||
RightBracket,
|
||||
LeftBrace,
|
||||
RightBrace,
|
||||
Semicolon,
|
||||
Comment,
|
||||
VAR,
|
||||
VAL,
|
||||
EOF,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Token {
|
||||
pub token_type: TokenType,
|
||||
// The token as a raw string
|
||||
pub value: String,
|
||||
/// The absolute position of this token, from the
|
||||
/// start of the file
|
||||
pub position: usize,
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn get_end_position(&self) -> usize {
|
||||
self.position + self.value.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn new_eof(position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::EOF,
|
||||
value: String::from(""),
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_number(value: String, position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::Number,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_operator(value: String, position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::Operator,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(value: String, position: usize, token_type: TokenType) -> Token {
|
||||
Token {
|
||||
token_type,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_identifier(value: String, position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::Identifier,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_string(value: String, position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::String,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_semicolon(position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::Semicolon,
|
||||
value: String::from(";"),
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_datatype(value: String, position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::Datatype,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_comment(value: String, position: usize) -> Token {
|
||||
Token {
|
||||
token_type: TokenType::Comment,
|
||||
value,
|
||||
position,
|
||||
}
|
||||
}
|
||||
}
|
@ -8,8 +8,6 @@ mod file;
|
||||
mod syntax;
|
||||
// Module to handle syntactic analysis
|
||||
mod lexic;
|
||||
// Defines the AST
|
||||
mod ast_types;
|
||||
// Transforms an AST to JS
|
||||
mod codegen;
|
||||
mod utils;
|
||||
|
@ -1,61 +0,0 @@
|
||||
/// Represents a qualified datatype of the compiler.
|
||||
///
|
||||
/// A datatype is composed of a path, e.g. `base.Str`, `base.Num`
|
||||
#[derive(PartialEq)]
|
||||
pub struct Datatype {
|
||||
t: String,
|
||||
}
|
||||
|
||||
impl Datatype {
|
||||
pub fn new(t: String) -> Datatype {
|
||||
Datatype { t }
|
||||
}
|
||||
|
||||
pub fn str() -> Datatype {
|
||||
Datatype {
|
||||
t: String::from("base.Str"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num() -> Datatype {
|
||||
Datatype {
|
||||
t: String::from("base.Num"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bool() -> Datatype {
|
||||
Datatype {
|
||||
t: String::from("base.Bool"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone(&self) -> Datatype {
|
||||
Datatype { t: self.t.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Datatype;
|
||||
|
||||
#[test]
|
||||
fn should_create_datatype() {
|
||||
let str = Datatype::new(String::from("base.Str"));
|
||||
assert_eq!("base.Str", str.t);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_create_primitive_datatypes() {
|
||||
assert_eq!("base.Str", Datatype::str().t);
|
||||
assert_eq!("base.Num", Datatype::num().t);
|
||||
assert_eq!("base.Bool", Datatype::bool().t);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_compare() {
|
||||
let s1 = Datatype::str();
|
||||
let s2 = Datatype::str();
|
||||
|
||||
assert_eq!(true, (s1 == s2));
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
# Semantic analysis
|
||||
|
||||
## Label checking
|
||||
|
||||
- Over all the bindings:
|
||||
- Resolve references with the Symbol table
|
||||
- If valid, insert reference into Symbol table
|
||||
|
||||
## Type checking
|
||||
|
||||
TODO
|
||||
|
||||
## Flow control check
|
||||
|
||||
TODO
|
@ -1,101 +0,0 @@
|
||||
use super::ast_types::{Binding, ModuleAST};
|
||||
use super::symbol_table::SymbolTable;
|
||||
|
||||
mod datatype;
|
||||
mod type_check;
|
||||
|
||||
use type_check::Typed;
|
||||
|
||||
pub use datatype::Datatype;
|
||||
|
||||
/// Checks the AST. In the future should return a list of errors.
|
||||
pub fn check_ast<'a>(ast: &'a ModuleAST, symbol_table: &'a mut SymbolTable) {
|
||||
for binding in ast.bindings.iter() {
|
||||
match binding {
|
||||
Binding::Val(b) => {
|
||||
let datatype = b.expression.t(symbol_table);
|
||||
let identifier = b.identifier;
|
||||
|
||||
// TODO: check datatype of a explicit datatype, e.g. `Str val x = 322`
|
||||
|
||||
symbol_table.insert(identifier.as_str(), datatype);
|
||||
}
|
||||
Binding::Var(b) => {
|
||||
let datatype = b.expression.t(symbol_table);
|
||||
let identifier = b.identifier;
|
||||
|
||||
// TODO: check datatype of a explicit datatype, e.g. `Str val x = 322`
|
||||
|
||||
symbol_table.insert(identifier.as_str(), datatype);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod t {
|
||||
use crate::ast_types::Expression;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_insert_into_symbol_table() {
|
||||
let s1 = String::from("id");
|
||||
let s2 = String::from("322");
|
||||
let binding = Binding::Val(crate::ast_types::ValBinding {
|
||||
datatype: None,
|
||||
identifier: &s1,
|
||||
expression: Expression::Number(&s2),
|
||||
});
|
||||
|
||||
let mut table = SymbolTable::new();
|
||||
|
||||
check_ast(
|
||||
&ModuleAST {
|
||||
bindings: vec![binding],
|
||||
},
|
||||
&mut table,
|
||||
);
|
||||
|
||||
assert!(table.has_id(&String::from("id")));
|
||||
assert!(table.check_type(&String::from("id"), Datatype::num()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_insert_id_reference() {
|
||||
let s1 = String::from("id");
|
||||
let s2 = String::from("322");
|
||||
let binding = Binding::Val(crate::ast_types::ValBinding {
|
||||
datatype: None,
|
||||
identifier: &s1,
|
||||
expression: Expression::Number(&s2),
|
||||
});
|
||||
|
||||
let mut table = SymbolTable::new();
|
||||
|
||||
check_ast(
|
||||
&ModuleAST {
|
||||
bindings: vec![binding],
|
||||
},
|
||||
&mut table,
|
||||
);
|
||||
|
||||
let s1 = String::from("id2");
|
||||
let s2 = String::from("id");
|
||||
let binding = Binding::Val(crate::ast_types::ValBinding {
|
||||
datatype: None,
|
||||
identifier: &s1,
|
||||
expression: Expression::Identifier(&s2),
|
||||
});
|
||||
|
||||
check_ast(
|
||||
&ModuleAST {
|
||||
bindings: vec![binding],
|
||||
},
|
||||
&mut table,
|
||||
);
|
||||
|
||||
assert!(table.has_id(&String::from("id2")));
|
||||
assert!(table.check_type(&String::from("id2"), Datatype::num()));
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
use crate::{ast_types::Expression, symbol_table::SymbolTable};
|
||||
|
||||
use super::datatype::Datatype;
|
||||
|
||||
pub trait Typed<'a> {
|
||||
fn t(&self, symbol_table: &'a mut SymbolTable) -> Datatype;
|
||||
}
|
||||
|
||||
impl<'a> Typed<'a> for Expression<'a> {
|
||||
/// Returns the Datatype of this Expression
|
||||
fn t(&self, symbol_table: &'a mut SymbolTable) -> Datatype {
|
||||
match self {
|
||||
Expression::Number(_) => Datatype::num(),
|
||||
Expression::String(_) => Datatype::str(),
|
||||
Expression::Boolean(_) => Datatype::bool(),
|
||||
Expression::Identifier(id) => {
|
||||
let res = symbol_table
|
||||
.get_type(id)
|
||||
.expect("SEMANTIC: identifier doesn't exist in Symbol table");
|
||||
res.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod t {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_get_type_of_primitives() {
|
||||
let mut t = SymbolTable::new();
|
||||
|
||||
let s = String::from("322");
|
||||
let exp = Expression::Number(&s);
|
||||
let datatype = exp.t(&mut t);
|
||||
|
||||
assert!(datatype == Datatype::num());
|
||||
|
||||
let s = String::from("hello");
|
||||
let exp = Expression::String(&s);
|
||||
let datatype = exp.t(&mut t);
|
||||
|
||||
assert!(datatype == Datatype::str());
|
||||
|
||||
let exp = Expression::Boolean(true);
|
||||
let datatype = exp.t(&mut t);
|
||||
|
||||
assert!(datatype == Datatype::bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shold_get_type_of_existing_id() {
|
||||
let mut table = SymbolTable::new();
|
||||
table.insert("my_number", Datatype::num());
|
||||
|
||||
let id = String::from("my_number");
|
||||
let exp = Expression::Identifier(&id);
|
||||
|
||||
assert!(exp.t(&mut table) == Datatype::num());
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use super::ast_types::{Binding, ValBinding, VarBinding};
|
||||
use super::ast::{Binding, ValBinding, VarBinding};
|
||||
use super::{expression, SyntaxResult};
|
||||
use crate::error_handling::SyntaxError;
|
||||
use crate::lexic::token::{Token, TokenType};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::ast_types::Expression;
|
||||
use super::ast::Expression;
|
||||
use crate::lexic::token::{Token, TokenType};
|
||||
|
||||
/// An expression can be:
|
||||
|
@ -1,13 +1,12 @@
|
||||
use crate::ast_types::Binding;
|
||||
use crate::error_handling::{MistiError, SyntaxError};
|
||||
|
||||
mod binding;
|
||||
mod expression;
|
||||
pub mod ast;
|
||||
|
||||
use super::ast_types;
|
||||
use ast::{Binding, ModuleAST};
|
||||
use crate::lexic::token::Token;
|
||||
|
||||
use ast_types::ModuleAST;
|
||||
|
||||
pub enum SyntaxResult {
|
||||
///
|
||||
@ -24,7 +23,7 @@ pub enum SyntaxResult {
|
||||
/// Constructs the Misti AST from a vector of tokens
|
||||
pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
|
||||
let _token_amount = tokens.len();
|
||||
let mut current_pos = 0;
|
||||
let current_pos = 0;
|
||||
|
||||
match next_construct(tokens, current_pos) {
|
||||
SyntaxResult::Ok(module) => Ok(ModuleAST {
|
||||
|
@ -4,6 +4,7 @@ pub enum Result3<T> {
|
||||
None,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> Result3<T> {
|
||||
pub fn unwrap(&self) -> &T {
|
||||
match self {
|
||||
|
Loading…
Reference in New Issue
Block a user