caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Markus Mottl <markus@oefai.at>
To: Agustin Valverde Ramos <a_valverde@mac.com>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Better option to read a file
Date: Wed, 17 Mar 2004 18:46:32 +0100	[thread overview]
Message-ID: <20040317174632.GD18178@fichte.ai.univie.ac.at> (raw)
In-Reply-To: <0AEE851F-7832-11D8-910D-000A95CED312@mac.com>

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


  reply	other threads:[~2004-03-17 17:46 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-16 21:28 Agustín Valverde
2004-03-17  3:48 ` Pietro Abate
2004-03-17  7:31 ` Christoph Bauer
2004-03-17 16:42   ` Agustin Valverde Ramos
2004-03-17 17:46     ` Markus Mottl [this message]
2004-03-17 18:20       ` Agustin Valverde Ramos
2004-03-17 18:54         ` Markus Mottl
2004-03-17  8:22 ` Jean-Christophe Filliatre
2004-03-17 10:11   ` Markus Mottl
  -- strict thread matches above, loose matches on Subject: below --
2004-03-16 20:38 Agustín Valverde

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040317174632.GD18178@fichte.ai.univie.ac.at \
    --to=markus@oefai.at \
    --cc=a_valverde@mac.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).