TUPLE: parser tex ind res enabled? ; : when% ( ? quot -- ? ) [ f ] if ; inline : ( tex -- parser ) CHAR: \0 suffix 0 0 t parser boa ; : parser-cur ( parser -- val ) [ ind>> ] [ tex>> ] bi nth ; : can-continue? ( parser -- ? ) [ ind>> 1 + ] [ tex>> ] bi bounds-check? ; : parser-next ( parser -- parser ) [ 1 + ] change-ind ; : run-and-reset ( ..a parser quot: ( ..a parser -- ..b parser ? ) -- ..b parser parsed? ) over clone [ call ] dip [ swapd ? ] keepd ; inline : match-string ( parser string -- parser parsed? ) t [ [ [ length 0 > ] dip and ] 2check ] [ drop unclip swap [ [ dup parser-cur ] dip = ] dip swap [ [ parser-next ] 2dip ] [ f ] if* ] while nip ; : match-number ( parser -- parser number/f ) [ [ dup [ can-continue? ] [ parser-cur digit? ] bi and ] [ dup parser-cur , parser-next ] while ] "" make dec> ; : match-character ( parser char -- parser parsed? ) [ dup parser-cur ] dip = [ parser-next t ] when% ; : parse-mul ( parser -- parser ) "mul(" match-string [ match-number dup [ [ CHAR: , match-character ] dip swap [ [ match-number ] dip swap [ * [ CHAR: right-parenthesis match-character ] dip swap [ [ + ] curry change-res ] [ drop ] if ] [ drop ] if* ] [ drop ] if ] [ drop ] if ] when ; : mul-parse ( parser -- parser ) [ dup can-continue? ] [ dup parser-cur CHAR: m = [ parse-mul ] [ parser-next ] if ] while ; : solve-day-three ( string -- result ) mul-parse res>> ; : parse-dodont-or-other ( parser -- parser ) [ "do()" match-string ] run-and-reset [ t >>enabled? ] [ "don't()" match-string [ f >>enabled? ] [ parser-next ] if ] if ; : dodont-parse ( parser -- parser ) [ dup can-continue? ] [ dup [ enabled?>> ] [ parser-cur CHAR: m = ] bi and [ parse-mul ] [ parse-dodont-or-other ] if ] while ; : solve-day-three-part-two ( string -- result ) dodont-parse res>> ;