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 Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MKDIR ?= mkdir -vp
CP ?= cp

OB=ocamlbuild -cflag -g -no-hygiene -use-ocamlfind -plugin-tag "package(str)" -classic-display
OB=ocamlbuild -cflags -g,-w,-8 -no-hygiene -use-ocamlfind -plugin-tag "package(str)"
ifdef OBV
OB += -verbose 6
endif
Expand Down
16 changes: 8 additions & 8 deletions regression/Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
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 test009 test010 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023

# test019 test020 test021 test022 test023 test024 test025 test026
# test027 test028 test029 test030
# Funcs:
# test011 test024 test025 test026 test027 test028 test029 test030 test 031

.PHONY: check $(TESTS)
.PHONY: check $(TESTS)

check: $(TESTS)
check: $(TESTS)

$(TESTS): %: %.expr
../rc.native $< && cat $@.input | ./$@ > $@.log && diff $@.log orig/$@.log
cat $@.input | ../rc.native -i $< > $@.log && diff $@.log orig/$@.log
cat $@.input | ../rc.native -s $< > $@.log && diff $@.log orig/$@.log
../rc.native $< ; cat $@.input | ./$@ > $@.log ; diff $@.log orig/$@.log
cat $@.input | ../rc.native -i $< > $@.log ; diff $@.log orig/$@.log
cat $@.input | ../rc.native -s $< > $@.log ; diff $@.log orig/$@.log

clean:
rm -f test*.log *.s *~ $(TESTS)
56 changes: 29 additions & 27 deletions src/Driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ open Expr
open Stmt
open Ostap

let parse filename =
let parse filename =
let s = Util.read filename in
Util.parse
(object
inherit Matcher.t s
inherit Util.Lexers.ident ["read"; "write"; "skip"] s
Util.parse
(object
inherit Matcher.t s
inherit Util.Lexers.ident ["read"; "write"; "skip"; "if"; "then"; "else"; "fi"; "while"; "do"; "od"; "for"; "elif"; "repeat"; "until"] s
inherit Util.Lexers.decimal s
inherit Util.Lexers.skip [
Matcher.Skip.whitespaces " \t\n";
Matcher.Skip.lineComment "--";
Matcher.Skip.nestedComment "(*" "*)"
Matcher.Skip.lineComment "--";
Matcher.Skip.nestedComment "(*" "*)"
] s
end)
(ostap (!(Stmt.parse) -EOF))
(ostap (!(Stmt.sequence) -EOF))

let main =
try
Expand All @@ -25,27 +25,29 @@ let main =
let to_compile = not (interpret || stack) in
let infile = Sys.argv.(if not to_compile then 2 else 1) in
match parse infile with

| `Ok prog ->
if to_compile
then
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"
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 | -s] <input file.expr>\n";
Printf.printf "Example: cat test001.input | .././rc.native -s test001.expr\n"
61 changes: 47 additions & 14 deletions src/Interpret.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,67 @@ module Expr =

open Expr


let match_operation 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 0 else 1
| "!!" -> fun x y -> if (x = 0 && y = 0) then 0 else 1

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 (op, x, y) -> (match_operation 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
(* 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
| 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

| Write e -> (st, input, output @ [Expr.eval e st])

| Seq (s1, s2) -> eval s1 conf |> eval s2 (*вычисляется s1 и conf передается в s2 *)

| If (exp, seq1, seq2) ->
if (Expr.eval exp st) != 0
then eval seq1 conf
else eval seq2 conf

| While (exp, seq) ->
if (Expr.eval exp st) != 0 then eval seq conf |> eval stmt else conf

| Repeat (seq, exp) ->
let (st', _, _) as conf' = eval seq conf in
if (Expr.eval exp st') == 0 then eval stmt conf' else conf'


end

Expand All @@ -42,7 +75,7 @@ module Program =

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

Expand Down
90 changes: 65 additions & 25 deletions src/Language.ml
Original file line number Diff line number Diff line change
@@ -1,44 +1,84 @@
open Ostap.Util

(* AST for expressions *)
module Expr =
struct

type t =
| Var of string
| Const of int
| Add of t * t
| Mul of t * 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 -")"
)
let rec expr_parser s =
expr id
[|
`Nona , [ostap ("!!"), (fun x y -> BinOp ("!!", x, y))];

end
`Nona , [ostap ("&&"), (fun x y -> BinOp ("&&", x, y))];

`Nona , [ostap ("=="), (fun x y -> BinOp ("==", x, y));
ostap ("!="), (fun x y -> BinOp ("!=", x, y));
ostap ("<="), (fun x y -> BinOp ("<=", x, y));
ostap (">="), (fun x y -> BinOp (">=", x, y));
ostap ("<"), (fun x y -> BinOp ("<", x, y));
ostap (">"), (fun x y -> BinOp (">", x, y))];

`Lefta , [ostap ("+"), (fun x y -> BinOp ("+", x, y));
ostap ("-"), (fun x y -> BinOp ("-", x, y))];

`Lefta , [ostap ("*"), (fun x y -> BinOp ("*", x, y));
ostap ("/"), (fun x y -> BinOp ("/", x, y));
ostap ("%"), (fun x y -> BinOp ("%", x, y))]
|]
expr' s
and
ostap (
expr':
n:DECIMAL {Const n}
| e:IDENT {Var e}
| -"(" expr_parser -")")

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

let expr = Expr.parse
let expr = Expr.expr_parser

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" e:expr %"then" seq:sequence seq':else_stmt?
%"fi" {If(e, seq, match seq' with None -> Skip | Some seq' -> seq')}
| %"while" e:expr
"do" seq:sequence %"od" {While(e, seq)}
| %"for" seq:sequence "," e:expr "," seq':sequence
%"do" s:sequence %"od" {Seq (seq, While (e, Seq (s, seq')))}
| %"repeat" seq:sequence
"until" e:expr {Repeat (seq, e)};

else_stmt:
%"else" sequence
| %"elif" e:expr %"then" seq:sequence seq':else_stmt?
{If(e,seq, match seq' with None -> Skip | Some seq' -> seq')};

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

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

type t = Stmt.t

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

end

Loading