Browse thread
[Caml-list] Better option to read a file
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ 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