123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118(*
* CharParser - Parsing character strings
* Copyright (C) 2008 David Teller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)openBatParserCo(** {6 Entry point} *)typeposition={offset:int;line:int}letstart_position={offset=1;line=1}letadvancecp=ifBatChar.is_newlinecthen((*Printf.eprintf "[Have reached line %i]\n%!" (p.line + 1);*){offset=1;line=p.line+1})else{(p)withoffset=p.offset+1}letsource_of_enums=Source.of_enumsstart_position advanceletsource_of_strings=source_of_enum(BatString.enums)letparseps=runp(source_of_strings)(*let parse_enum p e =
let latest = ref "" in
let lines = lines_of (input_enum e) in
let chars = BatEnum.concat (BatEnum.from (fun () -> match get lines with
| None -> raise BatEnum.No_more_elements
| Some l -> latest := l;
String.enum l)) in
let source = source_of_enum chars in
match run p source with
| Std.Ok _ as result -> result
| Std.Error report -> Std.Error (report, ?(*Furthest position*), ?(*List of labels at that point*), !latest)*)(** {6 Utilities}*)letcharc=label("\""^BatString.of_charc^"\"")(exactlyc)letstrings=label("\""^s^"\"")(let len=String.lengthsinlet recauxi=ifi<lenthenexactlys.[i]>>=fun_->aux(i+1)else returnsinaux0)letcase_char c=ifBatChar.is_lettercthenone_of##V<5##[Char.uppercasec;Char.lowercase c]##V>=5##[Char.uppercase_ascii c;Char.lowercase_asciic]elsecharcletcase_strings=label("case insensitive \""^s^"\"")(lets'=##V<5##String.lowercase##V>=5##String.lowercase_asciisinletlen =String.lengths'inletrecauxi=ifi<lenthencase_chars'.[i]>>=fun_->aux(i+1)elsereturnsinaux0)letwhitespace=satisfyBatChar.is_whitespaceletuppercase=label"upper case char"(satisfyBatChar.is_uppercase)letlowercase=label"lower case char"(satisfyBatChar.is_lowercase)letletter=label "letter"(satisfy BatChar.is_letter)letuppercase_latin1=label"upper case char (possibly accentuated)"(satisfyBatChar.is_uppercase_latin1)letlowercase_latin1=label"lower case char (possibly accentuated)"(satisfyBatChar.is_lowercase_latin1)letlatin1=label"letter (possibly accentuated)"(satisfyBatChar.is_latin1)letdigit=label"digit"(satisfyBatChar.is_digit)lethex=label "hex"(satisfy(funx->('0'<=x&&x<='9')||('a'<=x&&x<='f')||('A'<=x&&x<='F')))let not_charc=label("anything but '"^BatString.of_charc^"'")(satisfy (funx->x<>c)(*>>=
fun x -> Printf.eprintf "(%c)\n" x; return x*))letnone_ofl=label(BatString.of_list (BatVect.to_list (BatVect.append']'(List.fold_left(funaccx->BatVect.appendxacc)(BatVect.of_list (BatString.to_list"anything but ['"))l))))(none_of l)letnewline=satisfyBatChar.is_newline