src/Pure/ML/ml_parse.ML
author wenzelm
Sat, 23 Jul 2011 16:37:17 +0200
changeset 44818 9b00f09f7721
parent 30697 dcb233670c98
child 44819 8f5add916a99
permissions -rw-r--r--
defer evaluation of Scan.message, for improved performance in the frequent situation where failure is handled later (e.g. via ||);
wenzelm@24594
     1
(*  Title:      Pure/ML/ml_parse.ML
wenzelm@24594
     2
    Author:     Makarius
wenzelm@24594
     3
wenzelm@24594
     4
Minimal parsing for SML -- fixing integer numerals.
wenzelm@24594
     5
*)
wenzelm@24594
     6
wenzelm@24594
     7
signature ML_PARSE =
wenzelm@24594
     8
sig
wenzelm@24594
     9
  val fix_ints: string -> string
wenzelm@30687
    10
  val global_context: use_context
wenzelm@24594
    11
end;
wenzelm@24594
    12
wenzelm@24594
    13
structure ML_Parse: ML_PARSE =
wenzelm@24594
    14
struct
wenzelm@24594
    15
wenzelm@24594
    16
(** error handling **)
wenzelm@24594
    17
wenzelm@24594
    18
fun !!! scan =
wenzelm@24594
    19
  let
wenzelm@24594
    20
    fun get_pos [] = " (past end-of-file!)"
wenzelm@30697
    21
      | get_pos (tok :: _) = Position.str_of (ML_Lex.pos_of tok);
wenzelm@24594
    22
wenzelm@44818
    23
    fun err (toks, NONE) = (fn () => "SML syntax error" ^ get_pos toks)
wenzelm@44818
    24
      | err (toks, SOME msg) = (fn () => "SML syntax error" ^ get_pos toks ^ ": " ^ msg ());
wenzelm@24594
    25
  in Scan.!! err scan end;
wenzelm@24594
    26
wenzelm@24594
    27
fun bad_input x =
wenzelm@30697
    28
  (Scan.some (fn tok => (case ML_Lex.kind_of tok of ML_Lex.Error msg => SOME msg | _ => NONE)) :|--
wenzelm@44818
    29
    (fn msg => Scan.fail_with (K (fn () => msg)))) x;
wenzelm@24594
    30
wenzelm@24594
    31
wenzelm@24594
    32
(** basic parsers **)
wenzelm@24594
    33
wenzelm@27817
    34
fun $$$ x =
wenzelm@30697
    35
  Scan.one (fn tok => ML_Lex.kind_of tok = ML_Lex.Keyword andalso ML_Lex.content_of tok = x)
wenzelm@30697
    36
    >> ML_Lex.content_of;
wenzelm@24594
    37
wenzelm@30697
    38
val int = Scan.one (fn tok => ML_Lex.kind_of tok = ML_Lex.Int) >> ML_Lex.content_of;
wenzelm@30697
    39
wenzelm@30697
    40
val regular = Scan.one ML_Lex.is_regular >> ML_Lex.content_of;
wenzelm@30697
    41
val improper = Scan.one ML_Lex.is_improper >> ML_Lex.content_of;
wenzelm@24594
    42
wenzelm@24594
    43
val blanks = Scan.repeat improper >> implode;
wenzelm@24594
    44
wenzelm@24594
    45
wenzelm@24594
    46
(* fix_ints *)
wenzelm@24594
    47
wenzelm@24594
    48
(*approximation only -- corrupts numeric record field patterns *)
wenzelm@24594
    49
val fix_int =
wenzelm@24594
    50
  $$$ "#" ^^ blanks ^^ int ||
wenzelm@24594
    51
  ($$$ "infix" || $$$ "infixr") ^^ blanks ^^ int ||
wenzelm@24594
    52
  int >> (fn x => "(" ^ x ^ ":int)") ||
wenzelm@24594
    53
  regular ||
wenzelm@24594
    54
  bad_input;
wenzelm@24594
    55
wenzelm@24594
    56
fun do_fix_ints s =
wenzelm@24594
    57
  Source.of_string s
wenzelm@30697
    58
  |> ML_Lex.source
wenzelm@30697
    59
  |> Source.source ML_Lex.stopper (Scan.bulk (!!! fix_int)) NONE
wenzelm@24594
    60
  |> Source.exhaust
wenzelm@24594
    61
  |> implode;
wenzelm@24594
    62
wenzelm@24594
    63
val fix_ints = if ml_system_fix_ints then do_fix_ints else I;
wenzelm@24594
    64
wenzelm@30687
    65
wenzelm@30687
    66
(* global use_context *)
wenzelm@30687
    67
wenzelm@30687
    68
val global_context: use_context =
wenzelm@30687
    69
 {tune_source = fix_ints,
wenzelm@30687
    70
  name_space = ML_Name_Space.global,
wenzelm@30687
    71
  str_of_pos = Position.str_of oo Position.line_file,
wenzelm@30687
    72
  print = writeln,
wenzelm@30687
    73
  error = error};
wenzelm@30687
    74
wenzelm@24594
    75
end;