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
17 changes: 16 additions & 1 deletion regression/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
TESTS=test001 test002 test012 test013 test003 test004 test005 test006 test007 test008 test009 test010 test011 test014 test015 test016 test017 test018
TESTS=test001 test002 test003 test004 test005 test006 test007 test008 test012 test013 #exprs

TESTS+=test009 test010 test014 test015 test016 test017 test018 #if and while

TESTS+= test019 test020 test021 test022 #for

TESTS+= test023 #repeat

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

#TESTS=test001 test002 test012 test013 test003 test004 test005 test006 test007 test008 test009 test010 test011 test014 test015 test016 test017 test018
#TESTS=test001 test002 test012 test013

# test019 test020 test021 test022 test023 test024 test025 test026
# test027 test028 test029 test030
Expand Down
41 changes: 21 additions & 20 deletions src/Driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ 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"; "elif"; "else";
"fi"; "while"; "do"; "od"; "for"; "repeat"; "until"] s
inherit Util.Lexers.decimal s
inherit Util.Lexers.skip [
Matcher.Skip.whitespaces " \t\n";
Matcher.Skip.lineComment "--";
Matcher.Skip.nestedComment "(*" "*)"
] s
end)
(ostap (!(Stmt.parse) -EOF))
(ostap (!(Stmt.sequence) -EOF))

let main =
try
Expand All @@ -27,24 +28,24 @@ let main =
match parse infile with
| `Ok prog ->
if to_compile
then
let basename = Filename.chop_suffix infile ".expr" in
ignore @@ X86.build prog basename
else
let rec read acc =
try
let r = read_int () in
Printf.printf "> ";
read (acc @ [r])
with End_of_file -> acc
in
let input = read [] in
let output =
if interpret
then Interpret.Program.eval prog input
else StackMachine.Interpret.run (StackMachine.Compile.Program.compile prog) input
in
List.iter (fun i -> Printf.printf "%d\n" i) output
then
let basename = Filename.chop_suffix infile ".expr" in
ignore @@ X86.build prog basename
else
let rec read acc =
try
let r = read_int () in
Printf.printf "> ";
read (acc @ [r])
with End_of_file -> acc
in
let input = read [] in
let output =
if interpret
then Interpret.Program.eval prog input
else StackMachine.Interpret.run (StackMachine.Compile.Program.compile prog) input
in
List.iter (fun i -> Printf.printf "%d\n" i) output
| `Fail er -> Printf.eprintf "Syntax error: %s\n" er
with Invalid_argument _ ->
Printf.printf "Usage: rc [-i] <input file.expr>\n"
Expand Down
37 changes: 26 additions & 11 deletions src/Interpret.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@ module 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
| Var x -> st x
| Const z -> z
| Binop ("+", x, y) -> eval' x + eval' y
| Binop ("-", x, y) -> eval' x - eval' y
| Binop ("*", x, y) -> eval' x * eval' y
| Binop ("/", x, y) -> eval' x / eval' y
| Binop ("%", x, y) -> (eval' x) mod (eval' y)
| Binop ("<", x, y) -> if (eval' x) < (eval' y) then 1 else 0
| Binop ("<=", x, y) -> if (eval' x) <= (eval' y) then 1 else 0
| Binop (">", x, y) -> if (eval' x) > (eval' y) then 1 else 0
| Binop (">=", x, y) -> if (eval' x) >= (eval' y) then 1 else 0
| Binop ("==", x, y) -> if (eval' x) == (eval' y) then 1 else 0
| Binop ("!=", x, y) -> if (eval' x) <> (eval' y) then 1 else 0
| Binop ("&&", x, y) -> if ((eval' x) <> 0) && ((eval' y) <> 0) then 1 else 0
| Binop ("!!", x, y) -> if ((eval' x) <> 0) || ((eval' y) <> 0) then 1 else 0

end

Expand All @@ -27,13 +38,17 @@ module Stmt =

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
| 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])
| 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
| Seq (s1, s2) -> eval s1 conf |> eval s2

end

Expand Down
59 changes: 43 additions & 16 deletions src/Language.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@ module Expr =
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 -")"
ostap(
parse: expr0;
expr0: h:expr1 t:(-"!!" expr1)*{ List.fold_left(fun e op ->Binop("!!", e, op)) h t};
expr1: h:expr2 t:(-"&&" expr2)*{List.fold_left(fun e op ->Binop("&&", e, op)) h t};
expr2: h:expr3 t:(("==" | "!=" | "<=" | "<" | ">=" | ">")expr3)?{
match t with
| None -> h
| Some (op, y) -> Binop(Ostap.Matcher.Token.repr op, h, y)
};
expr3: h:expr4 t:(("+" | "-") expr4)*{
List.fold_left(fun e (op, y) -> Binop(Ostap.Matcher.Token.repr op, e, y)) h t};
expr4: h: prim t:(("*" | "/" | "%") prim)*{
List.fold_left(fun e (op, y) -> Binop(Ostap.Matcher.Token.repr op, e, y)) h t};
prim:
n:DECIMAL {Const n}
| e:IDENT {Var e}
| -"(" parse -")"
)

end
Expand All @@ -29,16 +38,34 @@ module Stmt =
| 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};

parse: s:simp ";" d:parse {Seq (s,d)} | simp
statement:
x:IDENT ":=" e:expr {Assign (x, e)}
| %"read" "(" x:IDENT ")" {Read x}
| %"write" "(" e:expr ")" {Write e}
| %"skip" {Skip}
| %"if" exp:expr %"then" seq1:sequence seq2:elsePart?
%"fi" {If(exp, seq1, match seq2 with None -> Skip | Some seq2 -> seq2)}
| %"while" exp:expr
"do" seq:sequence %"od" {While(exp, seq)}
| %"for" s1:sequence "," e:expr "," s2:sequence
%"do" s:sequence %"od" {Seq(s1, While (e, Seq (s, s2)))}
| %"repeat" seq:sequence
"until" exp:expr {Seq(seq, While(Expr.Binop("==", exp, (Const 0)), seq))};

elsePart:
%"else" sequence
| %"elif" exp:expr %"then" seq1:sequence seq2:elsePart?
{If(exp,seq1, match seq2 with None -> Skip | Some seq2 -> seq2)};

sequence:
s:statement ";" d:sequence {Seq (s,d)}
| statement
)

end
Expand All @@ -48,7 +75,7 @@ module Program =

type t = Stmt.t

let parse = Stmt.parse
let parse = Stmt.sequence

end

Loading