summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/camlp4/Camlp4/Struct/Lexer.mll
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/camlp4/Camlp4/Struct/Lexer.mll')
-rw-r--r--ocaml-binary-annot/camlp4/Camlp4/Struct/Lexer.mll483
1 files changed, 483 insertions, 0 deletions
diff --git a/ocaml-binary-annot/camlp4/Camlp4/Struct/Lexer.mll b/ocaml-binary-annot/camlp4/Camlp4/Struct/Lexer.mll
new file mode 100644
index 0000000000..b8e97efefb
--- /dev/null
+++ b/ocaml-binary-annot/camlp4/Camlp4/Struct/Lexer.mll
@@ -0,0 +1,483 @@
+(****************************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* INRIA Rocquencourt *)
+(* *)
+(* Copyright 2006-2006 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed under *)
+(* the terms of the GNU Library General Public License, with the special *)
+(* exception on linking described in LICENSE at the top of the Objective *)
+(* Caml source tree. *)
+(* *)
+(****************************************************************************)
+
+(* Authors:
+ * - Daniel de Rauglaudre: initial version
+ * - Nicolas Pouillard: refactoring
+ *)
+
+
+
+(* The lexer definition *)
+
+
+{
+
+(** A lexical analyzer. *)
+
+(* FIXME interface module Make (Token : Token) |+ Note that this Token sig is not in Sig +| *)
+(* : Sig.Lexer. S with module Loc = Token.Loc and module Token = Token; *)
+
+(* type context =
+{ loc : Loc.t ;
+ in_comment : bool ;
+ |+* FIXME When True, all lexers built by [Plexer.make ()] do not lex the
+ quotation syntax any more. Default is False (quotations are
+ lexed). +|
+ quotations : bool };
+
+value default_context : context;
+
+value mk : Loc.t -> Stream.t char -> Stream.t (Token.t * Loc.t);
+
+value mk' : context -> Stream.t char -> Stream.t (Token.t * Loc.t); *)
+(* FIXME Beware the context argument must be given like that:
+ * mk' { (default_context) with ... = ... } strm
+ *)
+
+module TokenEval = Token.Eval
+module Make (Token : Sig.Camlp4Token)
+= struct
+ module Loc = Token.Loc
+ module Token = Token
+
+ open Lexing
+ open Sig
+
+ (* Error report *)
+ module Error = struct
+
+ type t =
+ | Illegal_character of char
+ | Illegal_escape of string
+ | Unterminated_comment
+ | Unterminated_string
+ | Unterminated_quotation
+ | Unterminated_antiquot
+ | Unterminated_string_in_comment
+ | Comment_start
+ | Comment_not_end
+ | Literal_overflow of string
+
+ exception E of t
+
+ open Format
+
+ let print ppf =
+ function
+ | Illegal_character c ->
+ fprintf ppf "Illegal character (%s)" (Char.escaped c)
+ | Illegal_escape s ->
+ fprintf ppf "Illegal backslash escape in string or character (%s)" s
+ | Unterminated_comment ->
+ fprintf ppf "Comment not terminated"
+ | Unterminated_string ->
+ fprintf ppf "String literal not terminated"
+ | Unterminated_string_in_comment ->
+ fprintf ppf "This comment contains an unterminated string literal"
+ | Unterminated_quotation ->
+ fprintf ppf "Quotation not terminated"
+ | Unterminated_antiquot ->
+ fprintf ppf "Antiquotation not terminated"
+ | Literal_overflow ty ->
+ fprintf ppf "Integer literal exceeds the range of representable integers of type %s" ty
+ | Comment_start ->
+ fprintf ppf "this is the start of a comment"
+ | Comment_not_end ->
+ fprintf ppf "this is not the end of a comment"
+
+ let to_string x =
+ let b = Buffer.create 50 in
+ let () = bprintf b "%a" print x in Buffer.contents b
+ end;;
+
+ let module M = ErrorHandler.Register(Error) in ()
+
+ open Error
+
+ (* To store some context information:
+ * loc : position of the beginning of a string, quotation and comment
+ * in_comment: are we in a comment?
+ * quotations: shall we lex quotation?
+ * If quotations is false it's a SYMBOL token.
+ * antiquots : shall we lex antiquotations.
+ *)
+
+ type context =
+ { loc : Loc.t ;
+ in_comment : bool ;
+ quotations : bool ;
+ antiquots : bool ;
+ lexbuf : lexbuf ;
+ buffer : Buffer.t }
+
+ let default_context lb =
+ { loc = Loc.ghost ;
+ in_comment = false ;
+ quotations = true ;
+ antiquots = false ;
+ lexbuf = lb ;
+ buffer = Buffer.create 256 }
+
+ (* To buffer string literals, quotations and antiquotations *)
+
+ let store c = Buffer.add_string c.buffer (Lexing.lexeme c.lexbuf)
+ let istore_char c i = Buffer.add_char c.buffer (Lexing.lexeme_char c.lexbuf i)
+ let buff_contents c =
+ let contents = Buffer.contents c.buffer in
+ Buffer.reset c.buffer; contents
+
+ let loc c = Loc.merge c.loc (Loc.of_lexbuf c.lexbuf)
+ let quotations c = c.quotations
+ let antiquots c = c.antiquots
+ let is_in_comment c = c.in_comment
+ let in_comment c = { (c) with in_comment = true }
+ let set_start_p c = c.lexbuf.lex_start_p <- Loc.start_pos c.loc
+ let move_start_p shift c =
+ let p = c.lexbuf.lex_start_p in
+ c.lexbuf.lex_start_p <- { (p) with pos_cnum = p.pos_cnum + shift }
+
+ let update_loc c = { (c) with loc = Loc.of_lexbuf c.lexbuf }
+ let with_curr_loc f c = f (update_loc c) c.lexbuf
+ let parse_nested f c =
+ with_curr_loc f c;
+ set_start_p c;
+ buff_contents c
+ let shift n c = { (c) with loc = Loc.move `both n c.loc }
+ let store_parse f c = store c ; f c c.lexbuf
+ let parse f c = f c c.lexbuf
+ let mk_quotation quotation c name loc shift =
+ let s = parse_nested quotation (update_loc c) in
+ let contents = String.sub s 0 (String.length s - 2) in
+ QUOTATION { q_name = name ;
+ q_loc = loc ;
+ q_shift = shift ;
+ q_contents = contents }
+
+
+ (* Update the current location with file name and line number. *)
+
+ let update_loc c file line absolute chars =
+ let lexbuf = c.lexbuf in
+ let pos = lexbuf.lex_curr_p in
+ let new_file = match file with
+ | None -> pos.pos_fname
+ | Some s -> s
+ in
+ lexbuf.lex_curr_p <- { pos with
+ pos_fname = new_file;
+ pos_lnum = if absolute then line else pos.pos_lnum + line;
+ pos_bol = pos.pos_cnum - chars;
+ }
+
+ let err error loc =
+ raise(Loc.Exc_located(loc, Error.E error))
+
+ let warn error loc =
+ Format.eprintf "Warning: %a: %a@." Loc.print loc Error.print error
+
+ }
+
+ let newline = ('\010' | '\013' | "\013\010")
+ let blank = [' ' '\009' '\012']
+ let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_']
+ let uppercase = ['A'-'Z' '\192'-'\214' '\216'-'\222']
+ let identchar =
+ ['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
+ let ident = (lowercase|uppercase) identchar*
+ let locname = ident
+ let not_star_symbolchar =
+ ['$' '!' '%' '&' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~' '\\']
+ let symbolchar = '*' | not_star_symbolchar
+ let quotchar =
+ ['!' '%' '&' '+' '-' '.' '/' ':' '=' '?' '@' '^' '|' '~' '\\' '*']
+ let hexa_char = ['0'-'9' 'A'-'F' 'a'-'f']
+ let decimal_literal =
+ ['0'-'9'] ['0'-'9' '_']*
+ let hex_literal =
+ '0' ['x' 'X'] hexa_char ['0'-'9' 'A'-'F' 'a'-'f' '_']*
+ let oct_literal =
+ '0' ['o' 'O'] ['0'-'7'] ['0'-'7' '_']*
+ let bin_literal =
+ '0' ['b' 'B'] ['0'-'1'] ['0'-'1' '_']*
+ let int_literal =
+ decimal_literal | hex_literal | oct_literal | bin_literal
+ let float_literal =
+ ['0'-'9'] ['0'-'9' '_']*
+ ('.' ['0'-'9' '_']* )?
+ (['e' 'E'] ['+' '-']? ['0'-'9'] ['0'-'9' '_']*)?
+
+ (* Delimitors are extended (from 3.09) in a conservative way *)
+
+ (* These chars that can't start an expression or a pattern: *)
+ let safe_delimchars = ['%' '&' '/' '@' '^']
+
+ (* These symbols are unsafe since "[<", "[|", etc. exsist. *)
+ let delimchars = safe_delimchars | ['|' '<' '>' ':' '=' '.']
+
+ let left_delims = ['(' '[' '{']
+ let right_delims = [')' ']' '}']
+
+ let left_delimitor =
+ (* At least a safe_delimchars *)
+ left_delims delimchars* safe_delimchars (delimchars|left_delims)*
+
+ (* A '(' or a new super '(' without "(<" *)
+ | '(' (['|' ':'] delimchars*)?
+ (* Old brackets, no new brackets starting with "[|" or "[:" *)
+ | '[' ['|' ':']?
+ (* Old "[<","{<" and new ones *)
+ | ['[' '{'] delimchars* '<'
+ (* Old brace and new ones *)
+ | '{' (['|' ':'] delimchars*)?
+
+ let right_delimitor =
+ (* At least a safe_delimchars *)
+ (delimchars|right_delims)* safe_delimchars (delimchars|right_delims)* right_delims
+ (* A ')' or a new super ')' without ">)" *)
+ | (delimchars* ['|' ':'])? ')'
+ (* Old brackets, no new brackets ending with "|]" or ":]" *)
+ | ['|' ':']? ']'
+ (* Old ">]",">}" and new ones *)
+ | '>' delimchars* [']' '}']
+ (* Old brace and new ones *)
+ | (delimchars* ['|' ':'])? '}'
+
+
+ rule token c = parse
+ | newline { update_loc c None 1 false 0; NEWLINE }
+ | blank + as x { BLANKS x }
+ | "~" (lowercase identchar * as x) ':' { LABEL x }
+ | "?" (lowercase identchar * as x) ':' { OPTLABEL x }
+ | lowercase identchar * as x { LIDENT x }
+ | uppercase identchar * as x { UIDENT x }
+ | int_literal as i
+ { try INT(int_of_string i, i)
+ with Failure _ -> err (Literal_overflow "int") (Loc.of_lexbuf lexbuf) }
+ | float_literal as f
+ { try FLOAT(float_of_string f, f)
+ with Failure _ -> err (Literal_overflow "float") (Loc.of_lexbuf lexbuf) }
+ | (int_literal as i) "l"
+ { try INT32(Int32.of_string i, i)
+ with Failure _ -> err (Literal_overflow "int32") (Loc.of_lexbuf lexbuf) }
+ | (int_literal as i) "L"
+ { try INT64(Int64.of_string i, i)
+ with Failure _ -> err (Literal_overflow "int64") (Loc.of_lexbuf lexbuf) }
+ | (int_literal as i) "n"
+ { try NATIVEINT(Nativeint.of_string i, i)
+ with Failure _ -> err (Literal_overflow "nativeint") (Loc.of_lexbuf lexbuf) }
+ | '"'
+ { with_curr_loc string c;
+ let s = buff_contents c in STRING (TokenEval.string s, s) }
+ | "'" (newline as x) "'"
+ { update_loc c None 1 false 1; CHAR (TokenEval.char x, x) }
+ | "'" ( [^ '\\' '\010' '\013']
+ | '\\' (['\\' '"' 'n' 't' 'b' 'r' ' ' '\'']
+ |['0'-'9'] ['0'-'9'] ['0'-'9']
+ |'x' hexa_char hexa_char)
+ as x) "'" { CHAR (TokenEval.char x, x) }
+ | "'\\" (_ as c)
+ { err (Illegal_escape (String.make 1 c)) (Loc.of_lexbuf lexbuf) }
+ | "(*"
+ { store c; COMMENT(parse_nested comment (in_comment c)) }
+ | "(*)"
+ { warn Comment_start (Loc.of_lexbuf lexbuf) ;
+ parse comment (in_comment c); COMMENT (buff_contents c) }
+ | "*)"
+ { warn Comment_not_end (Loc.of_lexbuf lexbuf) ;
+ move_start_p (-1) c; SYMBOL "*" }
+ | "<<" (quotchar* as beginning)
+ { if quotations c
+ then (move_start_p (-String.length beginning);
+ mk_quotation quotation c "" "" 2)
+ else parse (symbolchar_star ("<<" ^ beginning)) c }
+ | "<<>>"
+ { if quotations c
+ then QUOTATION { q_name = ""; q_loc = ""; q_shift = 2; q_contents = "" }
+ else parse (symbolchar_star "<<>>") c }
+ | "<@"
+ { if quotations c then with_curr_loc maybe_quotation_at c
+ else parse (symbolchar_star "<@") c }
+ | "<:"
+ { if quotations c then with_curr_loc maybe_quotation_colon c
+ else parse (symbolchar_star "<:") c }
+ | "#" [' ' '\t']* (['0'-'9']+ as num) [' ' '\t']*
+ ("\"" ([^ '\010' '\013' '"' ] * as name) "\"")?
+ [^ '\010' '\013'] * newline
+ { let inum = int_of_string num
+ in update_loc c name inum true 0; LINE_DIRECTIVE(inum, name) }
+ | '(' (not_star_symbolchar as op) ')'
+ { ESCAPED_IDENT (String.make 1 op) }
+ | '(' (not_star_symbolchar symbolchar* not_star_symbolchar as op) ')'
+ { ESCAPED_IDENT op }
+ | '(' (not_star_symbolchar symbolchar* as op) blank+ ')'
+ { ESCAPED_IDENT op }
+ | '(' blank+ (symbolchar* not_star_symbolchar as op) ')'
+ { ESCAPED_IDENT op }
+ | '(' blank+ (symbolchar+ as op) blank+ ')'
+ { ESCAPED_IDENT op }
+ | ( "#" | "`" | "'" | "," | "." | ".." | ":" | "::"
+ | ":=" | ":>" | ";" | ";;" | "_"
+ | left_delimitor | right_delimitor ) as x { SYMBOL x }
+ | '$' { if antiquots c
+ then with_curr_loc dollar (shift 1 c)
+ else parse (symbolchar_star "$") c }
+ | ['~' '?' '!' '=' '<' '>' '|' '&' '@' '^' '+' '-' '*' '/' '%' '\\'] symbolchar *
+ as x { SYMBOL x }
+ | eof
+ { let pos = lexbuf.lex_curr_p in
+ lexbuf.lex_curr_p <- { pos with pos_bol = pos.pos_bol + 1 ;
+ pos_cnum = pos.pos_cnum + 1 }; EOI }
+ | _ as c { err (Illegal_character c) (Loc.of_lexbuf lexbuf) }
+
+ and comment c = parse
+ "(*"
+ { store c; with_curr_loc comment c; parse comment c }
+ | "*)" { store c }
+ | '<' (':' ident)? ('@' locname)? '<'
+ { store c;
+ if quotations c then with_curr_loc quotation c; parse comment c }
+ | ident { store_parse comment c }
+ | "\""
+ { store c;
+ begin try with_curr_loc string c
+ with Loc.Exc_located(_, Error.E Unterminated_string) ->
+ err Unterminated_string_in_comment (loc c)
+ end;
+ Buffer.add_char c.buffer '"';
+ parse comment c }
+ | "''" { store_parse comment c }
+ | "'''" { store_parse comment c }
+ | "'" newline "'"
+ { update_loc c None 1 false 1; store_parse comment c }
+ | "'" [^ '\\' '\'' '\010' '\013' ] "'" { store_parse comment c }
+ | "'\\" ['\\' '"' '\'' 'n' 't' 'b' 'r' ' '] "'" { store_parse comment c }
+ | "'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "'" { store_parse comment c }
+ | "'\\" 'x' hexa_char hexa_char "'" { store_parse comment c }
+ | eof
+ { err Unterminated_comment (loc c) }
+ | newline
+ { update_loc c None 1 false 0; store_parse comment c }
+ | _ { store_parse comment c }
+
+ and string c = parse
+ '"' { set_start_p c }
+ | '\\' newline ([' ' '\t'] * as space)
+ { update_loc c None 1 false (String.length space);
+ store_parse string c }
+ | '\\' ['\\' '"' 'n' 't' 'b' 'r' ' ' '\''] { store_parse string c }
+ | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] { store_parse string c }
+ | '\\' 'x' hexa_char hexa_char { store_parse string c }
+ | '\\' (_ as x)
+ { if is_in_comment c
+ then store_parse string c
+ else begin
+ warn (Illegal_escape (String.make 1 x)) (Loc.of_lexbuf lexbuf);
+ store_parse string c
+ end }
+ | newline
+ { update_loc c None 1 false 0; store_parse string c }
+ | eof { err Unterminated_string (loc c) }
+ | _ { store_parse string c }
+
+ and symbolchar_star beginning c = parse
+ | symbolchar* as tok { move_start_p (-String.length beginning) c ;
+ SYMBOL(beginning ^ tok) }
+
+ and maybe_quotation_at c = parse
+ | (ident as loc) '<'
+ { mk_quotation quotation c "" loc (1 + String.length loc) }
+ | symbolchar* as tok { SYMBOL("<@" ^ tok) }
+
+ and maybe_quotation_colon c = parse
+ | (ident as name) '<'
+ { mk_quotation quotation c name "" (1 + String.length name) }
+ | (ident as name) '@' (locname as loc) '<'
+ { mk_quotation quotation c name loc
+ (2 + String.length loc + String.length name) }
+ | symbolchar* as tok { SYMBOL("<:" ^ tok) }
+
+ and quotation c = parse
+ | '<' (':' ident)? ('@' locname)? '<' { store c ;
+ with_curr_loc quotation c ;
+ parse quotation c }
+ | ">>" { store c }
+ | eof { err Unterminated_quotation (loc c) }
+ | newline { update_loc c None 1 false 0 ;
+ store_parse quotation c }
+ | _ { store_parse quotation c }
+
+ and dollar c = parse
+ | '$' { set_start_p c; ANTIQUOT("", "") }
+ | ('`'? (identchar*|['.' '!']+) as name) ':'
+ { with_curr_loc (antiquot name) (shift (1 + String.length name) c) }
+ | _ { store_parse (antiquot "") c }
+
+ and antiquot name c = parse
+ | '$' { set_start_p c; ANTIQUOT(name, buff_contents c) }
+ | eof { err Unterminated_antiquot (loc c) }
+ | newline
+ { update_loc c None 1 false 0; store_parse (antiquot name) c }
+ | '<' (':' ident)? ('@' locname)? '<'
+ { store c; with_curr_loc quotation c; parse (antiquot name) c }
+ | _ { store_parse (antiquot name) c }
+
+ {
+
+ let lexing_store s buff max =
+ let rec self n s =
+ if n >= max then n
+ else
+ match Stream.peek s with
+ | Some x ->
+ Stream.junk s;
+ buff.[n] <- x;
+ succ n
+ | _ -> n
+ in
+ self 0 s
+
+ let from_context c =
+ let next _ =
+ let tok = with_curr_loc token c in
+ let loc = Loc.of_lexbuf c.lexbuf in
+ Some ((tok, loc))
+ in Stream.from next
+
+ let from_lexbuf ?(quotations = true) lb =
+ let c = { (default_context lb) with
+ loc = Loc.of_lexbuf lb;
+ antiquots = !Camlp4_config.antiquotations;
+ quotations = quotations }
+ in from_context c
+
+ let setup_loc lb loc =
+ let start_pos = Loc.start_pos loc in
+ lb.lex_abs_pos <- start_pos.pos_cnum;
+ lb.lex_curr_p <- start_pos
+
+ let from_string ?quotations loc str =
+ let lb = Lexing.from_string str in
+ setup_loc lb loc;
+ from_lexbuf ?quotations lb
+
+ let from_stream ?quotations loc strm =
+ let lb = Lexing.from_function (lexing_store strm) in
+ setup_loc lb loc;
+ from_lexbuf ?quotations lb
+
+ let mk () loc strm =
+ from_stream ~quotations:!Camlp4_config.quotations loc strm
+end
+}