feat: Implement eval methods for expressions

This commit is contained in:
Lucàs
2024-10-26 22:40:50 +02:00
parent b493c77d70
commit 9e201e8d16
28 changed files with 638 additions and 325 deletions
+13 -5
View File
@@ -1,8 +1,15 @@
open Syntax.Roots
let get_lexbuf () =
if Array.length Sys.argv > 1 then
let file_path = Sys.argv.(1) in
let file_stream = open_in file_path in
Lexing.from_channel file_stream
else Lexing.from_channel stdin
let () = let () =
let file_path = Sys.argv.(1) in let lexbuf = get_lexbuf () in
let file_stream = open_in file_path in let ast : program =
let lexbuf = Lexing.from_channel file_stream in
let ast =
try Analyzer.Parser.main Analyzer.Lexer.token lexbuf with try Analyzer.Parser.main Analyzer.Lexer.token lexbuf with
| Analyzer.Lexer.Error c -> | Analyzer.Lexer.Error c ->
let file_name = lexbuf.lex_curr_p.pos_fname let file_name = lexbuf.lex_curr_p.pos_fname
@@ -20,4 +27,5 @@ let () =
file_name line_num col_num "Erreur syntaxique" "Syntaxe incorrecte"; file_name line_num col_num "Erreur syntaxique" "Syntaxe incorrecte";
exit 1 exit 1
in in
Printf.printf "%s\n" (Syntax.SourceFiles.pp_source_files ast) let _ = ast#check_type in
Printf.printf "%s\n" (Syntax.Literals.string_of_literal_value ast#eval)
+2 -2
View File
@@ -1,7 +1,7 @@
(library (library
(name Analyzer) (name analyzer)
(modules lexer parser) (modules lexer parser)
(libraries Syntax)) (libraries syntax))
(menhir (menhir
(modules parser)) (modules parser))
+12 -3
View File
@@ -33,7 +33,8 @@ rule token = parse
| '+' { PLUS } | '+' { PLUS }
| '-' { MINUS } | '-' { MINUS }
| '*' { TIMES } | '*' { TIMES }
| '/' { DIV } | '/' { DIVIDE }
| "=" { EQUAL }
| "==" { EQUAL_EQUAL } | "==" { EQUAL_EQUAL }
| "!=" { NOT_EQUAL } | "!=" { NOT_EQUAL }
| "<" { LESS_THAN } | "<" { LESS_THAN }
@@ -43,16 +44,24 @@ rule token = parse
| "&&" { AMPERSAND_AMPERSAND } | "&&" { AMPERSAND_AMPERSAND }
| "||" { BAR_BAR } | "||" { BAR_BAR }
| "!" { EXCLAMATION } | "!" { EXCLAMATION }
| ":" { COLON }
(* Keywords *) (* Keywords *)
| "vrai" { BOOLEAN(true) } | "vrai" { BOOLEAN(true) }
| "faux" { BOOLEAN(false) } | "faux" { BOOLEAN(false) }
| "var" { VAR }
| "entier" { INTEGER_TYPE }
| "flottant" { FLOAT_TYPE }
| "booleen" { BOOLEAN_TYPE }
| "chaine" { STRING_TYPE }
| "caractere" { CHARACTER_TYPE }
| "nul" { NULL_TYPE }
| "vide" { VOID_TYPE }
(* Literals *) (* Literals *)
| interger as i { INT (int_of_string i) } | interger as i { INTEGER (int_of_string i) }
| float as f { FLOAT (float_of_string f) } | float as f { FLOAT (float_of_string f) }
| '"' { Buffer.clear buffer; STRING(string lexbuf) } | '"' { Buffer.clear buffer; STRING(string lexbuf) }
| "''" { NULL }
| "'\\''" { CHARACTER '\'' } | "'\\''" { CHARACTER '\'' }
| "'\\n'" { CHARACTER '\n' } | "'\\n'" { CHARACTER '\n' }
| "'\\t'" { CHARACTER '\t' } | "'\\t'" { CHARACTER '\t' }
+50 -29
View File
@@ -2,18 +2,28 @@
open Syntax open Syntax
%} %}
%token <int> INT %token <int> INTEGER
%token <float> FLOAT %token <float> FLOAT
%token <char> CHARACTER %token <char> CHARACTER
%token <bool> BOOLEAN %token <bool> BOOLEAN
%token <string> STRING %token <string> STRING
%token <string> IDENTIFIER %token <string> IDENTIFIER
%token NULL
%token EQUAL "="
%token VAR
%token INTEGER_TYPE
%token FLOAT_TYPE
%token BOOLEAN_TYPE
%token STRING_TYPE
%token CHARACTER_TYPE
%token NULL_TYPE
%token VOID_TYPE
%token PLUS "+" %token PLUS "+"
%token MINUS "-" %token MINUS "-"
%token TIMES "*" %token TIMES "*"
%token DIV "/" %token DIVIDE "/"
%token EQUAL_EQUAL "==" %token EQUAL_EQUAL "=="
%token NOT_EQUAL "!=" %token NOT_EQUAL "!="
%token LESS_THAN "<" %token LESS_THAN "<"
@@ -25,6 +35,7 @@ open Syntax
%token EXCLAMATION "!" %token EXCLAMATION "!"
%token SEMICOLON ";" %token SEMICOLON ";"
%token COLON ":"
%token LPAREN "(" %token LPAREN "("
%token RPAREN ")" %token RPAREN ")"
@@ -36,49 +47,59 @@ open Syntax
%nonassoc UMINUS %nonassoc UMINUS
%start <SourceFiles.source_files> main %start <Roots.program> main
%% %%
main: main:
| statements EOF { SourceFiles.SourceFile $1 } | statements EOF { new Roots.program $1 }
statements: statements:
| statement ";" { $1 } | statement ";" { $1 }
| statement ";" statements { Statements.SequenceStatement ($1, $3) } | statement ";" statements { new Statements.sequence $1 $3 }
statement: statement:
| expression { Statements.ExpressionStatement($1) } | expression { new Statements.expression $1 }
| VAR IDENTIFIER ":" tp "=" expression { new Statements.variableDeclaration $2 $4 $6 }
expression: expression:
| literal { Expressions.Literal($1) } | literal { new Expressions.literal $1 }
| IDENTIFIER { Expressions.Identifier($1) } | IDENTIFIER { new Expressions.identifier $1 }
| unary_expression { $1 } | unary_expression { $1 }
| binary_expression { $1 } | binary_expression { $1 }
| "(" expression ")" { $2 } | "(" expression ")" { $2 }
tp:
| INTEGER_TYPE { Types.IntegerType }
| FLOAT_TYPE { Types.FloatType }
| BOOLEAN_TYPE { Types.BooleanType }
| STRING_TYPE { Types.StringType }
| CHARACTER_TYPE { Types.CharacterType }
| NULL_TYPE { Types.NullType }
| VOID_TYPE { Types.VoidType }
literal: literal:
| INT { Literals.Integer($1) } | INTEGER { new Literals.eInteger $1 }
| FLOAT { Literals.Float($1) } | FLOAT { new Literals.eFloat $1 }
| BOOLEAN { Literals.Boolean($1) } | BOOLEAN { new Literals.eBoolean $1 }
| CHARACTER { Literals.Character($1) } | CHARACTER { new Literals.eCharacter $1 }
| STRING { Literals.String($1) } | STRING { new Literals.eString $1 }
| NULL { Literals.Null } | NULL_TYPE { new Literals.eNull }
unary_expression: unary_expression:
| "-" expression %prec UMINUS { Expressions.UnaryExpression(UnaryOperators.ArithmeticNegation, $2) } | "-" expression %prec UMINUS { new Expressions.unaryOperation (new UnaryOperators.arithmeticNegation) $2 }
| "!" expression { Expressions.UnaryExpression(UnaryOperators.LogicalNegation, $2) } | "!" expression { new Expressions.unaryOperation (new UnaryOperators.logicalNegation) $2 }
binary_expression: binary_expression:
| expression "+" expression { Expressions.BinaryExpression (BinaryOperators.Add, $1, $3) } | expression "+" expression { new Expressions.binaryOperation (new BinaryOperators.add) $1 $3 }
| expression "-" expression { Expressions.BinaryExpression (BinaryOperators.Subtract, $1, $3) } | expression "-" expression { new Expressions.binaryOperation (new BinaryOperators.subtract) $1 $3 }
| expression "*" expression { Expressions.BinaryExpression (BinaryOperators.Multiply, $1, $3) } | expression "*" expression { new Expressions.binaryOperation (new BinaryOperators.multiply) $1 $3 }
| expression "/" expression { Expressions.BinaryExpression (BinaryOperators.Divide, $1, $3) } | expression "/" expression { new Expressions.binaryOperation (new BinaryOperators.divide) $1 $3 }
| expression "==" expression { Expressions.BinaryExpression (BinaryOperators.Equals, $1, $3) } | expression "==" expression { new Expressions.binaryOperation (new BinaryOperators.equals) $1 $3 }
| expression "!=" expression { Expressions.BinaryExpression (BinaryOperators.NotEquals, $1, $3) } | expression "!=" expression { new Expressions.binaryOperation (new BinaryOperators.notEquals) $1 $3 }
| expression "<" expression { Expressions.BinaryExpression (BinaryOperators.LessThan, $1, $3) } | expression "<" expression { new Expressions.binaryOperation (new BinaryOperators.lessThan) $1 $3 }
| expression "<=" expression { Expressions.BinaryExpression (BinaryOperators.LessThanEquals, $1, $3) } | expression "<=" expression { new Expressions.binaryOperation (new BinaryOperators.lessThanEquals) $1 $3 }
| expression ">" expression { Expressions.BinaryExpression (BinaryOperators.GreaterThan, $1, $3) } | expression ">" expression { new Expressions.binaryOperation (new BinaryOperators.greaterThan) $1 $3 }
| expression ">=" expression { Expressions.BinaryExpression (BinaryOperators.GreaterThanEquals, $1, $3) } | expression ">=" expression { new Expressions.binaryOperation (new BinaryOperators.greaterThanEquals) $1 $3 }
| expression "&&" expression { Expressions.BinaryExpression (BinaryOperators.And, $1, $3) } | expression "&&" expression { new Expressions.binaryOperation (new BinaryOperators.logicalAnd) $1 $3 }
| expression "||" expression { Expressions.BinaryExpression (BinaryOperators.Or, $1, $3) } | expression "||" expression { new Expressions.binaryOperation (new BinaryOperators.logicalOr) $1 $3 }
-1
View File
@@ -1 +0,0 @@
type environment = { variables : (string * Types.types) list }
+1 -1
View File
@@ -1,3 +1,3 @@
(library (library
(name Croissant) (name Croissant)
(libraries Syntax Analyzer)) (libraries syntax analyzer))
+264 -26
View File
@@ -1,27 +1,265 @@
type binary_operators = class virtual binaryOperator =
| Add object
| Subtract inherit Node.node
| Multiply method virtual check_type : Types.t * Types.t -> Types.t
| Divide
| Equals
| NotEquals
| LessThan
| LessThanEquals
| GreaterThan
| GreaterThanEquals
| And
| Or
let pp_binary_operators = function method virtual eval
| Add -> "Add" : Literals.literal_value * Literals.literal_value ->
| Subtract -> "Subtract" Literals.literal_value
| Multiply -> "Multiply" end
| Divide -> "Divide"
| Equals -> "Equals" class add =
| NotEquals -> "NotEquals" object
| LessThan -> "LessThan" inherit binaryOperator
| LessThanEquals -> "LessThanEquals" method to_string = "Add"
| GreaterThan -> "GreaterThan"
| GreaterThanEquals -> "GreaterThanEquals" method check_type (left, right) =
| And -> "And" match (left, right) with
| Or -> "Or" | Types.IntegerType, Types.IntegerType -> Types.IntegerType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| Types.StringType, Types.StringType -> Types.StringType
| _ -> raise (Failure "Add: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Int (a + b)
| `Float a, `Float b -> `Float (a +. b)
| `Float a, `Int b -> `Float (a +. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a +. b)
| `String a, `String b -> `String (a ^ b) (* Concatenation *)
| _ -> raise (Failure "Add: operands must be numbers")
end
class subtract =
object
inherit binaryOperator
method to_string = "Subtract"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.IntegerType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| _ -> raise (Failure "Subtract: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Int (a - b)
| `Float a, `Float b -> `Float (a -. b)
| `Float a, `Int b -> `Float (a -. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a -. b)
| _ -> raise (Failure "Subtract: operands must be numbers")
end
class multiply =
object
inherit binaryOperator
method to_string = "Multiply"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.FloatType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| _ -> raise (Failure "Multiply: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Float (float_of_int a *. float_of_int b)
| `Float a, `Float b -> `Float (a *. b)
| `Float a, `Int b -> `Float (a *. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a *. b)
| _ -> raise (Failure "Multiply: operands must be numbers")
end
class divide =
object
inherit binaryOperator
method to_string = "Divide"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.FloatType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| _ -> raise (Failure "Divide: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Float (float_of_int a /. float_of_int b)
| `Float a, `Float b -> `Float (a /. b)
| `Float a, `Int b -> `Float (a /. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a /. b)
| _ -> raise (Failure "Divide: operands must be numbers")
end
class equals =
object
inherit binaryOperator
method to_string = "Equals"
method check_type (left, right) =
if left = right then Types.BooleanType
else raise (Failure "Equals: operands must have the same type")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a = b)
| `Float a, `Float b -> `Bool (a = b)
| `Float a, `Int b -> `Bool (a = float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a = b)
| `String a, `String b -> `Bool (a = b)
| `Bool a, `Bool b -> `Bool (a = b)
| `Char a, `Char b -> `Bool (a = b)
| `Null, `Null -> `Bool true
| `Void, `Void -> `Bool true
| _ -> raise (Failure "Equals: operands must have the same type")
end
class notEquals =
object
inherit binaryOperator
method to_string = "NotEquals"
method check_type (left, right) =
if left = right then Types.BooleanType
else raise (Failure "Equals: operands must have the same type")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a <> b)
| `Float a, `Float b -> `Bool (a <> b)
| `Float a, `Int b -> `Bool (a <> float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a <> b)
| `String a, `String b -> `Bool (a <> b)
| `Bool a, `Bool b -> `Bool (a <> b)
| `Char a, `Char b -> `Bool (a <> b)
| `Null, `Null -> `Bool false
| `Void, `Void -> `Bool false
| _ -> raise (Failure "NotEquals: operands must have the same type")
end
class lessThan =
object
inherit binaryOperator
method to_string = "LessThan"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "LessThan: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a < b)
| `Float a, `Float b -> `Bool (a < b)
| `Float a, `Int b -> `Bool (a < float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a < b)
| _ -> raise (Failure "LessThan: operands must be numbers")
end
class lessThanEquals =
object
inherit binaryOperator
method to_string = "LessThanEquals"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "LessThanEquals: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a <= b)
| `Float a, `Float b -> `Bool (a <= b)
| `Float a, `Int b -> `Bool (a <= float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a <= b)
| _ -> raise (Failure "LessThanEquals: operands must be numbers")
end
class greaterThan =
object
inherit binaryOperator
method to_string = "GreaterThan"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "GreaterThan: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a > b)
| `Float a, `Float b -> `Bool (a > b)
| `Float a, `Int b -> `Bool (a > float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a > b)
| _ -> raise (Failure "GreaterThan: operands must be numbers")
end
class greaterThanEquals =
object
inherit binaryOperator
method to_string = "GreaterThanEquals"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "GreaterThanEquals: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a >= b)
| `Float a, `Float b -> `Bool (a >= b)
| `Float a, `Int b -> `Bool (a >= float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a >= b)
| _ -> raise (Failure "GreaterThanEquals: operands must be numbers")
end
class logicalAnd =
object
inherit binaryOperator
method to_string = "And"
method check_type (left, right) =
match (left, right) with
| Types.BooleanType, Types.BooleanType -> Types.BooleanType
| _ -> raise (Failure "And: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Bool a, `Bool b -> `Bool (a && b)
| _ -> raise (Failure "And: operands must be booleans")
end
class logicalOr =
object
inherit binaryOperator
method to_string = "Or"
method check_type (left, right) =
match (left, right) with
| Types.BooleanType, Types.BooleanType -> Types.BooleanType
| _ -> raise (Failure "Or: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Bool a, `Bool b -> `Bool (a || b)
| _ -> raise (Failure "Or: operands must be booleans")
end
+27
View File
@@ -0,0 +1,27 @@
class evalEnvironment =
object
val mutable env : (string, Literals.literal_value) Hashtbl.t =
Hashtbl.create 10
method add (name : string) (lit : Literals.literal_value) =
Hashtbl.add env name lit
method find (name : string) = Hashtbl.find env name
method clone : evalEnvironment =
let new_env = new evalEnvironment in
Hashtbl.iter (fun k v -> new_env#add k v) env;
new_env
end
class typeEnvironments =
object
val mutable env : (string, Types.t) Hashtbl.t = Hashtbl.create 10
method add (name : string) (tp : Types.t) = Hashtbl.add env name tp
method find (name : string) = Hashtbl.find env name
method clone : typeEnvironments =
let new_env = new typeEnvironments in
Hashtbl.iter (fun k v -> new_env#add k v) env;
new_env
end
+57 -21
View File
@@ -1,23 +1,59 @@
open Literals class virtual expression =
open UnaryOperators object
open BinaryOperators inherit Node.node
method virtual check_type : Environments.typeEnvironments -> Types.t
method virtual eval : Environments.evalEnvironment -> Literals.literal_value
end
type expressions = class literal (lit : Literals.literal) =
| Literal of literals object
| Identifier of string inherit expression
| UnaryExpression of unary_operators * expressions method to_string = "Literal(" ^ lit#to_string ^ ")"
| BinaryExpression of binary_operators * expressions * expressions method check_type _ = lit#check_type
method eval _ = lit#value
end
let rec pp_expressions = function class identifier (name : string) =
| Literal l -> object
let pp_l = pp_literals l in inherit expression
Printf.sprintf "Literal(%s)" pp_l method to_string = "Identifier(" ^ name ^ ")"
| Identifier i -> Printf.sprintf "Identifier(\"%s\")" i
| UnaryExpression (op, e) -> method check_type env =
let pp_op = pp_unary_operators op and pp_e = pp_expressions e in try env#find name
Printf.sprintf "UnaryExpression(%s, %s)" pp_op pp_e with Not_found ->
| BinaryExpression (op, e1, e2) -> raise (Failure ("Identifier '" ^ name ^ "' not found"))
let pp_op = pp_binary_operators op
and pp_e1 = pp_expressions e1 method eval env = env#find name
and pp_e2 = pp_expressions e2 in end
Printf.sprintf "BinaryExpression(%s, %s, %s)" pp_op pp_e1 pp_e2
class unaryOperation (operator : UnaryOperators.unaryOperator)
(operand : expression) =
object
inherit expression
method to_string =
"UnaryOperation(" ^ operator#to_string ^ ", " ^ operand#to_string ^ ")"
method check_type env =
let operand_type = operand#check_type env in
operator#check_type operand_type
method eval env = operator#eval (operand#eval env)
end
class binaryOperation (operator : BinaryOperators.binaryOperator)
(left : expression) (right : expression) =
object
inherit expression
method to_string =
"BinaryOperation(" ^ operator#to_string ^ ", " ^ left#to_string ^ ", "
^ right#to_string ^ ")"
method check_type env =
let left_type = left#check_type env in
let right_type = right#check_type env in
operator#check_type (left_type, right_type)
method eval env = operator#eval (left#eval env, right#eval env)
end
+79 -14
View File
@@ -1,15 +1,80 @@
type literals = type literal_value =
| Integer of int [ `Int of int
| Float of float | `Float of float
| Character of char | `String of string
| String of string | `Bool of bool
| Boolean of bool | `Char of char
| Null | `Null
| `Void ]
let pp_literals = function let string_of_literal_value = function
| Integer i -> Printf.sprintf "Integer(%d)" i | `Int i -> string_of_int i
| Float f -> Printf.sprintf "Float(%f)" f | `Float f -> string_of_float f
| Character c -> Printf.sprintf "Character('%c')" c | `String s -> "\"" ^ s ^ "\""
| String s -> Printf.sprintf "String(\"%s\")" s | `Bool b -> string_of_bool b
| Boolean b -> Printf.sprintf "Boolean(%b)" b | `Char c -> "'" ^ String.make 1 c ^ "'"
| Null -> "Null" | `Null -> "null"
| `Void -> "void"
class virtual literal =
object
inherit Node.node
method virtual value : literal_value
method virtual check_type : Types.t
end
class eInteger (value : int) =
object
inherit literal
method value = `Int value
method to_string = "Integer(" ^ string_of_int value ^ ")"
method check_type = Types.IntegerType
end
class eFloat (value : float) =
object
inherit literal
method value = `Float value
method to_string : string = "Float(" ^ string_of_float value ^ ")"
method check_type = Types.FloatType
end
class eString (value : string) =
object
inherit literal
method value = `String value
method to_string = "String(\"" ^ value ^ "\")"
method check_type = Types.StringType
end
class eBoolean (value : bool) =
object
inherit literal
method value = `Bool value
method to_string = "Boolean(" ^ string_of_bool value ^ ")"
method check_type = Types.BooleanType
end
class eCharacter (value : char) =
object
inherit literal
method value = `Char value
method to_string = "Character(" ^ String.make 1 value ^ ")"
method check_type = Types.CharacterType
end
class eNull =
object
inherit literal
method value = `Null
method to_string = "Null"
method check_type = Types.NullType
end
class eVoid =
object
inherit literal
method value = `Void
method to_string = "Void"
method check_type = Types.VoidType
end
+6
View File
@@ -0,0 +1,6 @@
class virtual node =
object
method virtual to_string : string
(* method virtual check_type : Types.type_ *)
(* method virtual eval *)
end
+17
View File
@@ -0,0 +1,17 @@
class program (statement : Statements.statement) =
object
inherit Node.node
method to_string = "Program(" ^ statement#to_string ^ ")"
method check_type =
let env : Environments.typeEnvironments =
new Environments.typeEnvironments
in
statement#check_type env
method eval =
let env : Environments.evalEnvironment =
new Environments.evalEnvironment
in
statement#eval env
end
-8
View File
@@ -1,8 +0,0 @@
open Statements
type source_files = SourceFile of statements
let pp_source_files = function
| SourceFile stmts ->
let pp_stmt = pp_statements stmts in
Printf.sprintf "SourceFile(%s)" pp_stmt
+50 -11
View File
@@ -1,13 +1,52 @@
open Expressions class virtual statement =
object
inherit Node.node
method virtual check_type : Environments.typeEnvironments -> Types.t
method virtual eval : Environments.evalEnvironment -> Literals.literal_value
end
type statements = class sequence (left : statement) (right : statement) =
| SequenceStatement of statements * statements object
| ExpressionStatement of expressions inherit statement
let rec pp_statements = function method to_string =
| SequenceStatement (stmt1, stmt2) -> "Sequence(" ^ left#to_string ^ ", " ^ right#to_string ^ ")"
let pp_stmt1 = pp_statements stmt1 and pp_stmt2 = pp_statements stmt2 in
Printf.sprintf "SequenceStatement(%s, %s)" pp_stmt1 pp_stmt2 method check_type env =
| ExpressionStatement expr -> let _ = left#check_type env in
let pp_expr = pp_expressions expr in right#check_type env
Printf.sprintf "ExpressionStatement(%s)" pp_expr
method eval env =
let _ = left#eval env in
right#eval env
end
class expression (expression : Expressions.expression) =
object
inherit statement
method to_string = "Expression(" ^ expression#to_string ^ ")"
method check_type env = expression#check_type env
method eval env = expression#eval env
end
class variableDeclaration (name : string) (tp : Types.t)
(expression : Expressions.expression) =
object
inherit statement
method to_string =
"VariableDeclaration(" ^ name ^ ", " ^ Types.string_of_t tp ^ ", "
^ expression#to_string ^ ")"
method check_type env =
let expression_type = expression#check_type env in
if tp = expression_type then (
env#add name expression_type;
Types.VoidType)
else raise (Failure "VariableDeclaration: type mismatch")
method eval env =
let value = expression#eval env in
env#add name value;
value
end
+8 -6
View File
@@ -1,15 +1,17 @@
type types = type t =
| IntegerType | IntegerType
| FloatType | FloatType
| CharacterType
| StringType
| BooleanType | BooleanType
| StringType
| CharacterType
| NullType
| VoidType | VoidType
let pp_types = function let string_of_t = function
| IntegerType -> "IntegerType" | IntegerType -> "IntegerType"
| FloatType -> "FloatType" | FloatType -> "FloatType"
| CharacterType -> "CharacterType"
| StringType -> "StringType"
| BooleanType -> "BooleanType" | BooleanType -> "BooleanType"
| StringType -> "StringType"
| CharacterType -> "CharacterType"
| NullType -> "NullType"
| VoidType -> "VoidType" | VoidType -> "VoidType"
+39 -4
View File
@@ -1,5 +1,40 @@
type unary_operators = ArithmeticNegation | LogicalNegation class virtual unaryOperator =
object
inherit Node.node
method virtual check_type : Types.t -> Types.t
method virtual eval : Literals.literal_value -> Literals.literal_value
end
let pp_unary_operators = function class arithmeticNegation =
| ArithmeticNegation -> "ArithmeticNegation" object
| LogicalNegation -> "LogicalNegation" inherit unaryOperator
method to_string = "ArithmeticNegation"
method check_type (operand : Types.t) =
match operand with
| Types.IntegerType -> Types.IntegerType
| Types.FloatType -> Types.FloatType
| _ -> raise (Failure "ArithmeticNegation: operand must be a number")
method eval operand =
match operand with
| `Int i -> `Int (-i)
| `Float f -> `Float (-.f)
| _ -> raise (Failure "ArithmeticNegation: operand must be a number")
end
class logicalNegation =
object
inherit unaryOperator
method to_string = "LogicalNegation"
method check_type (operand : Types.t) =
match operand with
| Types.BooleanType -> Types.BooleanType
| _ -> raise (Failure "LogicalNegation: operand must be a boolean")
method eval operand =
match operand with
| `Bool b -> `Bool (not b)
| _ -> raise (Failure "LogicalNegation: operand must be a boolean")
end
+7 -3
View File
@@ -1,10 +1,14 @@
(library (library
(name Syntax) (name syntax)
(modules (modules
Node
Types Types
Literals Environments
BinaryOperators BinaryOperators
UnaryOperators UnaryOperators
Literals
Expressions Expressions
Statements Statements
SourceFiles)) Roots)
; (libraries typing)
)
-1
View File
@@ -1 +0,0 @@
!vrai;
-30
View File
@@ -1,30 +0,0 @@
open Alcotest
open Syntax.BinaryOperators
let test_pp_binary_operators () =
let to_check =
[
("Should return \"Add\"", "Add", Add);
("Should return \"Subtract\"", "Subtract", Subtract);
("Should return \"Multiply\"", "Multiply", Multiply);
("Should return \"Divide\"", "Divide", Divide);
("Should return \"Equals\"", "Equals", Equals);
("Should return \"NotEquals\"", "NotEquals", NotEquals);
("Should return \"LessThan\"", "LessThan", LessThan);
("Should return \"LessThanEquals\"", "LessThanEquals", LessThanEquals);
("Should return \"GreaterThan\"", "GreaterThan", GreaterThan);
( "Should return \"GreaterThanEquals\"",
"GreaterThanEquals",
GreaterThanEquals );
("Should return \"And\"", "And", And);
("Should return \"Or\"", "Or", Or);
]
in
List.iter
(fun (msg, expected, actual) ->
check string msg expected (pp_binary_operators actual))
to_check
let tests =
( "BinaryOperators",
[ test_case "pp_binary_operators" `Quick test_pp_binary_operators ] )
-32
View File
@@ -1,32 +0,0 @@
open Alcotest
open Syntax
let test_pp_expressions () =
let to_check =
[
( "Should return \"Literal(...)\"",
"Literal(Integer(1))",
Expressions.Literal (Literals.Integer 1) );
( "Should return \"Identifier(...)\"",
"Identifier(\"myVar\")",
Expressions.Identifier "myVar" );
( "Should return \"UnaryExpression(...)\"",
"UnaryExpression(ArithmeticNegation, Literal(Integer(2)))",
Expressions.UnaryExpression
( UnaryOperators.ArithmeticNegation,
Expressions.Literal (Literals.Integer 2) ) );
( "Should return \"BinaryExpression(...)\"",
"BinaryExpression(Add, Literal(Integer(5)), Literal(Integer(10)))",
Expressions.BinaryExpression
( BinaryOperators.Add,
Expressions.Literal (Literals.Integer 5),
Expressions.Literal (Literals.Integer 10) ) );
]
in
List.iter
(fun (msg, expected, actual) ->
check string msg expected (Expressions.pp_expressions actual))
to_check
let tests =
("Expressions", [ test_case "pp_expressions" `Quick test_pp_expressions ])
-22
View File
@@ -1,22 +0,0 @@
open Alcotest
open Syntax.Literals
let test_pp_literals () =
let to_check =
[
("Should return \"Integer(1)\"", "Integer(1)", Integer 1);
("Should return \"Float(1.000000)\"", "Float(1.000000)", Float 1.0);
( "Should return \"String(\\\"Hello, World!\\\")\"",
"String(\"Hello, World!\")",
String "Hello, World!" );
("Should return \"Character('c')\"", "Character('c')", Character 'c');
("Should return \"Boolean(true)\"", "Boolean(true)", Boolean true);
("Should return \"Boolean(false)\"", "Boolean(false)", Boolean false);
]
in
List.iter
(fun (msg, expected, actual) ->
check string msg expected (pp_literals actual))
to_check
let tests = ("Literals", [ test_case "pp_literals" `Quick test_pp_literals ])
-24
View File
@@ -1,24 +0,0 @@
open Alcotest
open Syntax
let test_pp_source_files () =
let to_check =
[
( "Should return \"SourceFile(...)\"",
"SourceFile(ExpressionStatement(BinaryExpression(Add, \
Literal(Integer(1)), Literal(Integer(2)))))",
SourceFiles.SourceFile
(Statements.ExpressionStatement
(Expressions.BinaryExpression
( BinaryOperators.Add,
Expressions.Literal (Literals.Integer 1),
Expressions.Literal (Literals.Integer 2) ))) );
]
in
List.iter
(fun (name, expected, actual) ->
check string name expected (SourceFiles.pp_source_files actual))
to_check
let tests =
("SourceFiles", [ test_case "pp_source_files" `Quick test_pp_source_files ])
-27
View File
@@ -1,27 +0,0 @@
open Alcotest
open Syntax
let test_pp_statements () =
let to_check =
[
( "Should return \"ExpressionStatement(...)\"",
"ExpressionStatement(Literal(Integer(1)))",
Statements.ExpressionStatement
(Expressions.Literal (Literals.Integer 1)) );
( "Should return \"SequenceStatement(...)\"",
"SequenceStatement(ExpressionStatement(Literal(Integer(1))), \
ExpressionStatement(Literal(Float(1.000000))))",
Statements.SequenceStatement
( Statements.ExpressionStatement
(Expressions.Literal (Literals.Integer 1)),
Statements.ExpressionStatement
(Expressions.Literal (Literals.Float 1.0)) ) );
]
in
List.iter
(fun (name, expected, actual) ->
check string name expected (Statements.pp_statements actual))
to_check
let tests =
("Statements", [ test_case "pp_statements" `Quick test_pp_statements ])
-13
View File
@@ -1,13 +0,0 @@
open Alcotest
let () =
run "Syntax"
[
TestTypes.tests;
TestLiterals.tests;
TestUnaryOperators.tests;
TestBinaryOperators.tests;
TestExpressions.tests;
TestStatements.tests;
TestSourceFiles.tests;
]
-18
View File
@@ -1,18 +0,0 @@
open Alcotest
open Syntax.Types
let test_pp_types () =
let to_check =
[
("Should return \"IntegerType\"", "IntegerType", IntegerType);
("Should return \"BooleanType\"", "BooleanType", BooleanType);
("Should return \"StringType\"", "StringType", StringType);
("Should return \"CharacterType\"", "CharacterType", CharacterType);
("Should return \"VoidType\"", "VoidType", VoidType);
]
in
List.iter
(fun (msg, expected, input) -> check string msg expected (pp_types input))
to_check
let tests = ("Types", [ test_case "pp_types" `Quick test_pp_types ])
-19
View File
@@ -1,19 +0,0 @@
open Alcotest
open Syntax.UnaryOperators
let test_pp_unary_operators () =
let to_check =
[
( "Should return \"ArithmeticNegation\"",
ArithmeticNegation,
"ArithmeticNegation" );
]
in
List.iter
(fun (msg, unary_operator, expected) ->
check string msg expected (pp_unary_operators unary_operator))
to_check
let tests =
( "UnaryOperators",
[ test_case "pp_unary_operators" `Quick test_pp_unary_operators ] )
-4
View File
@@ -1,4 +0,0 @@
(test
(name TestSyntax)
(libraries Syntax alcotest)
)
+5
View File
@@ -0,0 +1,5 @@
var a : entier = 5; // 5
var b : flottant = a + 3.8; // 8.8
var c : flottant = b * a; // 44.0
var d : chaine = "Hello" + "World"; // "HelloWorld"