diff options
author | Vladimir Azarov <avm@intermediate-node.net> | 2025-04-04 18:24:46 +0200 |
---|---|---|
committer | Vladimir Azarov <avm@intermediate-node.net> | 2025-04-04 18:24:46 +0200 |
commit | 7b29b31648fd737e7bbc007f480b799add91bc6b (patch) | |
tree | e724c15c959d98ece73c186b82a61100f4e8d06a /cpp.sml | |
parent | d7d4830443f1e385af862462f976553c8a9033e1 (diff) |
Beginning of the preprocessor
Diffstat (limited to 'cpp.sml')
-rw-r--r-- | cpp.sml | 104 |
1 files changed, 94 insertions, 10 deletions
@@ -1,11 +1,95 @@ -fun main [fname] = -let - val stream = Stream.streamInit fname - val tkl = Tokenizer.tokenize stream - val fileInfo = Stream.convert stream -in - Tokenizer.printTokens tkl (#2 fileInfo) -end - | main _ = printLn "Expected a signle argument: file name" +structure Cpp:> CPP = struct + type tkPos = Stream.pos + + type t = + { streams: Stream.t list, fileInfo: Stream.fileInfo list, + lastPos: tkPos option, firstId: Stream.fileId }; + + datatype tkExp = + Tk of Tokenizer.token | + Id | + NumConst | + StrLiteral | + UnOp | + BinOp | + Op + + type tkExpectedValue = string * tkExp list + + exception StreamTooOld + exception TkExpected of tkExpectedValue + + fun create fname = + let + val stream = Stream.create fname + val info = Stream.convert stream + in + { streams = [stream] , fileInfo = [info], lastPos = NONE, firstId = #1 info } + end -val () = main $ CommandLine.arguments () + fun getToken + ({ streams = stream :: tail, fileInfo, lastPos, firstId }: t) = + let + val (tk, stream) = Tokenizer.getToken stream + in + case tk of + NONE => getToken { streams = tail, fileInfo, lastPos, firstId } + | SOME (pos, tk) => + ( tk, { streams = stream :: tail, fileInfo, + lastPos = SOME pos, firstId }) + end + | getToken + { streams = [], fileInfo, lastPos = SOME lastPos, firstId } = + let + val pos = SOME (#1 lastPos, ~1) (* EOF *) + in + (Tokenizer.EOS, {streams = [], fileInfo, lastPos = pos, firstId }) + end + | getToken { streams = [], fileInfo, lastPos = NONE, firstId } = + (Tokenizer.EOS, { streams = [], fileInfo, + lastPos = SOME (firstId, ~1), firstId }) + + fun getLastPos ({ lastPos = NONE, ... }: t) = raise Unreachable + | getLastPos { lastPos = SOME p, ... } = p + + val tkExp2str = fn + (Tk tk) => Tokenizer.token2str tk + | Id: tkExp => "identifier" + | NumConst => "numeric constant" + | StrLiteral => "string literal" + | UnOp => "unary operator" + | BinOp => "binary operator" + | Op => "operator" + + fun prepAndRaise (stream: t) (id, pos) expList = + let + val fileInfo = + case List.find (fn (id', _, _) => id' = id) $ #fileInfo stream of + NONE => raise StreamTooOld + | SOME fileInfo => fileInfo + val pos = Stream.ppos2str $ Stream.pos2pposWithFI (id, pos) fileInfo + in + raise TkExpected (pos, expList) + end + + fun tkExpectedPrint (pos, expList) = + let + fun tkExps2str [e] [] = tkExp2str e + | tkExps2str [e] acc = + (String.concatWith ", " acc ^ " or ") ^ tkExp2str e + | tkExps2str (e :: ec) acc = + tkExps2str ec (tkExp2str e :: acc) + | tkExps2str [] _ = raise Unreachable + in + print pos; + print ":expected "; + printLn $ tkExps2str expList [] + end + + fun debugPrint fname = + let + val stream = create fname + in + () + end +end |