Simulate a Minsky Register Machine (I) There are many formalisms, so while you may find other sources useful I hope to specify this clearly enough that they're not necessary.

A RM consists of a finite state machine and a finite number of named registers, each of which holds a non-negative integer. For ease of textual input this task requires that the states also be named.

There are three types of state: increment and decrement, which both reference a specific register; and terminate. An increment state increments its register and passes control to its one successor. A decrement state has two successors: if its register is non-zero then it decrements it and passes control to the first successor; otherwise (i.e. register is zero) it simply passes control to the second successor.

For "niceness" as a programming language, the terminate states take a hard-coded string to print (so you can indicate exceptional termination).

Input is from stdin. The input format consists of one line per state, followed by the initial register contents. The first line is the initial state. BNF for the state lines is:

line       ::= inc_line
             | dec_line
inc_line   ::= label ' : ' reg_name ' + ' state_name
dec_line   ::= label ' : ' reg_name ' - ' state_name ' ' state_name
state_name ::= label
             | '"' message '"'
label      ::= identifier
reg_name   ::= identifier


There is some flexibility in the definition of identifier and message. Your program must accept a non-empty alphanumeric string as an identifier, but it may accept more general strings if you prefer (e.g. if your language supports identifiers with underscores and that's easier for you to work with). Similarly, for message you must accept a non-empty string of alphanumerics and spaces, but you may accept more complex strings which allow escaped newlines and double-quote characters if you want.

The final line of input, which gives the initial register values, is a space-separated list of identifier=int assignments, which must be non-empty. It is not required that it initialise all registers named in the program: any which aren't initialised are assumed to be 0.

Your program should read the input and simulate the RM. When it reaches a terminate state it should emit the message, a newline, and then the values of all the registers (in any convenient, human-readable, format, and any order).

Note: formally the registers should hold unbounded integers. However, you may if you wish assume that no register's value will ever exceed 2^30.

Some simple examples

a+=b, a=0

s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4


Expected results:

Ok
a=0 b=7


b+=a, t=0

init : t - init d0
d0 : a - d1 a0
d1 : b + d2
d2 : t + d0
a0 : t - a1 "Ok"
a1 : a + a0
a=3 b=4


Expected results:

Ok
a=3 b=7 t=0


Test cases for trickier-to-parse machines

s0 : t - s0 s1
s1 : t + "t is 1"
t=17


Expected results:

t is 1
t=1


and

s0 : t - "t is nonzero" "t is zero"
t=1


Expected results:

t is nonzero
t=0


A more complicated example

Taken from the DailyWTF's Josephus problem code challenge. Input is n (number of soldiers) and k (advance) and output in r is the (zero-indexed) position of the person who survives.

init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3


Expected results:

Ok
i=40 k=3 n=0 r=27 t=0


That program as a picture, for those who think visually and would find it helpful to grasp the syntax: 


If you enjoyed this golf, have a look at the sequel.
Perl, 166

@p=&lt;&gt;;/=/,$_{$`}=$' for split$",pop@p;$o='\w+';(map{($r
,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p),$_=$o=($_{$r}
+=','cmp$o)&lt;0?do{$_{$r}=0;$b}:$,until/"/;say for eval,%_


Run with perl -M5.010 file.

It started wildly different, but I'm afraid it converged with the Ruby solution in many areas towards the end.  Seems like Ruby's advantage is "no sigils", and Perl's "better regex integration".

A bit of detail from the innards, if you don't read Perl:


@p=&lt;&gt;: read the whole machine description to @p
/=/,$_{$`}=$' for split$",pop@p: for each (for) assignment (split$") in the last machine description line (@p), locate equal sign (/=/) then assign value $' to hask %_ key $`
$o='\w+': initial state would be first one to match Perl regex "word characters"
until/"/: loop until we reach a termination state:

map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p: loop on machine description @p: when we're on the line matching current state (if/^$o :/), tokenize (/".*?"|\S+/g) the rest of the line $' to variables ($r,$o,$,,$b).  Trick: the same variable $o if used initially for label name and subsequently for operator.  As soon as the label matches, the operator overrides it, and as a label can't (reasonably) be named + or -, it never matches again.
$_=$o=($_{$r}+=','cmp$o)&lt;0?do{$_{$r}=0;$b}:$,:- adjust target register $_{$r} up or down (ASCII magic: ','cmp'+' is 1 whereas ','cmp'-' is -1);- if the result is negative (&lt;0?, can only happens for -)- then stay at 0 ($_{$r}=0) and return second label $b;- else return first (possibly sole) label $,
BTW, it's $, instead of $a so it can be glued to next token until with no whitespace in between.

say for eval,%_: dump report (eval) and contents of registers in %_