create data 20000 allot \ create a 20K buffer variable fileid \ create a variable `fileid` s" data/03.txt" r/o open-file \ open data file drop \ drop the top value from the stack, it's just a status code and we aren't going to bother handling errors fileid ! \ save the file id to the variable variable data-len data 20000 fileid @ read-file drop data-len ! : data-str ( -- addr u ) data data-len @ ; : chop-prefix ( addr u u2 -- addr2 u2 ) \ chop the first `u2` bytes off the beginning of the string at `addr u` tuck \ duplicate `u2` and store it "under" the length of the string - \ subtract `u2` from the length of the string -rot \ stick the new string length underneath the start pointer + \ increment the start pointer by `u2` swap \ put them back in the right order ; require regexp.fs : mul-instr ( addr u -- flag ) (( =" mul(" \( {++ \d ++} \) ` , \( {++ \d ++} \) ` ) )) ; : get-product ( addr u -- u2 ) mul-instr \ match the string from `addr u` against the above regex if \ if the regex matches, then: \1 s>number drop \ convert the first capture from string to number, drop the status code (we already know it will succeed) \2 s>number drop \ convert the second capture from string to number, drop the status code * \ multiply, and leave the answer on the stack else 0 \ otherwise, leave 0 on the stack then ; variable result 0 result ! : sum-mul-instrs ( addr u -- u2 ) begin \ start looping s" mul(" search \ search for the string "mul(" if \ if successful, top 2 values on stack will be start address of "mul(" and remainder of original string 2dup \ duplicate address and remaining length of string get-product \ pass those to get-product above result @ + \ load `result` and add to product result ! \ store this new value back in `result` 4 chop-prefix \ bump the start of the string by 4 characters else \ if not successful, we have finished scanning through the string 2drop \ dump the string address and length result @ exit \ put the result on top of the stack and return to caller then again ; data-str sum-mul-instrs . bye