Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
/Driver.cmo
/Expr.cmi
/Expr.cmo
_build
_tags
rc.byte
rc.native
11 changes: 3 additions & 8 deletions regression/Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
TESTS=test001 test002 test012 test013
TESTS=test001 test002 test003 test004 test005 test006 test007 test008 test009 test010 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023

# More expressions:
# test003 test004 test005 test006 test007 test008

# Later:
# test009 test010 test 11
# test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026
# test027 test028 test029 test030
# test019 test020 test021 test022 test023 test024 test025 test026 test017 test018
# test027 test028 test029 test030 test011 test014 test015 test016

.PHONY: check $(TESTS)

Expand Down
3 changes: 1 addition & 2 deletions src/Driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let parse filename =
Util.parse
(object
inherit Matcher.t s
inherit Util.Lexers.ident ["read"; "write"; "skip"] s
inherit Util.Lexers.ident ["read"; "write"; "skip"; "if"; "fi"; "then"; "else"; "while"; "do"; "od"; "repeat"; "until"; "for"] s
inherit Util.Lexers.decimal s
inherit Util.Lexers.skip [
Matcher.Skip.whitespaces " \t\n";
Expand Down Expand Up @@ -48,4 +48,3 @@ let main =
| `Fail er -> Printf.eprintf "Syntax error: %s\n" er
with Invalid_argument _ ->
Printf.printf "Usage: rc [-i] <input file.expr>\n"

35 changes: 16 additions & 19 deletions src/Interpret.ml
Original file line number Diff line number Diff line change
@@ -1,49 +1,46 @@
open Language

(* Interpreter for expressions *)
module Expr =
struct

open Expr
open Language.BinOp

let rec eval expr st =
let eval' e = eval e st in
match expr with
| Var x -> st x

| Const z -> z
| Add (x, y) -> eval' x + eval' y
| Mul (x, y) -> eval' x * eval' y


| Binop (op, x, y) -> (apply op) (eval' x) (eval' y)
end

(* Interpreter for statements *)
module Stmt =
struct

open Stmt

(* State update primitive *)
let update st x v = fun y -> if y = x then v else st y

let rec eval stmt ((st, input, output) as conf) =
match stmt with
| Skip -> conf

| Assign (x, e) -> (update st x (Expr.eval e st), input, output)
| Read x ->
let z :: input' = input in
(update st x z, input', output)

| Read x -> let z :: input' = input in (update st x z, input', output)
| Write e -> (st, input, output @ [Expr.eval e st])

| Seq (s1, s2) -> eval s1 conf |> eval s2


| If (e, s1, s2) -> if (Expr.eval e st) <> 0 then (eval s1 conf) else (eval s2 conf)

| While (e, s) -> if (Expr.eval e st) <> 0 then (eval stmt (eval s conf)) else conf
end

module Program =
struct

let eval p input =
let (_, _, output) =
Stmt.eval p ((fun _ -> failwith "undefined variable"), input, [])
in
output

end
let (_, _, output) = Stmt.eval p ((fun _ -> failwith "undefined variable"), input, [])
in output
end
97 changes: 78 additions & 19 deletions src/Language.ml
Original file line number Diff line number Diff line change
@@ -1,54 +1,113 @@
(* AST for expressions *)
open Ostap
open Matcher

module Expr =
struct

type t =
| Var of string
| Const of int
| Add of t * t
| Mul of t * t
| Binop of string * t * t

ostap (
parse: x:mull "+" y:parse {Add (x,y)} | mull;
mull : x:prim "*" y:mull {Mul (x,y)} | prim;
prim :
n:DECIMAL {Const n}
| e:IDENT {Var e}
| -"(" parse -")"
)
parse:
orins;

orins:
l:andins suf:(("!!") andins)* {
List.fold_left (fun l (op, r) -> Binop (Token.repr op, l, r)) l suf
}
| andins;

andins:
l:cmp suf:(("&&") cmp)* {
List.fold_left (fun l (op, r) -> Binop (Token.repr op, l, r)) l suf
}
| cmp;

cmp:
l:add suf:(("<=" | "<" | ">=" | ">" | "==" | "!=") add)* {
List.fold_left (fun l (op, r) -> Binop (Token.repr op, l, r)) l suf
}
| add;

add:
l:mull suf:(("+" | "-") mull)* {
List.fold_left (fun l (op, r) -> Binop (Token.repr op, l, r)) l suf
}
| mull;

mull:
l:prim suf:(("*" | "/" | "%") prim)* {
List.fold_left (fun l (op, r) -> Binop (Token.repr op, l, r)) l suf
}
| prim;

prim:
n:DECIMAL {Const n}
| x:IDENT {Var x}
| -"(" parse -")"
)
end

(* AST statements/commands *)
module Stmt =
struct

type t =
| Skip
| Assign of string * Expr.t
| Read of string
| Write of Expr.t
| Seq of t * t
| If of Expr.t * t * t
| While of Expr.t * t

let expr = Expr.parse

ostap (
simp: x:IDENT ":=" e:expr {Assign (x, e)}
| %"read" "(" x:IDENT ")" {Read x}
| %"write" "(" e:expr ")" {Write e}
| %"skip" {Skip};

| %"skip" {Skip}
| %"if" e:!(Expr.parse)
%"then" s1:!(parse)
%"else" s2:!(parse)
%"fi" {If (e, s1, s2)}
| %"if" e:!(Expr.parse)
%"then" s1:!(parse)
%"fi" {If (e, s1, Skip)}
| %"while" e:!(Expr.parse)
%"do" s:!(parse)
%"od" {While (e, s)}
| %"repeat" s:!(parse)
%"until" e:!(Expr.parse) {Seq (s, While (Binop ("==", e, Const 0), s))}
| %"for" i:!(parse) "," n:!(Expr.parse) "," b:!(parse)
%"do" a:!(parse)
%"od" {Seq (i, (While (n, Seq (a, b))))};
parse: s:simp ";" d:parse {Seq (s,d)} | simp
)
end


module BinOp =
struct
let apply op =
match op with
| "+" -> fun x y -> x + y
| "*" -> fun x y -> x * y
| "-" -> fun x y -> x - y
| "/" -> fun x y -> x / y
| "%" -> fun x y -> x mod y
| "<" -> fun x y -> if x < y then 1 else 0
| "<=" -> fun x y -> if x <= y then 1 else 0
| ">" -> fun x y -> if x > y then 1 else 0
| ">=" -> fun x y -> if x >= y then 1 else 0
| "==" -> fun x y -> if x = y then 1 else 0
| "!=" -> fun x y -> if x <> y then 1 else 0
| "&&" -> fun x y -> if (x <> 0) && (y <> 0) then 1 else 0
| "!!" -> fun x y -> if (x <> 0) || (y <> 0) then 1 else 0
end

module Program =
struct

type t = Stmt.t

let parse = Stmt.parse

end

Loading