From 226f58656b4b7f92f6de9a817ab9106937e061e9 Mon Sep 17 00:00:00 2001 From: Vladimir Azarov Date: Mon, 24 Mar 2025 22:37:21 +0100 Subject: Simplified stream --- stream.sml | 155 ++++++++++++++++--------------------------------------------- 1 file changed, 40 insertions(+), 115 deletions(-) (limited to 'stream.sml') diff --git a/stream.sml b/stream.sml index 10b02cc..92deb61 100644 --- a/stream.sml +++ b/stream.sml @@ -2,20 +2,12 @@ structure Stream :> STREAM = struct type fileId = int type fileOffset = int type pos = fileId * fileOffset - type convPos = string * int * int option + type ppos = string * int * int option + type fileInfo = fileId * string * string - type filesInfo = (fileId * string * string) list + exception UngetcError - exception EndOfStream - exception EndOfFile - - (* unreachable *) - exception InvalidStream - exception InvalidStreamAdvance - - exception LineWithoutNl - - fun pos2str (pos, line, col) = + fun ppos2str (pos, line, col) = let val % = Int.toString in @@ -24,14 +16,9 @@ structure Stream :> STREAM = struct | NONE => pos ^ ":" ^ %line end - type t = { - (* stack of file ids, file offsets and file contents *) - stack: (fileId * fileOffset * string) list, - (* list of file ids, file names and file contents *) - allFiles: filesInfo - } + type t = fileId * string * fileOffset * string - fun extractFilesInfo (s: t) = #allFiles s + fun recycle (fid, fname, _, contents) = (fid, fname, contents) fun calcFilePos s offset = let @@ -46,20 +33,13 @@ structure Stream :> STREAM = struct calc s 0 offset (1, 1) end - fun printPos fileList (id, pos) = + fun printPos (_, fname, contents) (_, pos) = let - val triple = List.find (fn (fid, _, _) => fid = id) fileList + val (line, col) = calcFilePos contents pos + val line = Int.toString line + val col = Int.toString col in - case triple of - NONE => raise InvalidStream - | SOME (_, fname, contents) => - let - val (line, col) = calcFilePos contents pos - val line = Int.toString line - val col = Int.toString col - in - print $ fname ^ ":" ^ line ^ ":" ^ col ^ ": " - end + print $ fname ^ ":" ^ line ^ ":" ^ col ^ ": " end fun readFile fname = @@ -72,114 +52,59 @@ structure Stream :> STREAM = struct s end - fun getchar - ({ stack = (id, off, contents) :: rest, allFiles }: t) - : (char * t) = + fun getchar (S as (fid, fname, off, contents)) = if off < String.size contents then - (String.sub (contents, off), - { stack = (id, off + 1, contents) :: rest, allFiles }) + (SOME $ String.sub (contents, off), (fid, fname, off + 1, contents)) else - raise EndOfFile - | getchar _ = raise EndOfStream + (NONE, S) - fun ungetc - ({ stack = (id, off, contents) :: rest, allFiles }) = + fun ungetc (fid, fname, off, contents) = if off = 0 then - raise InvalidStream + raise UngetcError else - { stack = (id, off - 1, contents) :: rest, allFiles } - | ungetc _ = raise InvalidStream - - fun readline { stack = (fid, off, contents) :: rest, allFiles } = - let - val prevIsSlash = - off > 0 andalso String.sub (contents, off - 1) = #"\\" - - open String - fun read prevIsSlash offset acc = - let - val c = sub (contents, offset) - in - if offset = size contents then - raise LineWithoutNl - else if c = #"\n" then - if prevIsSlash then - read (c = #"\\") (offset + 1) (#" " :: tl acc) - else - (implode $ rev acc, offset + 1) - else - read (c = #"\\") (offset + 1) (c :: acc) - end - - val (arg, newOffset) = read prevIsSlash off [] - in - (arg, { stack = (fid, newOffset, contents) :: rest, allFiles }) - end - | readline _ = raise InvalidStream + (fid, fname, off - 1, contents) - fun getOffset ({ stack = (_, off, _) :: _, ... }: t) = off - | getOffset _ = raise InvalidStream + fun getOffset (_, _, off, _) = off - fun getPosAfterCharRead - ({ stack = (id, off, _) :: _, ... }: t) = (id, off - 1) - | getPosAfterCharRead _ = raise InvalidStream + fun getPosAfterCharRead (fid, _, off, _) = (fid, off - 1) - fun getPposFromPos (id, pos) - { stack = (_, _, _) :: _, allFiles} = + fun getPposFromPos (_, pos) (_, fname, _, contents) = let - val (fname, contents) = - case List.find (fn (fid, _, _) => fid = id) allFiles of - NONE => raise InvalidStream - | SOME (_, fname, contents) => (fname, contents) - val (line, col) = calcFilePos contents pos in (fname, line, SOME col) end - | getPposFromPos _ _ = raise InvalidStream - fun getPos ({ stack = (id, off, _) :: _, ... }: t) = (id, off) - | getPos _ = raise InvalidStream + fun pposWithoutCol (fname, line, SOME _) = (fname, line, NONE) + | pposWithoutCol (_, _, NONE) = raise Unreachable - fun getSubstr startOff endOff - ({ stack = (_, _, contents) :: _, ... }: t) = - String.substring (contents, startOff, endOff - startOff) - | getSubstr _ _ _ = raise InvalidStream + fun getPos (id, _, off, _) = (id, off) - fun advanceToNewFile - ({ stack = (_, off, contents) :: rest, allFiles }: t) = - if off = String.size contents then - { stack = rest, allFiles } - else - raise InvalidStreamAdvance - | advanceToNewFile _ = raise InvalidStreamAdvance + fun getSubstr startOff endOff (_, _, _, contents) = + String.substring (contents, startOff, endOff - startOff) fun streamInit fname = let val contents = readFile fname in - { allFiles = [(0, fname, contents)], stack = [(0, 0, contents)] } + (0, fname, 0, contents) end - fun isFirstOnLine (id, offset) (stream: t) = - case List.find (fn (fid, _, _) => id = fid) (#allFiles stream) of - NONE => raise InvalidStream - | SOME (_, _, contents) => + fun isFirstOnLine (_, offset) ((_, _, _, contents) : t) = + let + fun returnToNL ~1 = true + | returnToNL offset = let - fun returnToNL ~1 = true - | returnToNL offset = - let - val chr = String.sub (contents, offset) - in - if chr = #"\n" then - true - else if Char.isSpace chr then - returnToNL (offset - 1) - else - false - end + val chr = String.sub (contents, offset) in - returnToNL (offset - 1) + if chr = #"\n" then + true + else if Char.isSpace chr then + returnToNL (offset - 1) + else + false end - + in + returnToNL (offset - 1) + end end -- cgit v1.2.3