| 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 ?
>
>
>
>
>
>
>
>