Changing an expression to string - ocaml

I need to convert an arithmetic sequence that uses
this type:
type expr =
VarX
| VarY
| Sine of expr
| Cosine of expr
| Average of expr * expr
| Times of expr * expr
| Thresh of expr * expr * expr * expr
here are the definitions for all the things in it:
e ::= x | y | sin (pi*e) | cos (pi*e) | ((e + e)/2) | e * e | (e<e ? e : e)
need to convert something like this:
exprToString (Thresh(VarX,VarY,VarX,(Times(Sine(VarX),Cosine(Average(VarX,VarY))))));;
to this:
string = "(x<y?x:sin(pi*x)*cos(pi*((x+y)/2)))"
I know I have to do this recursively by matching each expr with its appropriate string but Im not sure where the function begins matching or how to recurse through it. Any help or clues would be appreciated

Here is a simplified version of what you probably want:
type expr =
| VarX
| Sine of expr
let rec exprToString = function
| VarX -> "x"
| Sine e -> "sin(" ^ exprToString e ^ ")"
let () = print_endline (exprToString (Sine (Sine (Sine (Sine VarX)))))
It recurses over the AST nodes and create the string representation of the input by concatenating the string representations of the nodes.
This approach may not work nicely for bigger real world examples since:
String concatenation (^) creates a new string from two, this is slower than using some more appropriate data structure such as Buffer.t
Too many parentheses, ex, (2*(2*(2*2))), not 2*2*2*2. If you want minimize the number of parentheses, your algorithm must be aware of operator precedence and connectivity.

Related

Need help checking if my CFG question is correct

I need to write a CFG for the language below:
L = { w ∈ Σ* | w is a regular expression over a binary alphabet }
I came up with:
S = SΣ* | ε
X = S | ε
I'm starting the discipline now, and if it isn't correct, i would apreciate an explanation.
Many thanks!
PS.: This is not part from a homework, it is just an exercise from a Computer Science Theory book.
ANSWER BASED ON Mo B. POST
S = e | {0,1}
X = S | S* | Z
Y = X | YX
Z = Y | Z | Y
SECOND ANSWER BASED ON Mo B. POST
S = e | {0,1}
X = S | S'*' | '(' Z ')'
Y = X | YX
Z = Y | Z '|' Y
No, this is not correct. The language is the set of regular expressions (which itself isn't regular, but it's luckily context-free), so you need to come up with a context-free grammar for regular expressions. (First, make sure you know the formal definition for regular expressions.)
The meta-alphabet Σ has not been defined in your question, but it only works if Σ at least contains the mentioned binary alphabet, say 0 and 1, and the symbols ε, *, |, ( and ).
Here is one way of doing it:
Basic ::= 'ε' // Note that this is the symbol 'ε' which is not the same as ε
| c // for c in {0, 1} or whatever the binary alphabet is
Star ::= Basic
| Star '*'
| '(' Regular ')'
Concat ::= Star
| Concat Star
Regular ::= Concat
| Regular '|' Concat

Implement an interpreter in Ocaml

i'm trying to write an interpreter in Ocaml, i have defined the syntax already and the semantic for the most of the operations.
I'm trying to implement two more operations:
Ntimes: this has two argouments, an Integer and a function. Ntimes has to apply the function n times.
Pipe: this is the same has the pipe in the linux bash.
example of Ntimes:
Ntimes(Int(4),f);;
example of Pipe:
Pipe(f1,(f2,(f3,(f4,(f5,Nil)))));;
The interpeter that i have is this:
SYNTAX
type ide = string;;
type operator = Plus | Minus | Mul | Div | And | Or | Eq;;
type exp = Int of int
| Bool of bool
| Den of string
| Op of exp * operator * exp
| Let of ide * exp * exp
| Fun of ide * exp
| Apply of exp * exp
| Ifz of exp * exp * exp
| Etup of tuple
| Pipe of tuple
| ManyTimes of int * exp
and tuple = Nil | Seq of exp * tuple;;
type dexp = Dint of int | Dbool of bool | Dstring of string | Unbound | Dtuple of dexp list | Funval of efun and efun = ide * exp * dexp env ;;
RUN-TIME SUPPORT
let rec eval ((e: exp), (r:dexp env)) = match e with
Int i -> Dint i
| Bool i -> Dbool i
.
.
.
.
| Etup e1 -> let v = (evalList e1 r) in Dtuple v
| Apply(e1, e2) -> (match eval(e1, r) with
| Funval(i, a, r1) -> eval(a, bind(r1, i, eval(e2, r)))
| _ -> failwith("no funct in apply"))
| NTimes(i,e) -> *I have no idea*
| Pipe(e) -> * I have no idea*
;;
Thanks for the any help that you will give me!

Generating C code in Ocaml

I'm trying to create a code generating DSL in OCaml, however I can't find many examples on what the code generation looks like. I would just like to see how to create code values in OCaml.
For example if I had a type like this:
let equation =
Add of int * int
| Sub of int * int
| Mul of int * int
| Div of int * int;;
and I want a function like this:
let write_code = function
| Add (x, y) -> // INSERT CODE "x + y" here
etc... how would this look?
I have looked at this example http://okmij.org/ftp/meta-programming/tutorial/power.ml but the characters .< >. are causing syntax errors when I try to compile.
The code generated will not need to be compiled or executed, but saved to a .c file for later use.
I would just like to see the basic structure for this simple example so I can apply it to a more complicated problem.
You can do like that :
type equation =
| Const of int
| Var of string
| Add of equation * equation
| Mul of equation * equation ;;
let rec c_string_of_equation = function
| Const i -> string_of_int i
| Var x -> x
| Add (e1, e2) ->
"(" ^ c_string_of_equation e1 ^ ") + (" ^ c_string_of_equation e2 ^ ")"
| Mul (e1, e2) ->
"(" ^ c_string_of_equation e1 ^ ") * (" ^ c_string_of_equation e2 ^ ")"
;;
Here you produce a string and after that you can write that string where you want.
I changed your expression type a bit to be more general.
The result string will contain too much parentheses, but it does not matter because the generated code is not targeted to humans but to a compiler.
You could use a buffer :
As it's written in the module :
This module implements buffers that automatically expand as necessary. It provides accumulative concatenation of strings in quasi-linear time (instead of quadratic time when strings are concatenated pairwise).
For example, you can write :
let equation =
| Add of int * int
| Sub of int * int
| Mul of int * int
| Div of int * int;;
let co = open_out filename
let buff = Buffer.create 11235
let write_code = function
| Add (x, y) -> Buffer.add_string buff (Printf.sprintf "%d + %d" x y)
| ... -> ...
let write c =
write_code c;
Buffer.output_buffer co buff
With
# Buffer.create;;
- : int -> Buffer.t = <fun>
# Buffer.add_string;;
- : Buffer.t -> string -> unit = <fun>
# Buffer.output_buffer;;
- : out_channel -> Buffer.t -> unit = <fun>
Notice that Buffer.add_string write the string at the end of the buffer ;-)

What is causing this type error in OCaml?

type expr = NUM of int
| PLUS of expr * expr
| MINUS of expr * expr
let rec calc expr1 =
match expr1 with
| NUM i -> NUM i
| PLUS (lexpr1, rexpr1) ->
(match lexpr1, rexpr1 with
| (*(NUM li1,NUM ri1) -> NUM li1+ri1*)
| (lexpr1', rexpr1') -> PLUS (calc lexpr1', calc rexpr1'))
It says
Error: This expression has type expr but an expression was expected of type int
I don't know why errors keep coming out
Ocaml in the line
NUM li1+ri1
first creates a NUM and then tries to add ri1. But since + operator applies only on ints and not at expr and int, it throws an error.
To fix this add ints first:
NUM (li1+ri1)

Function that evaluates mathematical expression

I need to create a function that returns the result of calculating expressions of a created type:
type expr =
VarX
| VarY
| Sine of expr
| Cosine of expr
| Average of expr * expr
| Times of expr * expr
| Thresh of expr * expr * expr * expr
here is what the function is supposed to do :
eval : expr * float * float -> float that takes an triple (e,x,y) and evaluates the expression e at the point x,y . x and y are going to be between -1 and 1 and the result of the function will be in the same interval. Once you have implemented the function, you should get the following behavior at the OCaml prompt:
# eval (Sine(Average(VarX,VarY)),0.5,-0.5);;
- :float = 0.0
Here is the function that I wrote it needs to return a float:
let rec eval (e,x,y) = match e with
VarX -> x*1.0
|VarY ->y*1.0
|Sine expr -> sin(pi* eval (expr,x,y))
|Cosine expr -> cos( pi* eval (expr,x,y))
|Average (expr1, expr2) -> (eval (expr1,x,y)+eval (expr2,x,y))/2.0
|Times (expr1, expr2) -> (eval (expr1,x,y))*(eval (expr2,x,y))
|Thresh (expr1, expr2, expr3, expr4) ->if((eval (expr1,x,y))<(eval (expr2,x,y)))then (eval (expr3,x,y)) else(eval (expr4,x,y));;
this is the error that i get,
Error: This expression has type float but an expression was expected of type
int
how do i make the function return a float, i know it needs to think that every return value for each case needs to be a float but im not sure how to do that
The operator for multiplying two floats is *.. The operator for adding two floats is +.. And, the operator for dividing two floats is /.