caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* 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;
as well as URLs for NNTP newsgroup(s).