Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Better option to read a file
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Markus Mottl <markus@o...>
Subject: Re: [Caml-list] Better option to read a file
On Wed, 17 Mar 2004, Agustin Valverde Ramos wrote:
> No, my parser works over all the file content. I want to read formulas 
> like the following:
[snip]
> I think that the Markus suggestion is better for me, because I have 
> never worked with ocamllex. By the way, can I obtain benefits in 
> efficiency using ocamllex? because in this case I'll learn to use it.

Please do yourself a favor, save a lot of work and use ocamllex and
ocamlyacc.  These tools are the Right Thing (tm) for the job.  Since I had
a very similar project handy, here are the files you need to get going:

file: ast.ml
Contains abstract syntax tree and pretty printer for logical expressions
---------------------------------------------------------------------------
open Format

type expr =
  | Id of string
  | Not of expr
  | And of expr * expr
  | Or of expr * expr
  | Imp of expr * expr

let rec pp_expr ppf = function
  | Id id -> pp_print_string ppf id
  | Not e -> fprintf ppf "-%a" pp_expr e
  | And (e1, e2) -> fprintf ppf "(@[%a &@ %a@])" pp_expr e1 pp_expr e2
  | Or (e1, e2) -> fprintf ppf "(@[%a |@ %a@])" pp_expr e1 pp_expr e2
  | Imp (e1, e2) -> fprintf ppf "(@[%a ->@ %a@])" pp_expr e1 pp_expr e2
---------------------------------------------------------------------------

file: parser.mly
Contains the translator: tokens -> abstract syntax tree
---------------------------------------------------------------------------
%token <string> ID
%token NOT AND OR IMP LPAREN RPAREN EOF

%start main
%type <Ast.expr> main

%%

main : expr EOF { $1 }

expr
  : ID { Ast.Id $1 }
  | LPAREN expr bin_op expr RPAREN { $3 $2 $4 }
  | NOT expr { Ast.Not $2 }

bin_op
  : AND { fun arg1 arg2 -> Ast.And (arg1, arg2) }
  | OR  { fun arg1 arg2 -> Ast.Or (arg1, arg2) }
  | IMP { fun arg1 arg2 -> Ast.Imp (arg1, arg2) }
---------------------------------------------------------------------------

file: lexer.mll
Contains the translator: string -> tokens
---------------------------------------------------------------------------
{ open Parser }

rule token = parse
  | [' ' '\t' '\n']     { token lexbuf }
  | ['a' - 'z']+ as id  { ID id }
  | '&'                 { AND }
  | '|'                 { OR }
  | "->"                { IMP }
  | "-"                 { NOT }
  | '('                 { LPAREN }
  | ')'                 { RPAREN }
  | eof                 { EOF }

{
  let lexbuf = Lexing.from_channel stdin in
  let ast = Parser.main token lexbuf in
  Format.printf "%a@." Ast.pp_expr ast
}
---------------------------------------------------------------------------

file: Makefile
Requires OCamlMakefile
---------------------------------------------------------------------------
SOURCES = ast.ml parser.mly lexer.mll
RESULT  = parse

include OCamlMakefile
---------------------------------------------------------------------------

Just type "make" and the resulting "parse"-program will read in your
logical expressions from stdin until EOF and pretty-print them (note:
the topmost expression also needs parenthesis!). E.g.:

file: test.dat
---------------------------------------------------------------------------
(
  (
    (p | (r -> t)) &
    (q | (t -> s))
  ) ->
  (
    (p & -(q -> -t)) |
    (r -> ((q -> (s | r)) & s))
  )
)
---------------------------------------------------------------------------

Running "parse < test.dat" should yield:

(((p | (r -> t)) & (q | (t -> s))) ->
 ((p & -(q -> -t)) | (r -> ((q -> (s | r)) & s))))

Have fun!

Regards,
Markus

-- 
Markus Mottl          http://www.oefai.at/~markus          markus@oefai.at

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners