diff --git a/kiss/src/kiss/Kiss.hx b/kiss/src/kiss/Kiss.hx index 2058a0f5..79005c81 100644 --- a/kiss/src/kiss/Kiss.hx +++ b/kiss/src/kiss/Kiss.hx @@ -27,6 +27,8 @@ typedef KissState = { file:String, readTable:ReadTable, startOfLineReadTable:ReadTable, + startOfFileReadTable:ReadTable, + endOfFileReadTable:ReadTable, fieldForms:Map, specialForms:Map, macros:Map, @@ -55,6 +57,8 @@ class Kiss { file: "", readTable: Reader.builtins(), startOfLineReadTable: new ReadTable(), + startOfFileReadTable: new ReadTable(), + endOfFileReadTable: new ReadTable(), fieldForms: FieldForms.builtins(), specialForms: SpecialForms.builtins(), macros: Macros.builtins(), diff --git a/kiss/src/kiss/Macros.hx b/kiss/src/kiss/Macros.hx index cccea522..84188a3a 100644 --- a/kiss/src/kiss/Macros.hx +++ b/kiss/src/kiss/Macros.hx @@ -527,6 +527,12 @@ class Macros { case MetaExp("start", stringsExp): table = k.startOfLineReadTable; stringsThatMatch(stringsExp, "defReaderMacro"); + case MetaExp("bof", stringsExp): + table = k.startOfFileReadTable; + stringsThatMatch(stringsExp, "defReaderMacro"); + case MetaExp("eof", stringsExp): + table = k.endOfFileReadTable; + stringsThatMatch(stringsExp, "defReaderMacro"); default: stringsThatMatch(exps[0], "defReaderMacro"); }; @@ -591,6 +597,12 @@ class Macros { case MetaExp("start", stringsExp): table = k.startOfLineReadTable; stringsThatMatch(stringsExp, "undefReaderMacro"); + case MetaExp("bof", stringsExp): + table = k.startOfFileReadTable; + stringsThatMatch(stringsExp, "undefReaderMacro"); + case MetaExp("eof", stringsExp): + table = k.endOfFileReadTable; + stringsThatMatch(stringsExp, "undefReaderMacro"); default: stringsThatMatch(exps[0], "undefReaderMacro"); }; diff --git a/kiss/src/kiss/Reader.hx b/kiss/src/kiss/Reader.hx index ef598268..80e85fcd 100644 --- a/kiss/src/kiss/Reader.hx +++ b/kiss/src/kiss/Reader.hx @@ -287,8 +287,30 @@ class Reader { They can't be read all at once because some expressions change the Readtable state **/ public static function readAndProcess(stream:Stream, k:KissState, process:(ReaderExp) -> Void) { + for (key => func in k.startOfFileReadTable) { + if (stream.startsWith(key)) { + var pos = stream.position(); + stream.dropString(key); + var v = func(stream, k); + if (v != null) + process(v.withPos(pos)); + break; + } + } + while (true) { stream.dropWhitespace(); + for (key => func in k.endOfFileReadTable) { + if (stream.content == key) { + var pos = stream.position(); + stream.dropString(key); + var v = func(stream, k); + if (v != null) + process(v.withPos(pos)); + break; + } + } + if (stream.isEmpty()) break; var position = stream.position();