mirror of
https://github.com/LucasVbr/croissant.git
synced 2026-05-13 17:12:10 +00:00
feat: Implement eval methods for expressions
This commit is contained in:
+13
-5
@@ -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 file_path = Sys.argv.(1) in
|
||||
let file_stream = open_in file_path in
|
||||
let lexbuf = Lexing.from_channel file_stream in
|
||||
let ast =
|
||||
let lexbuf = get_lexbuf () in
|
||||
let ast : program =
|
||||
try Analyzer.Parser.main Analyzer.Lexer.token lexbuf with
|
||||
| Analyzer.Lexer.Error c ->
|
||||
let file_name = lexbuf.lex_curr_p.pos_fname
|
||||
@@ -20,4 +27,5 @@ let () =
|
||||
file_name line_num col_num "Erreur syntaxique" "Syntaxe incorrecte";
|
||||
exit 1
|
||||
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
@@ -1,7 +1,7 @@
|
||||
(library
|
||||
(name Analyzer)
|
||||
(name analyzer)
|
||||
(modules lexer parser)
|
||||
(libraries Syntax))
|
||||
(libraries syntax))
|
||||
|
||||
(menhir
|
||||
(modules parser))
|
||||
|
||||
+12
-3
@@ -33,7 +33,8 @@ rule token = parse
|
||||
| '+' { PLUS }
|
||||
| '-' { MINUS }
|
||||
| '*' { TIMES }
|
||||
| '/' { DIV }
|
||||
| '/' { DIVIDE }
|
||||
| "=" { EQUAL }
|
||||
| "==" { EQUAL_EQUAL }
|
||||
| "!=" { NOT_EQUAL }
|
||||
| "<" { LESS_THAN }
|
||||
@@ -43,16 +44,24 @@ rule token = parse
|
||||
| "&&" { AMPERSAND_AMPERSAND }
|
||||
| "||" { BAR_BAR }
|
||||
| "!" { EXCLAMATION }
|
||||
| ":" { COLON }
|
||||
|
||||
(* Keywords *)
|
||||
| "vrai" { BOOLEAN(true) }
|
||||
| "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 *)
|
||||
| interger as i { INT (int_of_string i) }
|
||||
| interger as i { INTEGER (int_of_string i) }
|
||||
| float as f { FLOAT (float_of_string f) }
|
||||
| '"' { Buffer.clear buffer; STRING(string lexbuf) }
|
||||
| "''" { NULL }
|
||||
| "'\\''" { CHARACTER '\'' }
|
||||
| "'\\n'" { CHARACTER '\n' }
|
||||
| "'\\t'" { CHARACTER '\t' }
|
||||
|
||||
+50
-29
@@ -2,18 +2,28 @@
|
||||
open Syntax
|
||||
%}
|
||||
|
||||
%token <int> INT
|
||||
%token <int> INTEGER
|
||||
%token <float> FLOAT
|
||||
%token <char> CHARACTER
|
||||
%token <bool> BOOLEAN
|
||||
%token <string> STRING
|
||||
%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 MINUS "-"
|
||||
%token TIMES "*"
|
||||
%token DIV "/"
|
||||
%token DIVIDE "/"
|
||||
%token EQUAL_EQUAL "=="
|
||||
%token NOT_EQUAL "!="
|
||||
%token LESS_THAN "<"
|
||||
@@ -25,6 +35,7 @@ open Syntax
|
||||
%token EXCLAMATION "!"
|
||||
|
||||
%token SEMICOLON ";"
|
||||
%token COLON ":"
|
||||
|
||||
%token LPAREN "("
|
||||
%token RPAREN ")"
|
||||
@@ -36,49 +47,59 @@ open Syntax
|
||||
|
||||
%nonassoc UMINUS
|
||||
|
||||
%start <SourceFiles.source_files> main
|
||||
%start <Roots.program> main
|
||||
|
||||
%%
|
||||
|
||||
main:
|
||||
| statements EOF { SourceFiles.SourceFile $1 }
|
||||
| statements EOF { new Roots.program $1 }
|
||||
|
||||
statements:
|
||||
| statement ";" { $1 }
|
||||
| statement ";" statements { Statements.SequenceStatement ($1, $3) }
|
||||
| statement ";" statements { new Statements.sequence $1 $3 }
|
||||
|
||||
statement:
|
||||
| expression { Statements.ExpressionStatement($1) }
|
||||
| expression { new Statements.expression $1 }
|
||||
| VAR IDENTIFIER ":" tp "=" expression { new Statements.variableDeclaration $2 $4 $6 }
|
||||
|
||||
expression:
|
||||
| literal { Expressions.Literal($1) }
|
||||
| IDENTIFIER { Expressions.Identifier($1) }
|
||||
| literal { new Expressions.literal $1 }
|
||||
| IDENTIFIER { new Expressions.identifier $1 }
|
||||
| unary_expression { $1 }
|
||||
| binary_expression { $1 }
|
||||
| "(" 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:
|
||||
| INT { Literals.Integer($1) }
|
||||
| FLOAT { Literals.Float($1) }
|
||||
| BOOLEAN { Literals.Boolean($1) }
|
||||
| CHARACTER { Literals.Character($1) }
|
||||
| STRING { Literals.String($1) }
|
||||
| NULL { Literals.Null }
|
||||
| INTEGER { new Literals.eInteger $1 }
|
||||
| FLOAT { new Literals.eFloat $1 }
|
||||
| BOOLEAN { new Literals.eBoolean $1 }
|
||||
| CHARACTER { new Literals.eCharacter $1 }
|
||||
| STRING { new Literals.eString $1 }
|
||||
| NULL_TYPE { new Literals.eNull }
|
||||
|
||||
unary_expression:
|
||||
| "-" expression %prec UMINUS { Expressions.UnaryExpression(UnaryOperators.ArithmeticNegation, $2) }
|
||||
| "!" expression { Expressions.UnaryExpression(UnaryOperators.LogicalNegation, $2) }
|
||||
| "-" expression %prec UMINUS { new Expressions.unaryOperation (new UnaryOperators.arithmeticNegation) $2 }
|
||||
| "!" expression { new Expressions.unaryOperation (new UnaryOperators.logicalNegation) $2 }
|
||||
|
||||
binary_expression:
|
||||
| expression "+" expression { Expressions.BinaryExpression (BinaryOperators.Add, $1, $3) }
|
||||
| expression "-" expression { Expressions.BinaryExpression (BinaryOperators.Subtract, $1, $3) }
|
||||
| expression "*" expression { Expressions.BinaryExpression (BinaryOperators.Multiply, $1, $3) }
|
||||
| expression "/" expression { Expressions.BinaryExpression (BinaryOperators.Divide, $1, $3) }
|
||||
| expression "==" expression { Expressions.BinaryExpression (BinaryOperators.Equals, $1, $3) }
|
||||
| expression "!=" expression { Expressions.BinaryExpression (BinaryOperators.NotEquals, $1, $3) }
|
||||
| expression "<" expression { Expressions.BinaryExpression (BinaryOperators.LessThan, $1, $3) }
|
||||
| expression "<=" expression { Expressions.BinaryExpression (BinaryOperators.LessThanEquals, $1, $3) }
|
||||
| expression ">" expression { Expressions.BinaryExpression (BinaryOperators.GreaterThan, $1, $3) }
|
||||
| expression ">=" expression { Expressions.BinaryExpression (BinaryOperators.GreaterThanEquals, $1, $3) }
|
||||
| expression "&&" expression { Expressions.BinaryExpression (BinaryOperators.And, $1, $3) }
|
||||
| expression "||" expression { Expressions.BinaryExpression (BinaryOperators.Or, $1, $3) }
|
||||
| expression "+" expression { new Expressions.binaryOperation (new BinaryOperators.add) $1 $3 }
|
||||
| expression "-" expression { new Expressions.binaryOperation (new BinaryOperators.subtract) $1 $3 }
|
||||
| expression "*" expression { new Expressions.binaryOperation (new BinaryOperators.multiply) $1 $3 }
|
||||
| expression "/" expression { new Expressions.binaryOperation (new BinaryOperators.divide) $1 $3 }
|
||||
| expression "==" expression { new Expressions.binaryOperation (new BinaryOperators.equals) $1 $3 }
|
||||
| expression "!=" expression { new Expressions.binaryOperation (new BinaryOperators.notEquals) $1 $3 }
|
||||
| expression "<" expression { new Expressions.binaryOperation (new BinaryOperators.lessThan) $1 $3 }
|
||||
| expression "<=" expression { new Expressions.binaryOperation (new BinaryOperators.lessThanEquals) $1 $3 }
|
||||
| expression ">" expression { new Expressions.binaryOperation (new BinaryOperators.greaterThan) $1 $3 }
|
||||
| expression ">=" expression { new Expressions.binaryOperation (new BinaryOperators.greaterThanEquals) $1 $3 }
|
||||
| expression "&&" expression { new Expressions.binaryOperation (new BinaryOperators.logicalAnd) $1 $3 }
|
||||
| expression "||" expression { new Expressions.binaryOperation (new BinaryOperators.logicalOr) $1 $3 }
|
||||
@@ -1 +0,0 @@
|
||||
type environment = { variables : (string * Types.types) list }
|
||||
@@ -1,3 +1,3 @@
|
||||
(library
|
||||
(name Croissant)
|
||||
(libraries Syntax Analyzer))
|
||||
(libraries syntax analyzer))
|
||||
|
||||
+264
-26
@@ -1,27 +1,265 @@
|
||||
type binary_operators =
|
||||
| Add
|
||||
| Subtract
|
||||
| Multiply
|
||||
| Divide
|
||||
| Equals
|
||||
| NotEquals
|
||||
| LessThan
|
||||
| LessThanEquals
|
||||
| GreaterThan
|
||||
| GreaterThanEquals
|
||||
| And
|
||||
| Or
|
||||
class virtual binaryOperator =
|
||||
object
|
||||
inherit Node.node
|
||||
method virtual check_type : Types.t * Types.t -> Types.t
|
||||
|
||||
let pp_binary_operators = function
|
||||
| Add -> "Add"
|
||||
| Subtract -> "Subtract"
|
||||
| Multiply -> "Multiply"
|
||||
| Divide -> "Divide"
|
||||
| Equals -> "Equals"
|
||||
| NotEquals -> "NotEquals"
|
||||
| LessThan -> "LessThan"
|
||||
| LessThanEquals -> "LessThanEquals"
|
||||
| GreaterThan -> "GreaterThan"
|
||||
| GreaterThanEquals -> "GreaterThanEquals"
|
||||
| And -> "And"
|
||||
| Or -> "Or"
|
||||
method virtual eval
|
||||
: Literals.literal_value * Literals.literal_value ->
|
||||
Literals.literal_value
|
||||
end
|
||||
|
||||
class add =
|
||||
object
|
||||
inherit binaryOperator
|
||||
method to_string = "Add"
|
||||
|
||||
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
|
||||
| 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
|
||||
@@ -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
@@ -1,23 +1,59 @@
|
||||
open Literals
|
||||
open UnaryOperators
|
||||
open BinaryOperators
|
||||
class virtual expression =
|
||||
object
|
||||
inherit Node.node
|
||||
method virtual check_type : Environments.typeEnvironments -> Types.t
|
||||
method virtual eval : Environments.evalEnvironment -> Literals.literal_value
|
||||
end
|
||||
|
||||
type expressions =
|
||||
| Literal of literals
|
||||
| Identifier of string
|
||||
| UnaryExpression of unary_operators * expressions
|
||||
| BinaryExpression of binary_operators * expressions * expressions
|
||||
class literal (lit : Literals.literal) =
|
||||
object
|
||||
inherit expression
|
||||
method to_string = "Literal(" ^ lit#to_string ^ ")"
|
||||
method check_type _ = lit#check_type
|
||||
method eval _ = lit#value
|
||||
end
|
||||
|
||||
let rec pp_expressions = function
|
||||
| Literal l ->
|
||||
let pp_l = pp_literals l in
|
||||
Printf.sprintf "Literal(%s)" pp_l
|
||||
| Identifier i -> Printf.sprintf "Identifier(\"%s\")" i
|
||||
| UnaryExpression (op, e) ->
|
||||
let pp_op = pp_unary_operators op and pp_e = pp_expressions e in
|
||||
Printf.sprintf "UnaryExpression(%s, %s)" pp_op pp_e
|
||||
| BinaryExpression (op, e1, e2) ->
|
||||
let pp_op = pp_binary_operators op
|
||||
and pp_e1 = pp_expressions e1
|
||||
and pp_e2 = pp_expressions e2 in
|
||||
Printf.sprintf "BinaryExpression(%s, %s, %s)" pp_op pp_e1 pp_e2
|
||||
class identifier (name : string) =
|
||||
object
|
||||
inherit expression
|
||||
method to_string = "Identifier(" ^ name ^ ")"
|
||||
|
||||
method check_type env =
|
||||
try env#find name
|
||||
with Not_found ->
|
||||
raise (Failure ("Identifier '" ^ name ^ "' not found"))
|
||||
|
||||
method eval env = env#find name
|
||||
end
|
||||
|
||||
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
@@ -1,15 +1,80 @@
|
||||
type literals =
|
||||
| Integer of int
|
||||
| Float of float
|
||||
| Character of char
|
||||
| String of string
|
||||
| Boolean of bool
|
||||
| Null
|
||||
type literal_value =
|
||||
[ `Int of int
|
||||
| `Float of float
|
||||
| `String of string
|
||||
| `Bool of bool
|
||||
| `Char of char
|
||||
| `Null
|
||||
| `Void ]
|
||||
|
||||
let pp_literals = function
|
||||
| Integer i -> Printf.sprintf "Integer(%d)" i
|
||||
| Float f -> Printf.sprintf "Float(%f)" f
|
||||
| Character c -> Printf.sprintf "Character('%c')" c
|
||||
| String s -> Printf.sprintf "String(\"%s\")" s
|
||||
| Boolean b -> Printf.sprintf "Boolean(%b)" b
|
||||
| Null -> "Null"
|
||||
let string_of_literal_value = function
|
||||
| `Int i -> string_of_int i
|
||||
| `Float f -> string_of_float f
|
||||
| `String s -> "\"" ^ s ^ "\""
|
||||
| `Bool b -> string_of_bool b
|
||||
| `Char c -> "'" ^ String.make 1 c ^ "'"
|
||||
| `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
|
||||
@@ -0,0 +1,6 @@
|
||||
class virtual node =
|
||||
object
|
||||
method virtual to_string : string
|
||||
(* method virtual check_type : Types.type_ *)
|
||||
(* method virtual eval *)
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
@@ -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 =
|
||||
| SequenceStatement of statements * statements
|
||||
| ExpressionStatement of expressions
|
||||
class sequence (left : statement) (right : statement) =
|
||||
object
|
||||
inherit statement
|
||||
|
||||
let rec pp_statements = function
|
||||
| SequenceStatement (stmt1, stmt2) ->
|
||||
let pp_stmt1 = pp_statements stmt1 and pp_stmt2 = pp_statements stmt2 in
|
||||
Printf.sprintf "SequenceStatement(%s, %s)" pp_stmt1 pp_stmt2
|
||||
| ExpressionStatement expr ->
|
||||
let pp_expr = pp_expressions expr in
|
||||
Printf.sprintf "ExpressionStatement(%s)" pp_expr
|
||||
method to_string =
|
||||
"Sequence(" ^ left#to_string ^ ", " ^ right#to_string ^ ")"
|
||||
|
||||
method check_type env =
|
||||
let _ = left#check_type env in
|
||||
right#check_type env
|
||||
|
||||
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
|
||||
+9
-7
@@ -1,15 +1,17 @@
|
||||
type types =
|
||||
type t =
|
||||
| IntegerType
|
||||
| FloatType
|
||||
| CharacterType
|
||||
| StringType
|
||||
| BooleanType
|
||||
| StringType
|
||||
| CharacterType
|
||||
| NullType
|
||||
| VoidType
|
||||
|
||||
let pp_types = function
|
||||
let string_of_t = function
|
||||
| IntegerType -> "IntegerType"
|
||||
| FloatType -> "FloatType"
|
||||
| CharacterType -> "CharacterType"
|
||||
| StringType -> "StringType"
|
||||
| BooleanType -> "BooleanType"
|
||||
| VoidType -> "VoidType"
|
||||
| StringType -> "StringType"
|
||||
| CharacterType -> "CharacterType"
|
||||
| NullType -> "NullType"
|
||||
| VoidType -> "VoidType"
|
||||
@@ -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
|
||||
| ArithmeticNegation -> "ArithmeticNegation"
|
||||
| LogicalNegation -> "LogicalNegation"
|
||||
class arithmeticNegation =
|
||||
object
|
||||
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
@@ -1,10 +1,14 @@
|
||||
(library
|
||||
(name Syntax)
|
||||
(name syntax)
|
||||
(modules
|
||||
Node
|
||||
Types
|
||||
Literals
|
||||
Environments
|
||||
BinaryOperators
|
||||
UnaryOperators
|
||||
Literals
|
||||
Expressions
|
||||
Statements
|
||||
SourceFiles))
|
||||
Roots)
|
||||
; (libraries typing)
|
||||
)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!vrai;
|
||||
@@ -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 ] )
|
||||
@@ -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 ])
|
||||
@@ -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 ])
|
||||
@@ -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 ])
|
||||
@@ -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 ])
|
||||
@@ -1,13 +0,0 @@
|
||||
open Alcotest
|
||||
|
||||
let () =
|
||||
run "Syntax"
|
||||
[
|
||||
TestTypes.tests;
|
||||
TestLiterals.tests;
|
||||
TestUnaryOperators.tests;
|
||||
TestBinaryOperators.tests;
|
||||
TestExpressions.tests;
|
||||
TestStatements.tests;
|
||||
TestSourceFiles.tests;
|
||||
]
|
||||
@@ -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 ])
|
||||
@@ -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 ] )
|
||||
@@ -1,4 +0,0 @@
|
||||
(test
|
||||
(name TestSyntax)
|
||||
(libraries Syntax alcotest)
|
||||
)
|
||||
@@ -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"
|
||||
Reference in New Issue
Block a user