Re: Clean way to set Lexing.pos_fname field ?

"Gabriel Scherer [email protected] [ocaml_beginners]" <[email protected]>
Newsgroups gmane.comp.lang.ocaml.beginners
Message-ID <CAPFanBHZNRcMd9dMk5FbbnaT5j50+Z57pLkrpET5VwPaoHGDzw@mail.gmail.com>
> Why doesn't Ocaml automatically set it for me when Lexing.from_channel is
called ?

An input_channel may not come from a file in the filesystem, so it does not
contain the necessary information. (Also you may want to report location in
a file different that the one actually read, if it is generated from
somewhere else)

The usual way is to set lex_curr_p before the start of the lexing phase to
contain the information you want. Typically you will do something like:

    lexbuf.Lexing.lex_curr_p <- {
      Lexing.pos_fname = file_name;
      pos_lnum = 1;
      pos_bol = 0;
      pos_cnum = 0;
    }

The lexer will then preserve this location information. This is documented
in the manual:
  http://caml.inria.fr/pub/docs/manual-ocaml/libref/Lexing.html

At each token, the lexing engine will copy lex_curr_p to lex_start_p, then
> change the pos_cnum field of lex_curr_p by updating it with the number of
> characters read since the start of the lexbuf. The other fields are left
> unchanged by the lexing engine. In order to keep them accurate, they must
> be initialised before the first use of the lexbuf, and updated by the
> relevant lexer actions (i.e. at each end of line -- see also new_line).
>

On Mon, Oct 5, 2015 at 10:55 AM, [email protected] [ocaml_beginners]
<[email protected]> wrote:

>
>
> Here is a minimal example showing my problem, it uses just one
> silly_lexer.mll file, whose contents are :
>
> {
>     let accu=ref[]
>     let add_to_accu x=(accu:=x::(!accu));;
> }
>
> rule silly_parse = parse
>    _ as c
>       {  add_to_accu (c,Lexing.lexeme_start_p lexbuf); silly_parse lexbuf}
>   | eof { List.rev(!accu) }
>
> {
>
> let parse_file fn=
>           let _=(accu:=[]) in
>           let in_channel=open_in fn in
>           let answer=silly_parse (Lexing.from_channel in_channel) in
>           close_in in_channel; answer
>
> }
>
> I execute ocamllex silly_lexer.mll, enter my toplevel and type
>
>         OCaml version 4.02.1
>
> # #use"silly_lexer.ml";;
> (...)
> # let example=parse_file "silly_lexer.ml";;
> val example : (char * Lexing.position) list =
>   [('#', {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 0});
>    (' ', {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 1});
>    ('1', {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 2});
>    (' ', {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 3});
>    ('"', {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 4});
>    ('s', {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 5});
>
> Notice how the Lexing.pos_fname is set to "" rather "silly_lexer.ml".
>
>
>  Sure, I know how to manually set this Lexing.pos_fname field, but I can't
> help
>  feeling that this is not the clean way to do things. Why doesn't Ocaml
>  automatically set it for me when Lexing.from_channel is called ? What am
> I missing ?
>
>
>
>
>
>
> 
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.