Tigerインタプリタへ論理演算子を導入したい
論理演算 & | を追加。
code:diff
commit 7c6729b8c0f4295e416b78f553b1bfca30b3839b
Author: takashi hatakeyama <takashi.hatakeyama@gmail.com>
Date: Sun Sep 3 20:55:53 2023 +0900
論理演算を追加
diff --git a/lib/eval.ml b/lib/eval.ml
index d34e630..700442c 100644
--- a/lib/eval.ml
+++ b/lib/eval.ml
@@ -64,7 +64,7 @@ let rec f expr env: val_t * table =
| _ -> failwith "type error")
| Syntax.OpExp { left; op; right } ->
match op with
- | Syntax.PlusOp | Syntax.MinusOp | Syntax.TimesOp | Syntax.DivideOp ->
+ | Syntax.PlusOp | Syntax.MinusOp | Syntax.TimesOp | Syntax.DivideOp | Syntax.AndOp | Syntax.OrOp ->
calc op left right env
| Syntax.EqOp | Syntax.NeqOp | Syntax.LtOp | Syntax.GtOp | Syntax.LeOp | Syntax.GeOp ->
compare op left right env
@@ -77,6 +77,10 @@ and calc op e1 e2 env =
| Syntax.MinusOp, IntVal v1, IntVal v2 -> IntVal(v1 - v2), env
| Syntax.TimesOp, IntVal v1, IntVal v2 -> IntVal(v1 * v2), env
| Syntax.DivideOp, IntVal v1, IntVal v2 -> IntVal(v1 / v2), env
+ | Syntax.AndOp, IntVal v1, IntVal v2 ->
+ if v1 = 1 && v2 = 1 then IntVal(1), env else IntVal(0), env
+ | Syntax.OrOp, IntVal v1, IntVal v2 ->
+ if v1 = 1 || v2 = 1 then IntVal(1), env else IntVal(0), env
| _ -> failwith "type error"
and compare op e1 e2 env =
diff --git a/lib/lexer.mll b/lib/lexer.mll
index 34e720c..3a693a0 100644
--- a/lib/lexer.mll
+++ b/lib/lexer.mll
@@ -27,6 +27,8 @@ rule token = parse
| "-" { Parser.MINUS }
| "*" { Parser.TIMES }
| "/" { Parser.DIVIDE }
+ | "&" { Parser.AND }
+ | "|" { Parser.OR }
| "=" { Parser.EQ }
| "<>" { Parser.NEQ }
| "<" { Parser.LT }
diff --git a/lib/parser.mly b/lib/parser.mly
index 7b66693..0983c6a 100644
--- a/lib/parser.mly
+++ b/lib/parser.mly
@@ -8,6 +8,7 @@
%token <string> ID
%token PLUS MINUS TIMES DIVIDE
%token EQ NEQ LT LE GT GE
+%token AND OR
%token LET IN END IF THEN ELSE
%token VAR FUNCTION ASSIGN
%token LPAREN RPAREN COMMA COLON SEMICOLON
@@ -16,7 +17,6 @@
// あとで使う
// %token COMMA COLON SEMICOLON LPAREN RPAREN LBRACK RBRACK
// %token LBRACE RBRACE DOT
-// %token AND OR
// %token ARRAY WHILE FOR TO DO OF
// %token BREAK NIL
// %token FUNCTION TYPE
@@ -29,6 +29,7 @@
%nonassoc THEN
%nonassoc ELSE
+%left AND OR
%left PLUS MINUS
%left TIMES DIVIDE
%nonassoc EQ NEQ LT LE GT GE
@@ -47,6 +48,8 @@ exp:
| exp MINUS exp { Syntax.OpExp { left = $1; op = Syntax.MinusOp; right = $3} }
| exp TIMES exp { Syntax.OpExp { left = $1; op = Syntax.TimesOp; right = $3} }
| exp DIVIDE exp { Syntax.OpExp { left = $1; op = Syntax.DivideOp; right = $3} }
+| exp AND exp { Syntax.OpExp { left = $1; op = Syntax.AndOp; right = $3} }
+| exp OR exp { Syntax.OpExp { left = $1; op = Syntax.OrOp; right = $3} }
| exp EQ exp { Syntax.OpExp { left = $1; op = Syntax.EqOp; right = $3} }
| exp NEQ exp { Syntax.OpExp { left = $1; op = Syntax.NeqOp; right = $3} }
| exp LT exp { Syntax.OpExp { left = $1; op = Syntax.LtOp; right = $3} }
diff --git a/lib/syntax.ml b/lib/syntax.ml
index 1570bda..1bb46df 100644
--- a/lib/syntax.ml
+++ b/lib/syntax.ml
@@ -5,6 +5,8 @@ and op_t =
| MinusOp
| TimesOp
| DivideOp
+ | AndOp
+ | OrOp
| EqOp
| NeqOp
| LtOp
diff --git a/test/tiger_test.expected b/test/tiger_test.expected
index de9525b..1e70e40 100644
--- a/test/tiger_test.expected
+++ b/test/tiger_test.expected
@@ -33,3 +33,9 @@ result: 55
result: -30
ABC
result: ()
+result: 1
+result: 0
+result: 0
+result: 1
+result: 1
+result: 0
diff --git a/test/tiger_test.ml b/test/tiger_test.ml
index 2d2ffa3..f43cb6f 100644
--- a/test/tiger_test.ml
+++ b/test/tiger_test.ml
@@ -326,7 +326,43 @@ let () =
(* Unit を返す *)
let () =
- let src = "( )" in
+ let src = "()" in
print_string "result: ";
Tiger.Eval.print_val (eval src);
print_newline ()
+
+(* 論理積 (and) その1 *)
+let () =
+ print_string "result: ";
+ Tiger.Eval.print_val (eval "1 & 1"); (* => 1 *)
+ print_newline ()
+
+(* 論理積 (and) その2 *)
+let () =
+ print_string "result: ";
+ Tiger.Eval.print_val (eval "1 & 0"); (* => 0 *)
+ print_newline ()
+
+(* 論理積 (and) その3 *)
+let () =
+ print_string "result: ";
+ Tiger.Eval.print_val (eval "0 & 0"); (* => 1 *)
+ print_newline ()
+
+(* 論理和 (or) その1 *)
+let () =
+ print_string "result: ";
+ Tiger.Eval.print_val (eval "1 | 1"); (* => 1 *)
+ print_newline ()
+
+(* 論理和 (or) その2 *)
+let () =
+ print_string "result: ";
+ Tiger.Eval.print_val (eval "1 | 0"); (* => 1 *)
+ print_newline ()
+
+(* 論理和 (or) その3 *)
+let () =
+ print_string "result: ";
+ Tiger.Eval.print_val (eval "0 | 0"); (* => 0 *)
+ print_newline ()