caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Pietro Abate <Pietro.Abate@anu.edu.au>
To: ocaml ml <caml-list@inria.fr>
Subject: buidlExpressionParser
Date: Sun, 31 Jul 2005 23:21:19 +1000	[thread overview]
Message-ID: <20050731132119.GA368@pulp.anu.edu.au> (raw)

[-- Attachment #1: Type: text/plain, Size: 979 bytes --]

Hi all,

I'm trying to write a generic parser similar to the buidlExpressionParser
in the haskel library (without using external libraries). I came up with
a kind of hack that uses the grammar extension mechanism (attached).

Is there a better way of doing this ?

And an other question: at the moment I'm using ( Plexer.gmake () ) as a
lexer, but I don't need it (too restrictive and doesn't lex tokens like
"[]" ).

Does anybody have an example on how to write a simple lexer that I can
use instead ?

:)
p

compile with:

ocamlfind ocamlc -c -pp "camlp4o -I . pa_extend.cmo q_MLast.cmo " -I /usr/lib/ocaml/3.08.3/camlp4 datatype.ml inputParser.ml

ocamlc /usr/lib/ocaml/3.08.3/camlp4/gramlib.cma datatype.cmo inputParser.cmo main.ml

-- 
++ Blog: http://blog.rsise.anu.edu.au/?q=pietro
++ 
++ "All great truths begin as blasphemies." -George Bernard Shaw
++ Please avoid sending me Word or PowerPoint attachments.
   See http://www.fsf.org/philosophy/no-word-attachments.html

[-- Attachment #2: datatype.ml --]
[-- Type: text/plain, Size: 507 bytes --]


type t =
    Atom of string
  | And of t * t
  | Or of t * t
  | Not of t


let rec string_of_formula = function
    |And(f1,f2) ->
            Printf.sprintf "(%s And %s)"
            (string_of_formula f1)
            (string_of_formula f2)
    |Or(f1,f2) ->
            Printf.sprintf "(%s Or %s)"
            (string_of_formula f1)
            (string_of_formula f2)
    |Not(f) -> Printf.sprintf "(Not %s)" (string_of_formula f)
    |Atom(s) -> s
;;

let print s = print_endline (string_of_formula s)

[-- Attachment #3: inputParser.ml --]
[-- Type: text/plain, Size: 918 bytes --]

(*pp camlp4o -I . pa_extend.cmo q_MLast.cmo *)

open Genlex

let gram = Grammar.gcreate (Plexer.gmake ());;
let expr_term = Grammar.Entry.create gram "expr_term";;

let add_uconn op co =
    EXTEND
      expr_term: LEVEL "Simple"
      [[ $op$; x = expr_term -> co [x] ]];
    END
;;

let add_biconn lev op co =
    EXTEND
      expr_term: LEVEL $lev$
      [[ x = expr_term; $op$; y = expr_term -> co [x;y] ]];
    END
;;

EXTEND
GLOBAL : expr_term;
  expr_term:
    [ "One" LEFTA [ ]
    | "Two" RIGHTA [ ]
    | "Simple" NONA
      [ x = LIDENT -> Datatype.Atom x 
      | "("; p = expr_term; ")" -> p
      ]
    ];

END

let buildParser table =
    List.iter(function
    |"Simple",op,co -> add_uconn op co
    |lev,op,co -> add_biconn lev op co
    ) table;
    let loc = Token.dummy_loc in
    let _ = Grammar.Entry.print expr_term in
    fun s ->
        Grammar.Entry.parse expr_term (Stream.of_string s)
;;


[-- Attachment #4: main.ml --]
[-- Type: text/plain, Size: 302 bytes --]


open Datatype

let inputparser = InputParser.buildParser [
    ("Simple","~",(fun l -> Not(List.hd l)) );
    ("One","&",(fun l -> And(List.hd l, List.hd(List.tl l))) );
    ("One","v",(fun l -> Or(List.hd l, List.hd(List.tl l))) );
    ] ;;

let a = inputparser "a & ( c v ~ d)" in
Datatype.print a


             reply	other threads:[~2005-07-31 13:21 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-07-31 13:21 Pietro Abate [this message]
2005-07-31 23:39 ` [Caml-list] buidlExpressionParser skaller
2005-08-01  1:45   ` Pietro Abate
2005-08-01  8:13     ` skaller
2005-08-12  7:07 ` Pietro Abate

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=20050731132119.GA368@pulp.anu.edu.au \
    --to=pietro.abate@anu.edu.au \
    --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).