feat: Add Literals and operator of comparison

This commit is contained in:
Lucàs
2024-07-02 22:35:25 +02:00
parent 9ba70f93aa
commit 69e88fd5fd
5 changed files with 160 additions and 40 deletions
+20 -2
View File
@@ -8,13 +8,31 @@ let string_of_binary_operator = function
| Substract -> "Substract"
| Multiply -> "Multiply"
| Divide -> "Divide"
| AmpersandAmpersand -> "AmpersandAmpersand"
| BarBar -> "BarBar"
| EqualsEquals -> "EqualsEquals"
| ExclamationEquals -> "ExclamationEquals"
| LessThan -> "LessThan"
| LessThanEquals -> "LessThanEquals"
| GreaterThan -> "GreaterThan"
| GreaterThanEquals -> "GreaterThanEquals"
(** [string_of_unary_operator op] returns a string representation of the unary operator [op]. *)
let string_of_unary_operator = function Negate -> "Negate"
let string_of_unary_operator = function Negate -> "Negate" | Not -> "Not"
(** [string_of_literal l] returns a string representation of the literal [l]. *)
let string_of_literal = function
| Integer i -> "Integer(" ^ string_of_int i ^ ")"
| Float f -> "Float(" ^ string_of_float f ^ ")"
| Character c -> "Character('" ^ Char.escaped c ^ "')"
| String s -> "String(\"" ^ s ^ "\")"
| Boolean b -> "Boolean(" ^ string_of_bool b ^ ")"
| Null -> "Null"
(** [string_of_expression e] returns a string representation of the expression [e]. *)
let rec string_of_expression = function
| IntegerLiteral i -> "IntegerLiteral(" ^ string_of_int i ^ ")"
| Literal l -> "Literal(" ^ string_of_literal l ^ ")"
| Identifier i -> "Identifier(\"" ^ i ^ "\")"
| UnaryExpression (op, e) ->
"UnaryExpression("
^ string_of_unary_operator op
+25 -3
View File
@@ -1,10 +1,32 @@
(* lib/ast/syntax.ml *)
type binary_operator = Add | Substract | Multiply | Divide
type unary_operator = Negate
type literal =
| Integer of int
| Float of float
| Character of char
| String of string
| Boolean of bool
| Null
type binary_operator =
| Add
| Substract
| Multiply
| Divide
| AmpersandAmpersand
| BarBar
| EqualsEquals
| ExclamationEquals
| LessThan
| LessThanEquals
| GreaterThan
| GreaterThanEquals
type unary_operator = Negate | Not
type expression =
| IntegerLiteral of int
| Literal of literal
| Identifier of string
| UnaryExpression of unary_operator * expression
| BinaryExpression of binary_operator * expression * expression
+26 -1
View File
@@ -6,8 +6,16 @@
let line_comment = "//" [^ '\n']*
let letter = ['a'-'z' 'A'-'Z']
let digit = ['0'-'9']
let alphanum = letter | digit
let non_digit = '_'
let identifier = letter (alphanum | non_digit)*
let integer = digit+
let float = digit* '.' digit+
let char = "'" [^'.'] "'"
let string = '"' [^'.']* '"'
rule token = parse
| [' ' '\t'] | line_comment { token lexbuf }
@@ -18,11 +26,28 @@ rule token = parse
| '*' { TIMES }
| '/' { DIVIDE }
| ';' { SEMICOLON }
| "&&" { AMPERSAND_AMPERSAND }
| "||" { BAR_BAR }
| "==" { EQUALS_EQUALS }
| "!=" { EXCLAMATION_EQUALS }
| '<' { LESS_THAN }
| "<=" { LESS_THAN_EQUALS }
| '>' { GREATER_THAN }
| ">=" { GREATER_THAN_EQUALS }
| integer as lxm { INT(int_of_string lxm) }
| "!" { EXCLAMATION }
| '(' { LPAREN }
| ')' { RPAREN }
| "vrai" { BOOLEAN(true) }
| "faux" { BOOLEAN(false) }
| "vide" { NULL }
| integer as lxm { INTEGER(int_of_string lxm) }
| float as lxm { FLOAT(float_of_string lxm) }
| char as lxm { CHARACTER(lxm.[1]) }
| string as lxm { STRING(String.sub lxm 1 (String.length lxm - 2)) }
| identifier as lxm { IDENTIFIER(lxm) }
| eof { EOF }
| _ as c { raise (Error c) }
+40 -8
View File
@@ -3,12 +3,27 @@
open Ast.Syntax
%}
%token <int> INT
%token <int> INTEGER
%token <float> FLOAT
%token <bool> BOOLEAN
%token <char> CHARACTER
%token <string> STRING
%token <string> IDENTIFIER
%token NULL
%token PLUS "+"
%token MINUS "-"
%token TIMES "*"
%token DIVIDE "/"
%token AMPERSAND_AMPERSAND "&&"
%token BAR_BAR "||"
%token EXCLAMATION "!"
%token EQUALS_EQUALS "=="
%token EXCLAMATION_EQUALS "!="
%token LESS_THAN "<"
%token LESS_THAN_EQUALS "<="
%token GREATER_THAN ">"
%token GREATER_THAN_EQUALS ">="
%token LPAREN "("
%token RPAREN ")"
@@ -17,6 +32,7 @@
%token EOF
%left "&&" "||"
%left "+" "-"
%left "*" "/"
%nonassoc UMINUS
@@ -28,6 +44,7 @@
main:
| statements EOF { SourceFile($1) }
| EOF { SourceFile([]) }
statements:
| statement ";" { [$1] }
@@ -37,19 +54,34 @@ statement:
| expression { ExpressionStatement($1) }
expression:
| literal { $1 }
| literal { Literal($1) }
| IDENTIFIER { Identifier($1) }
| unary_expression { $1 }
| binary_expression { $1 }
| "(" expression ")" { $2 }
literal:
| INT { IntegerLiteral($1) }
| INTEGER { Integer($1) }
| FLOAT { Float($1) }
| CHARACTER { Character($1) }
| STRING { String($1) }
| BOOLEAN { Boolean($1) }
| NULL { Null }
unary_expression:
| MINUS expression %prec UMINUS { UnaryExpression(Negate, $2) }
| "-" expression %prec UMINUS { UnaryExpression(Negate, $2) }
| "!" expression { UnaryExpression(Not, $2) }
binary_expression:
| e1=expression PLUS e2=expression { BinaryExpression(Add, e1, e2) }
| e1=expression MINUS e2=expression { BinaryExpression(Substract, e1, e2) }
| e1=expression TIMES e2=expression { BinaryExpression(Multiply, e1, e2) }
| e1=expression DIVIDE e2=expression { BinaryExpression(Divide, e1, e2) }
| e1=expression "+" e2=expression { BinaryExpression(Add, e1, e2) }
| e1=expression "-" e2=expression { BinaryExpression(Substract, e1, e2) }
| e1=expression "*" e2=expression { BinaryExpression(Multiply, e1, e2) }
| e1=expression "/" e2=expression { BinaryExpression(Divide, e1, e2) }
| e1=expression "&&" e2=expression { BinaryExpression(AmpersandAmpersand, e1, e2) }
| e1=expression "||" e2=expression { BinaryExpression(BarBar, e1, e2) }
| e1=expression "==" e2=expression { BinaryExpression(EqualsEquals, e1, e2) }
| e1=expression "!=" e2=expression { BinaryExpression(ExclamationEquals, e1, e2) }
| e1=expression "<" e2=expression { BinaryExpression(LessThan, e1, e2) }
| e1=expression "<=" e2=expression { BinaryExpression(LessThanEquals, e1, e2) }
| e1=expression ">" e2=expression { BinaryExpression(GreaterThan, e1, e2) }
| e1=expression ">=" e2=expression { BinaryExpression(GreaterThanEquals, e1, e2) }
+47 -24
View File
@@ -4,60 +4,83 @@ open Alcotest
open Ast.Syntax
open Ast.Print
let test_string_of_literal () =
check string "42" "Integer(42)" (string_of_literal (Integer 42));
check string "3.14" "Float(3.14)" (string_of_literal (Float 3.14));
check string "true" "Boolean(true)" (string_of_literal (Boolean true));
check string "false" "Boolean(false)" (string_of_literal (Boolean false));
check string "hello" "String(\"hello\")" (string_of_literal (String "hello"));
check string "c" "Character('c')" (string_of_literal (Character 'c'));
check string "null" "Null" (string_of_literal Null)
let test_string_of_binary_operator () =
check string "+" "Add" (string_of_binary_operator Add);
check string "-" "Substract" (string_of_binary_operator Substract);
check string "*" "Multiply" (string_of_binary_operator Multiply);
check string "/" "Divide" (string_of_binary_operator Divide)
check string "/" "Divide" (string_of_binary_operator Divide);
check string "&&" "AmpersandAmpersand"
(string_of_binary_operator AmpersandAmpersand);
check string "||" "BarBar" (string_of_binary_operator BarBar);
check string "==" "EqualsEquals" (string_of_binary_operator EqualsEquals);
check string "!=" "ExclamationEquals"
(string_of_binary_operator ExclamationEquals);
check string "<" "LessThan" (string_of_binary_operator LessThan);
check string "<=" "LessThanEquals" (string_of_binary_operator LessThanEquals);
check string ">" "GreaterThan" (string_of_binary_operator GreaterThan);
check string ">=" "GreaterThanEquals"
(string_of_binary_operator GreaterThanEquals)
let test_string_of_unary_operator () =
check string "-" "Negate" (string_of_unary_operator Negate)
check string "-" "Negate" (string_of_unary_operator Negate);
check string "!" "Not" (string_of_unary_operator Not)
let test_string_of_expression () =
let expr = BinaryExpression (Add, IntegerLiteral 1, IntegerLiteral 2) in
let expr = Literal (Integer 42) in
check string "42" "Literal(Integer(42))" (string_of_expression expr);
let expr = BinaryExpression (Add, Literal (Integer 1), Literal (Integer 2)) in
check string "1 + 2"
"BinaryExpression(Add, IntegerLiteral(1), IntegerLiteral(2))"
(string_of_expression expr)
"BinaryExpression(Add, Literal(Integer(1)), Literal(Integer(2)))"
(string_of_expression expr);
let expr = UnaryExpression (Negate, Literal (Integer 42)) in
check string "-42" "UnaryExpression(Negate, Literal(Integer(42)))"
(string_of_expression expr);
let expr = Identifier "x" in
check string "x" "Identifier(\"x\")" (string_of_expression expr)
let test_string_of_statement () =
let stmt = ExpressionStatement (IntegerLiteral 42) in
check string "42;" "ExpressionStatement(IntegerLiteral(42))"
let stmt = ExpressionStatement (Literal (Integer 42)) in
check string "42;" "ExpressionStatement(Literal(Integer(42)))"
(string_of_statement stmt)
let test_string_of_source_file () =
let source_file =
SourceFile
[
ExpressionStatement (IntegerLiteral 1);
ExpressionStatement (Literal (Integer 1));
ExpressionStatement
(BinaryExpression (Add, IntegerLiteral 2, IntegerLiteral 3));
(BinaryExpression (Add, Literal (Integer 2), Literal (Integer 3)));
]
in
check string "1; 2 + 3;"
"SourceFile([ExpressionStatement(IntegerLiteral(1)), \
ExpressionStatement(BinaryExpression(Add, IntegerLiteral(2), \
IntegerLiteral(3)))])"
"SourceFile([ExpressionStatement(Literal(Integer(1))), \
ExpressionStatement(BinaryExpression(Add, Literal(Integer(2)), \
Literal(Integer(3))))])"
(string_of_source_file source_file)
let () =
let open Alcotest in
run "AST tests"
[
( "string_of_literal",
[ test_case "literal" `Quick test_string_of_literal ] );
( "string_of_unary_operator",
[
test_case "string_of_unary_operator" `Quick
test_string_of_unary_operator;
] );
[ test_case "unary_operator" `Quick test_string_of_unary_operator ] );
( "string_of_binary_operator",
[
test_case "string_of_binary_operator" `Quick
test_string_of_binary_operator;
] );
[ test_case "binary_operator" `Quick test_string_of_binary_operator ] );
( "string_of_expression",
[ test_case "string_of_expression" `Quick test_string_of_expression ] );
[ test_case "expression" `Quick test_string_of_expression ] );
( "string_of_statement",
[ test_case "string_of_statement" `Quick test_string_of_statement ] );
[ test_case "statement" `Quick test_string_of_statement ] );
( "string_of_source_file",
[ test_case "string_of_source_file" `Quick test_string_of_source_file ]
);
[ test_case "source_file" `Quick test_string_of_source_file ] );
]