mirror of
https://github.com/LucasVbr/croissant.git
synced 2026-05-13 17:12:10 +00:00
feat: Add Literals and operator of comparison
This commit is contained in:
+21
-3
@@ -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
|
||||
@@ -33,4 +51,4 @@ let string_of_statement = function
|
||||
let string_of_source_file = function
|
||||
| SourceFile stmts ->
|
||||
let stmt_strings = List.map string_of_statement stmts in
|
||||
"SourceFile([" ^ String.concat ", " stmt_strings ^ "])"
|
||||
"SourceFile([" ^ String.concat ", " stmt_strings ^ "])"
|
||||
+26
-4
@@ -1,12 +1,34 @@
|
||||
(* 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
|
||||
|
||||
type statement = ExpressionStatement of expression
|
||||
type source_file = SourceFile of statement list
|
||||
type source_file = SourceFile of statement list
|
||||
+26
-1
@@ -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
@@ -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
@@ -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 ] );
|
||||
]
|
||||
Reference in New Issue
Block a user