* How can I have a string matched my custom type?
@ 2005-05-28 15:46 jeremy
2007-05-28 16:14 ` [Caml-list] " Jean-Christophe Filliatre
0 siblings, 1 reply; 5+ messages in thread
From: jeremy @ 2005-05-28 15:46 UTC (permalink / raw)
To: caml-list
[-- Attachment #1: Type: text/plain, Size: 1044 bytes --]
hi list,
I want to parse an expression string from the command line arguments, and have written some codes like below:
open Printf
type expr =
Plus of expr * expr
| Minus of expr * expr
| Times of expr * expr
| Divide of expr * expr
| Value of string
let rec to_string e =
match e with
Plus (left, right) -> "(" ^ (to_string left) ^ "+" ^ (to_string right) ^ ")"
| Minus (left, right) -> "(" ^ (to_string left) ^ "-" ^ (to_string right) ^ ")"
| Times (left, right) -> "(" ^ (to_string left) ^ "*" ^ (to_string right) ^ ")"
| Divide (left, right) -> "(" ^ (to_string left) ^ "/" ^ (to_string right) ^ ")"
| Value v -> v
let _ =
print_endline (to_string Sys.argv.(1))
when I compile it , It raise an error :
This expression has type string but is here used with type expr
How can I solve this problem? thx .
[-- Attachment #2: Type: text/html, Size: 2536 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] How can I have a string matched my custom type?
2005-05-28 15:46 How can I have a string matched my custom type? jeremy
@ 2007-05-28 16:14 ` Jean-Christophe Filliatre
2007-05-28 17:54 ` Mehdi
0 siblings, 1 reply; 5+ messages in thread
From: Jean-Christophe Filliatre @ 2007-05-28 16:14 UTC (permalink / raw)
To: jeremy; +Cc: caml-list
> I want to parse an expression string from the command line arguments, and have written some codes like below:
>
> type expr =
> Plus of expr * expr
> | Minus of expr * expr
> | Times of expr * expr
> | Divide of expr * expr
> | Value of string
>
> let rec to_string e =
> match e with
> Plus (left, right) -> "(" ^ (to_string left) ^ "+" ^ (to_string right) ^ ")"
> | Minus (left, right) -> "(" ^ (to_string left) ^ "-" ^ (to_string right) ^ ")"
> | Times (left, right) -> "(" ^ (to_string left) ^ "*" ^ (to_string right) ^ ")"
> | Divide (left, right) -> "(" ^ (to_string left) ^ "/" ^ (to_string right) ^ ")"
> | Value v -> v
>
> let _ =
> print_endline (to_string Sys.argv.(1))
As you say, you want to _parse_ an expression from a string, which
means a function of type string->expr, but your code only contains a
_pretty-printer_, that is the opposite operation, which has type
expr->string.
There are several ways to build such a parser. A simple way is to
write a recursive descending parser using Genlex and Stream from
ocaml's standard library, as follows:
======================================================================
open Genlex
let lex = make_lexer ["+"; "-"; "*"; "/"; "("; ")"];;
let rec expr s =
let t = term s in
match Stream.peek s with
| Some (Kwd "+") -> Stream.junk s; Plus (t, expr s)
| Some (Kwd "-") -> Stream.junk s; Minus (t, expr s)
| _ -> t
and term s =
let f = factor s in
match Stream.peek s with
| Some (Kwd "*") -> Stream.junk s; Times (f, term s)
| Some (Kwd "/") -> Stream.junk s; Divide (f, term s)
| _ -> f
| _ -> failwith "syntax error"
and factor s = match Stream.peek s with
| Some (Kwd "(") ->
Stream.junk s;
let e = expr s in
begin match Stream.peek s with
| Some (Kwd ")") -> Stream.junk s; e
| _ -> failwith "syntax error"
end
| Some (Int n) ->
Stream.junk s;
Value (string_of_int n)
| _ ->
failwith "syntax error"
let parse s = expr (lex (Stream.of_string s))
======================================================================
then you can parse the string "(1+2)*3+4" as follows:
======================================================================
let e = parse "(1+2)*3+4"
# val e : expr =
Plus (Times (Plus (Value "1", Value "2"), Value "3"), Value "4")
======================================================================
Another more sophisticated (but more powerful) way is to use a tool
like ocamlyacc or menhir.
Hope this helps,
--
Jean-Christophe
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] How can I have a string matched my custom type?
2007-05-28 16:14 ` [Caml-list] " Jean-Christophe Filliatre
@ 2007-05-28 17:54 ` Mehdi
2007-05-28 18:07 ` Jean-Christophe Filliatre
0 siblings, 1 reply; 5+ messages in thread
From: Mehdi @ 2007-05-28 17:54 UTC (permalink / raw)
To: Jean-Christophe Filliatre; +Cc: jeremy, caml-list
[-- Attachment #1: Type: text/plain, Size: 440 bytes --]
There a little problem when you try to compute
> let e = parse "1*3-2";;
I get :
> val e : expr = Times (Value "1", Value "3")
>
I didn't understand why it forgets to "minus 2" at the end. As I'm not
familiar with Genlex, can anyone tell me why isn't working ?
Am I missing somesthing ?
I also didn't understand why there is this in "term" :
> | _ -> f
> | _ -> failwith "syntax error"
--
Mehdi Dogguy
مهدي الدڤي
[-- Attachment #2: Type: text/html, Size: 1052 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] How can I have a string matched my custom type?
2007-05-28 17:54 ` Mehdi
@ 2007-05-28 18:07 ` Jean-Christophe Filliatre
2007-05-28 18:23 ` Mehdi
0 siblings, 1 reply; 5+ messages in thread
From: Jean-Christophe Filliatre @ 2007-05-28 18:07 UTC (permalink / raw)
To: Mehdi; +Cc: jeremy, caml-list
Mehdi writes:
> There a little problem when you try to compute
>
> > let e = parse "1*3-2";;
>
>
> I get :
>
> > val e : expr = Times (Value "1", Value "3")
This is a Genlex limitation. "-2" is recognized as an integer
constant. Thus you need to add extra space:
======================================================================
# parse "1*3 - 2";;
- : expr = Minus (Times (Value "1", Value "3"), Value "2")
======================================================================
> I also didn't understand why there is this in "term" :
>
> > | _ -> f
> > | _ -> failwith "syntax error"
Simply because I wrote this code in a rush :-) Forget about the last
line.
--
Jean-Christophe
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] How can I have a string matched my custom type?
2007-05-28 18:07 ` Jean-Christophe Filliatre
@ 2007-05-28 18:23 ` Mehdi
0 siblings, 0 replies; 5+ messages in thread
From: Mehdi @ 2007-05-28 18:23 UTC (permalink / raw)
To: Jean-Christophe Filliatre; +Cc: jeremy, caml-list
[-- Attachment #1: Type: text/plain, Size: 837 bytes --]
> > There a little problem when you try to compute
> >
> > > let e = parse "1*3-2";;
> >
> >
> > I get :
> >
> > > val e : expr = Times (Value "1", Value "3")
>
> This is a Genlex limitation. "-2" is recognized as an integer
> constant. Thus you need to add extra space:
>
> ======================================================================
> # parse "1*3 - 2";;
> - : expr = Minus (Times (Value "1", Value "3"), Value "2")
> ======================================================================
ok
> I also didn't understand why there is this in "term" :
> >
> > > | _ -> f
> > > | _ -> failwith "syntax error"
>
> Simply because I wrote this code in a rush :-) Forget about the last
> line.
I thought it was something obscur behind these two lines :)
thanks for the quick answer
--
Mehdi Dogguy
مهدي الدڤي
[-- Attachment #2: Type: text/html, Size: 1445 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2007-05-28 18:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-05-28 15:46 How can I have a string matched my custom type? jeremy
2007-05-28 16:14 ` [Caml-list] " Jean-Christophe Filliatre
2007-05-28 17:54 ` Mehdi
2007-05-28 18:07 ` Jean-Christophe Filliatre
2007-05-28 18:23 ` Mehdi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox