Make a Snake Parser! Snakes look like this:
      &gt;&gt;&gt;v
@     ^  v
^  &gt;&gt;&gt;^  v
^        v
^&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;

The snake can cross over itself as in this case:
 @
 ^
&gt;^&gt;v
 ^&lt;&lt;

For a crossover to be valid, the characters on either side must be moving the same direction. The case of
 @
&gt;^v
 ^&lt;

can be considered unclear and invalid.
The output is a string of WASD representing going from the head to the tail  (@).
Given a snake that doesn't backtrack and isn't ambiguous, can you write a program that will output the string of moves that the snake takes?
This is code-golf, so shortest answer wins!
Test cases:
(Note: The @ can be replaced with any character not in v^&lt;&gt;)
Input:
&gt;&gt;&gt;&gt;v
    v
  v&lt;&lt;  @
  v    ^
  &gt;&gt;&gt;&gt;&gt;^

Output: ddddssaassdddddww

Input:
@&gt;&gt;v
^  v
^  v
^&lt;&lt;&lt;

Output: dddsssaaawww

Input:
&gt;&gt;&gt;v
   v       @
   v       ^
   &gt;&gt;&gt;&gt;v   ^
       &gt;&gt;&gt;&gt;^

Output: dddsssddddsddddwww

Input:
@&lt;&lt; v
  ^ v
v&lt;^&lt;&lt;
v ^
&gt;&gt;^

Output: ssaaaassddwwwwaa

Input:
@v&lt;v
^v^v
^v^&lt;
^&lt;

Output: ssawwasssawww
Java, 626 539 536 529 bytes

-87 bytes by saving a few in a lot of places. Thanks goes to Mr Public for pointing some out.

-3 bytes because I can't manage to remove all the spaces first try (thanks mbomb007)

+8 bytes to fix for this case:

@v&lt;v
^v^v
^v^&lt;
^&lt;


-15 bytes by front-loading variable declaration



s-&gt;{String o="",t;String[]p=s.split("\n");int h=p.length,w=p[0].length(),y=0,x,b=0,a,n,m;char[][]d=new char[h][w];for(;y&lt;h;y++)for(x=0;x&lt;w;x++){d[y][x]=p[y].charAt(x);if(d[y][x]=='@')d[y][x]=' ';}for(;b&lt;h;b++)for(a=0;a&lt;w;a++){t="";x=a;y=b;n=0;m=0;while(!(y&lt;0|y&gt;h|x&lt;0|x&gt;w||d[y][x]==' ')){if(y+m&gt;=0&amp;y+m&lt;h&amp;x+n&gt;=0&amp;x+n&lt;w&amp;&amp;d[y+m][x+n]==d[y-m][x-n])d[y][x]=d[y-m][x-n];n=m=0;switch(d[y][x]){case'^':t+="W";m--;break;case'&lt;':t+="A";n--;break;case'v':t+="S";m++;break;case'&gt;':t+="D";n++;}x+=n;y+=m;}o=t.length()&gt;o.length()?t:o;}return o;}


Readable version:

static Function&lt;String,String&gt; parser = snake -&gt; {
    // declare all variables in one place to minimize declaration overhead
    String output = "", path;
    String[] split = snake.split("\n");
    int h=split.length, w=split[0].length(), y=0, x, startY=0, startX, dx, dy;
    char[][] board = new char[h][w];
    // setup char[][] board
    for (; y&lt;h; y++)
        for (x=0; x&lt;w; x++) {
            board[y][x]=split[y].charAt(x);
            if(board[y][x]=='@')board[y][x]=' ';
        }
    // find the longest possible path
    for (; startY&lt;h; startY++)
        for (startX=0; startX&lt;w; startX++) {
            path = "";
            x=startX; y=startY; dx=0; dy=0;
            while (!(y&lt;0 | y&gt;h | x&lt;0 | x&gt;w || board[y][x] == ' ')) {
                if (y + dy &gt;= 0 &amp; y + dy &lt; h &amp; x + dx &gt;= 0 &amp; x + dx &lt; w
                        &amp;&amp; board[y + dy][x + dx] == board[y - dy][x - dx]) {
                    board[y][x] = board[y - dy][x - dx];
                } dx = dy = 0;
                switch(board[y][x]) {
                    case '^':path+="W";dy--;break;
                    case '&lt;':path+="A";dx--;break;
                    case 'v':path+="S";dy++;break;
                    case '&gt;':path+="D";dx++;break;
                }
                x+=dx; y+=dy;
            }
            output = path.length()&gt;output.length()?path:output;
        }
    return output;
};


Takes a String like v  @\n&gt;&gt;&gt;^.
Creates a path starting at each coordinate, then returns the longest one.
The lookahead required for the overlapping paths was the hardest part.