/* Parser.js - changes control section

ID	Date	 Notes
DB001	01/03/00 Parse_M should return an empty Array if it does
		 not find an S_Starter on the input stream
EN001	01/03/00 Update parser to permit repeat E [L]
EN002	01/03/00 Update parser to permit bk (backwards) dv (dive) rl (roll)

*/
/********************************************************************
  Parse_L, Parse_M, Parse_S:

  Recursive Descent Parsing for the grammar:
1)  	L	->	S M
2)  	M	->	S M
3)  	M	->	epsilon
4.0)	S	->	repeat E [L]
4.1)  	S	->	fd E|rt E|lt E|dv E|rl E|bk E
4.2)	S	->	pu|pd|hide|show
5)	E	->	<integer>

  There is a function for each of the non-terminals in the grammar.
  Specifically Parse_L, Parse_M and Parse_S.

  Each of these returns a node.

*********************************************************************/
var ParseError = '';

function SetParseError(s,t){
if (ParseError=='') ParseError=s+ 
                 " "+t[0]+" "+t[1]+" at line "+t[2];
}

function Parse_L(ts){
return(new Array("SEQ", Parse_S(ts),Parse_M(ts)))
}

function Parse_M(ts){
if (IsEmpty(ts))
  return(new Array())
else{
  if (Is_S_Starter(Peek(ts)[1])) {
    return(new Array("SEQ", Parse_S(ts),Parse_M(ts)))
    }
  else
    return(new Array())						//DB001
  }
}

function Parse_S(ts){
var cm;
var nm;
if (Is_S_Starter(Peek(ts)[1]))
  switch (Peek(ts)[1]) {
    case "repeat":						//EN001
      cm = Get(ts);
      nm = Get(ts);
      if (nm[0]!="INTEGER")
        SetParseError("Number expected",nm);
      ws = Get(ts);
      if (ws[1] != '[')
        SetParseError('Open square bracket expected',ws);
      ls = Parse_L(ts);
      ws = Get(ts);
      if (ws[1] != ']')
        SetParseError('Close square bracket expected',ws);
      return(new Array('REPEAT',nm[1],ls));
      break;
    case "fd":           // these all take one parameter
    case "lt":
    case "rt":
    case "dv":							//EN002
    case "rl":							//EN002
    case "bk":							//EN002
      cm = Get(ts);
      nm = Get(ts);
      if (nm[0]!="INTEGER")
        SetParseError("Number expected",nm);
      else
        return(new Array("PRIM",cm[1],nm[1]))
      break;
    case "pu":		// these all take zero parameters
    case "pd":
    case "hide":
    case "show":
      cm = Get(ts);
      return(new Array("PRIM", cm[1]));
      break;
  }
else{
  alert("Error line: "+Peek(ts)[2]+' : Unknown token '+Peek(ts)[1]);
  return "";
  }
}

/* Is_S_Starter returns true if x  in S's starter set */
function Is_S_Starter(x){
return(' fd lt pd pu rt hide show repeat dv bk rl '.search(' '+x+' ')>=0)
}

function PPrint(a){
var i;
var x;
if (typeof(a)=="string")
  return a;
else {
  if ((!a)||(a.length==0))
    return("()");
  x="("+PPrint(a[0]);
  for (i=1;i<a.length;i++)
    x+=","+PPrint(a[i]);
  return(x+")");
  }
}



