На самом деле здесь ничего уникального в expect. За ним стоит
простейшая идея: циклический буфер на N килобайт, в него постоянно
добавляются вновь принятые данные, что не влезло -- откидывается с
конца. И по этому буферу ищем регэкспы. Такое можно руками сделать
в любом языке. А каждый "оператор" expect -- это по-сути while(1) с
дочитыванием сколько есть в буфер. Другое дело, что такой подход не
эффективен. Ты будешь каждый раз с начала буфера всё парсить
заново... Есть так называемые PEG-парсеры, работающие не с дискретными описаниями синтаксиса и грамматики на каких-либо языках, а прямо сразу с регэкспами, которые заменяют и синтаксис и грамматику. Верней, нужен packrat-парсер, который обычно спрятан внутри PEG-парсера. Фактически это такой способ оптимизировать парсер рекурсивного спуска, ценой существенно большего расхода памяти, что он начинает работать за линейное время, а не экспоненциальное (и те же регэкспы будут не 100500 раз одни и те же символы просматривать, а условно однократно).
И взяв любой язык программирования (для C++ есть масса вариантов) и PEG-парсер, можно легко построить в итоге свой expect. Тут мне сразу вспомнился страшный японский проект (но он сырой и бажный, зато сделано круто): https://github.com/yhirose/cpp-peglib И есть более зрелый проект: https://github.com/taocpp/PEGTL
Даже в Tcl есть:
https://wiki.tcl-lang.org/page/PEG+Example
https://core.tcl-lang.org/tcllib/doc/trunk/embedded/md/tcllib/files/modules/pt/pt_introduction.md
О PEG:
https://en.wikipedia.org/wiki/Parsing_expression_grammar
https://habr.com/ru/post/471860/
https://stackoverflow.com/questions/1410477/what-is-packrat-parsing
https://pdos.csail.mit.edu/~baford/packrat/icfp02/