begin to work on checking the grammar, context and so on

parent f583faa6
Pipeline #138 passed with stages
in 6 minutes and 49 seconds
......@@ -3,3 +3,4 @@
**/*.rs.bk
/.idea
out.*
notes.org
......@@ -13,22 +13,66 @@ pub struct Expr {
#[derive(Debug)]
pub enum Expr_ {
ILiteral(i64),
FLiteral(f64),
SLiteral(String),
BLiteral(bool),
VarIdent(String),
Type(Type_),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Assign(Type_, String, Box<Expr>),
Print(Box<Expr>),
Return(Box<Expr>),
Func(String, Vec<Expr>, Type_, Vec<Expr>), // name, vec Arg, type, vec expressions
FuncCall(String, Vec<Expr>), // name, vec arguments
Arg(Type_, String), // type, name
// Ident, Type, Value, Other
ILiteral {
val: i32,
},
FLiteral {
val: f32,
},
SLiteral {
val: String,
},
BLiteral {
val: bool,
},
VarIdent {
ident: String,
},
Type {
t: Type_,
},
Add {
expr1: Box<Expr>,
expr2: Box<Expr>,
},
Sub {
expr1: Box<Expr>,
expr2: Box<Expr>,
},
Mul {
expr1: Box<Expr>,
expr2: Box<Expr>,
},
Div {
expr1: Box<Expr>,
expr2: Box<Expr>,
},
Assign {
ident: String,
t: Type_,
expr: Box<Expr>,
},
Print {
expr: Box<Expr>,
},
Return {
expr: Box<Expr>,
},
Func {
ident: String,
t: Type_,
args: Vec<Expr>,
expr: Vec<Expr>,
}, // name, type, vec Arg, vec expressions
FuncCall {
ident: String,
args: Vec<Expr>,
}, // name, vec arguments
Arg {
ident: String,
t: Type_,
}, // name, type
}
#[derive(Debug, Clone)]
......
use crate::ast::Program;
use crate::ast::Expr_;
fn check_main(program: &Program) -> bool {
let mut has_main = false;
for expression in &program.stmts {
match &expression.node {
Expr_::Func {
ident: identifier,
t: _,
args: _,
expr: _,
} => {
if identifier == "main" {
has_main = true
}
}
_ => {}
}
}
has_main
}
pub fn check_grammar(program: &Program) -> bool {
if !check_main(&program) {
panic!("No main function detected. Compilation aborted.");
}
true
}
......@@ -16,8 +16,8 @@ pub enum Token {
VarType(Type_), // type
Integer(i64), // Integer up to i64
Float(f64), // Float up to i64
Integer(i32), // Integer up to i32
Float(f32), // Float up to i32
Str(String), // strings
Bool(bool), // bools (created with `True` or `False`)
......
......@@ -6,21 +6,16 @@ use std::io::Read;
mod ast;
mod lexer;
mod parser;
mod grammar;
fn main() {
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
// Debug
// let lexer = lexer::Lexer::new(&s);
// for tok in lexer {
// eprintln!("Token: {:?}", tok);
// }
let lexer = lexer::Lexer::new(&s);
let program = parser::parse(lexer).unwrap();
for expression in &program.stmts {
eprintln!("{:?}", expression);
eprintln!("{:?}\n", expression);
}
grammar::check_grammar(&program);
}
......@@ -16,68 +16,99 @@ parser! {
// a program is a collection of statements
program: Program {
// <statements>
statements[s] => Program { stmts: s }
}
// statements are an array of expressions
// returns an array of statements
// <statements> <assign>;
statements: Vec<Expr> {
=> vec![],
// <statements> def <Ident> (<argsdef>) { <statements> }
statements[mut st] Def Ident(func) LParen argsdef[arguments] RParen LCBracket statements[body] RCBracket => {
let function = Expr {
span: span!(),
node: Expr_::Func(func, arguments, Type_::Void, body),
node: Expr_::Func{
ident:func,
t:Type_::Void,
args:arguments,
expr:body,
},
};
st.push(function);
st
},
// <statements> def <Ident> (<argsdef>) -> <VarType> { <statements> }
statements[mut st] Def Ident(func) LParen argsdef[arguments] RParen Arrow VarType(vartype) LCBracket statements[body] RCBracket => {
let function = Expr {
span: span!(),
node: Expr_::Func(func, arguments, vartype, body),
node: Expr_::Func{
ident:func, t:vartype, args:arguments, expr:body,
},
};
st.push(function);
st
},
// <statements> <assign>;
statements[mut st] assign[e] Semi => {
st.push(e);
st
}
}
// Returns array of function’s arguments declarations
argsdef: Vec<Expr> {
=> vec![],
// <argsdef> <Ident> : <VarType> ,
argsdef[mut st] Ident(varname) Colon VarType(vartype) Comma => {
let argument = Expr {
span: span!(),
node: Expr_::Arg(vartype, varname),
node: Expr_::Arg{
ident:varname, t:vartype,
},
};
st.push(argument);
st
}
// <argsdef> <Ident> : <VarType>
argsdef[mut st] Ident(varname) Colon VarType(vartype) => {
let argument = Expr {
span: span!(),
node: Expr_::Arg(vartype, varname),
node: Expr_::Arg{
ident:varname,
t: vartype,
},
};
st.push(argument);
st
}
}
// Returns array of arguments in fuction call
args: Vec<Expr> {
=> vec![],
// <args> <Ident> ,
args[mut st] Ident(varname) Comma => {
st.push(Expr {
span: span!(),
node: Expr_::VarIdent(varname),
node: Expr_::VarIdent{
ident: varname,
},
});
st
},
// <args> <Ident>
args[mut st] Ident(varname) => {
st.push(Expr {
span: span!(),
node: Expr_::VarIdent(varname),
node: Expr_::VarIdent{
ident:varname,
},
});
st
}
......@@ -88,17 +119,26 @@ parser! {
// <id var> : <type> = <elem assign>
Ident(var) Colon VarType(vartype) Equals assign[rhs] => Expr {
span: span!(),
node: Expr_::Assign(vartype, var, Box::new(rhs)),
node: Expr_::Assign{
ident:var, t:vartype, expr:Box::new(rhs),
},
},
// print (<assign>)
Print LParen assign[a] RParen => Expr {
span: span!(),
node: Expr_::Print(Box::new(a)),
node: Expr_::Print{
expr:Box::new(a),
},
},
// return <term>
Return term[t] => Expr {
span: span!(),
node: Expr_::Return(Box::new(t)),
node: Expr_::Return{
expr: Box::new(t),
},
},
// <term>
term[t] => t,
......@@ -108,32 +148,46 @@ parser! {
// <func>(<arguments>)
Ident(func) LParen args[arguments] RParen => Expr {
span: span!(),
node: Expr_::FuncCall(func, arguments),
node: Expr_::FuncCall{
ident:func, args:arguments,
},
},
// <elem> + <elem>
term[lhs] Plus fact[rhs] => Expr {
span: span!(),
node: Expr_::Add(Box::new(lhs), Box::new(rhs)),
node: Expr_::Add{
expr1:Box::new(lhs), expr2:Box::new(rhs),
},
},
// <elem> - <elem>
term[lhs] Minus fact[rhs] => Expr {
span: span!(),
node: Expr_::Sub(Box::new(lhs), Box::new(rhs)),
node: Expr_::Sub{
expr1:Box::new(lhs), expr2:Box::new(rhs),
},
},
// <elem> ([*/] <elem>)
fact[x] => x
}
fact: Expr {
// <fact> * <atom>
// <fact> * <atom> (précédence à droite)
fact[lhs] Star atom[rhs] => Expr {
span: span!(),
node: Expr_::Mul(Box::new(lhs), Box::new(rhs)),
node: Expr_::Mul{
expr1:Box::new(lhs), expr2:Box::new(rhs),
},
},
// <fact> / <atom>
// <fact> / <atom> (précédence à droite)
fact[lhs] Slash atom[rhs] => Expr {
span: span!(),
node: Expr_::Div(Box::new(lhs), Box::new(rhs)),
node: Expr_::Div{
expr1:Box::new(lhs), expr2:Box::new(rhs),
},
},
// <elem>
atom[x] => x
......@@ -144,30 +198,31 @@ parser! {
// Type of variable
VarType(i) => Expr {
span: span!(),
node: Expr_::Type(i),
node: Expr_::Type{t:i},
},
// Identifier (String)
Ident(i) => Expr {
span: span!(),
node: Expr_::VarIdent(i),
node: Expr_::VarIdent{ident: i},
},
// i un integer
Integer(i) => Expr {
span: span!(),
node: Expr_::ILiteral(i),
node: Expr_::ILiteral{val: i},
},
// <i> un float
Float(i) => Expr {
span: span!(),
node: Expr_::FLiteral(i),
node: Expr_::FLiteral{val: i},
},
// <i> un string
Str(i) => Expr {
span: span!(),
node: Expr_::SLiteral(i),
node: Expr_::SLiteral{val: i},
},
Bool(i) => Expr {
span: span!(),
node: Expr_::BLiteral(i),
node: Expr_::BLiteral{val: i},
},
// (<atom>)
LParen assign[a] RParen => a
......
a: int = 10;
def main() -> int {
a : float = .45;
_a2 : float = 6.15;
......@@ -11,12 +13,14 @@ def main() -> int {
printHello(d, b, a);
return 0;
}
def plus() -> int {
a: int = 10;
b: int = 5;
c: int = a + b + c;
return c;
}
# an argument must be `<identifier>: <type>,`
def printHello(b: str, c: int, d: float) {
a: float = "Hello World!\n";
......
a: int = 10;
def plus() -> int {
a: int = 10;
b: int = 5;
c: int = a + b + c;
return c;
}
# an argument must be `<identifier>: <type>,`
def printHello(b: str, c: int, d: float) {
a: float = "Hello World!\n";
print(a);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment