@@ -58,6 +58,7 @@ type error =
5858 | Illegal_character of char
5959 | Illegal_escape of string
6060 | Unterminated_comment of Location .t
61+ | Unmatched_nested_comment of Location .t
6162 | Unterminated_string
6263 | Unterminated_string_in_comment of Location .t * Location .t
6364 | Keyword_as_label of string
@@ -165,6 +166,8 @@ let get_stored_string () =
165166(* To store the position of the beginning of a string and comment *)
166167let string_start_loc = ref Location. none;;
167168let comment_start_loc = ref [] ;;
169+ let line_comment_start_loc = ref [] ;;
170+ let single_line_comment = ref false ;;
168171let in_comment () = ! comment_start_loc <> [] ;;
169172let is_in_string = ref false
170173let in_string () = ! is_in_string
@@ -264,6 +267,8 @@ let report_error ppf = function
264267 fprintf ppf " Illegal backslash escape in string or character (%s)" s
265268 | Unterminated_comment _ ->
266269 fprintf ppf " Comment not terminated"
270+ | Unmatched_nested_comment _ ->
271+ fprintf ppf " Unmatched nested comment"
267272 | Unterminated_string ->
268273 fprintf ppf " String literal not terminated"
269274 | Unterminated_string_in_comment (_ , loc ) ->
@@ -417,6 +422,17 @@ rule token = parse
417422 let esc = String.sub l 1 (String.length l - 1) in
418423 raise (Error(Illegal_escape esc, Location.curr lexbuf))
419424 }
425+ | " // "
426+ { let start_loc = Location.curr lexbuf in
427+ single_line_comment := true;
428+ line_comment_start_loc := [start_loc];
429+ reset_string_buffer ();
430+ let end_loc = comment lexbuf in
431+ let s = get_stored_string () in
432+ reset_string_buffer ();
433+ COMMENT (s, { start_loc with
434+ Location.loc_end = end_loc.Location.loc_end })
435+ }
420436 | " /* "
421437 { let start_loc = Location.curr lexbuf in
422438 comment_start_loc := [start_loc];
@@ -541,15 +557,33 @@ rule token = parse
541557 }
542558
543559and comment = parse
544- " /*"
545- { comment_start_loc := (Location .curr lexbuf ) :: ! comment_start_loc;
560+ | " /*"
561+ {
562+ comment_start_loc := (Location .curr lexbuf ) :: ! comment_start_loc;
546563 store_lexeme lexbuf;
547564 comment lexbuf;
548565 }
549566 | " */"
550- { match ! comment_start_loc with
551- | [] -> assert false
552- | [_] -> comment_start_loc := []; Location. curr lexbuf
567+ {
568+ match ! comment_start_loc with
569+ | [] ->
570+ (* If it's part of a single line comment, we should raise an
571+ * unterminated nested comment error *)
572+ if ! single_line_comment then (
573+ let loc = Location. curr lexbuf in
574+ let start = List. hd (List. rev ! line_comment_start_loc) in
575+ raise (Error (Unmatched_nested_comment loc, start))
576+ )
577+ else assert false
578+ | [_] ->
579+ if ! single_line_comment then (
580+ comment_start_loc := [] ;
581+ store_lexeme lexbuf;
582+ comment lexbuf;
583+ )
584+ else (
585+ comment_start_loc := [] ; Location. curr lexbuf
586+ )
553587 | _ :: l -> comment_start_loc := l ;
554588 store_lexeme lexbuf;
555589 comment lexbuf;
@@ -619,9 +653,27 @@ and comment = parse
619653 raise (Error (Unterminated_comment start, loc))
620654 }
621655 | newline
622- { update_loc lexbuf None 1 false 0 ;
623- store_lexeme lexbuf;
624- comment lexbuf
656+ {
657+ if not ! single_line_comment then (
658+ update_loc lexbuf None 1 false 0 ;
659+ store_lexeme lexbuf;
660+ comment lexbuf
661+ )
662+ else (
663+ (* check if there are any unmatched nested comments *)
664+ match ! comment_start_loc with
665+ | [] -> (
666+ (* reset since we're done parsing a single line comment *)
667+ single_line_comment := false ;
668+ match ! line_comment_start_loc with
669+ | [] -> assert false
670+ | _ -> line_comment_start_loc := [] ; Location. curr lexbuf
671+ )
672+ | _ ->
673+ let start = List. hd (List. rev ! comment_start_loc) in
674+ comment_start_loc := [] ;
675+ raise (Error (Unmatched_nested_comment start, Location. curr lexbuf))
676+ )
625677 }
626678 | _
627679 { store_lexeme lexbuf; comment lexbuf }
0 commit comments