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
2 changes: 1 addition & 1 deletion 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"; "then"; "else"; "fi"; "while"; "do"; "od"; "repeat"; "until"; "for"] s
inherit Util.Lexers.decimal s
inherit Util.Lexers.skip [
Matcher.Skip.whitespaces " \t\n";
Expand Down
85 changes: 53 additions & 32 deletions src/Interpret.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,69 @@ open Language

(* Interpreter for expressions *)
module Expr =
struct
struct

open Expr
open Expr

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
let calc_op op x y =
match op with
| "+" -> x + y
| "-" -> x - y
| "*" -> x * y
| "/" -> x / y
| "%" -> x mod y
| "==" -> if(x == y) then 1 else 0
| "!=" -> if(x != y) then 1 else 0
| ">" -> if(x > y) then 1 else 0
| ">=" -> if(x >= y) then 1 else 0
| "<" -> if(x < y) then 1 else 0
| "<=" -> if(x <= y) then 1 else 0
| "!!" -> if((x != 0) || (y != 0)) then 1 else 0
| "&&" -> if((x != 0) && (y != 0)) then 1 else 0

end

let rec eval expr st =
let eval' e = eval e st in
match expr with
| Var x -> st x
| Const z -> z
| BinOp (op, x, y) -> calc_op op (eval' x ) (eval' y )
end

(* Interpreter for statements *)
module Stmt =
struct
struct

open Stmt
open Stmt

(* State update primitive *)
let update st x v = fun y -> if y = x then v else st y
(* 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)
| Write e -> (st, input, output @ [Expr.eval e st])
| Seq (s1, s2) -> eval s1 conf |> eval s2

end
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)
| 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
| Repeat(e, s) -> eval s conf |> eval (While(BinOp("==",e,Const 0),s))

end

module Program =
struct
struct

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

end
in
output
end
125 changes: 82 additions & 43 deletions src/Language.ml
Original file line number Diff line number Diff line change
@@ -1,54 +1,93 @@
open Ostap
open Matcher
(* AST for expressions *)
module Expr =
struct
struct

type t =
| Var of string
| Const of int
| Add of t * t
| Mul of t * t
type t =
| Var of string
| Const of int
| 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 -")"
)

end
ostap (
parse:
head:and_op tail:("!!" and_op)*{
List.fold_left(fun left (op, right) -> BinOp(Token.repr op, left, right)) head tail}
| and_op;

and_op:
head:comp_op tail:("&&" comp_op)*{
List.fold_left(fun left (op, right) -> BinOp(Token.repr op, left, right)) head tail}
| comp_op;

comp_op:
head:addsub_op tail:((">=" | ">" | "<=" | "<" | "==" | "!=") addsub_op)*{
List.fold_left(fun left (op, right) -> BinOp(Token.repr op, left, right)) head tail}
| addsub_op;

addsub_op:
head:muldiv_op tail:(("+" | "-") muldiv_op)*{
List.fold_left(fun left (op, right) -> BinOp(Token.repr op, left, right)) head tail}
| muldiv_op;

muldiv_op:
head:primary tail:(("*" | "/" | "%") primary)*{
List.fold_left(fun left (op, right) -> BinOp(Token.repr op, left, right)) head tail}
| primary;

primary:
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

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};

parse: s:simp ";" d:parse {Seq (s,d)} | simp
)
struct

end
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
| Repeat of Expr.t * t

ostap (
parse:
s:simp ";" d:parse {Seq(s,d)}
|simp;
expr:
!(Expr.parse);
simp:
x:IDENT ":=" e:expr {Assign (x, e)}
| %"read" "(" x:IDENT ")" {Read x}
| %"write" "(" e:expr ")" {Write e}
| %"skip" {Skip}
| %"if" e:expr
%"then" s:parse
%"fi" {If(e,s,Skip)}
| %"if" e:expr
"then" s1:parse
"else" s2:parse
"fi" {If(e,s1,s2)}
| %"while" e:expr
"do" s:parse
"od" {While(e,s)}
| %"repeat" s:parse
"until" e:expr {Repeat(e,s)}
| %"for" s1:parse
"," e:expr
"," s2:parse
"do" s3:parse
"od" {Seq(s1,While(e,Seq(s3,s2)))})
end

module Program =
struct

type t = Stmt.t

let parse = Stmt.parse

end
struct
type t = Stmt.t
let parse = Stmt.parse
end

Loading