(* SYNTAX.PAS: Please read the bottom of DRAAK.PAS for Copyright details.  *)

function isChar(inchar: char): boolean;
begin
 if (((inchar >= '0') AND (inchar <= '9')) OR ((inchar >= 'A') AND (inchar  <= 'Z'))
 OR ((inchar >= 'a') AND (inchar <= 'z')) OR (inchar = '.') OR (inchar = '_')) then
 isChar := true  else isChar := false;end;

function isChare(inchar: char): boolean;
begin
 if (((inchar >= '0') AND (inchar <= '9')) OR ((inchar >= 'A') AND (inchar  <= 'Z'))
 OR ((inchar >= 'a') AND (inchar <= 'z')) OR (inchar = '.') OR (inchar = '_')
 OR (inchar = '"') OR (inchar = ' ')) then
 isChare := true else isChare := false;end;

function checkSyntax(icode: PChar; defs, retDef: PDef): PSyn;
var id, ii, iis: word; {id := defs i, ii := incode i, iis := ii save}
 dumbSyn, saveSyn: PSyn;
 typeTemp, placeHold: PChar;
 saveC: char; single: Boolean;
begin
 {Attempt to find the right syntax}
 while defs <> nil do
 begin
  ii := 0; id := 1;
  {First, remove the white space at the begining}
  while icode[ii] = ' ' do ii := ii+1;
{  mark(markPtr); For this, this is easier.  later it's not}
  dumbSyn := new(PSyn); saveSyn := dumbSyn;
  dumbSyn^.synType := nil;
  dumbSyn^.synVal := nil;
  dumbSyn^.nextSyntax := nil;
  while defs^.command[id] <> #0 do
  begin
   single := false;
   while icode[ii] = defs^.command[id] do
   begin
    ii := ii+1; id := id+1;
    if ((icode[ii] = #0) AND (defs^.command[id] = #0)) then
     break;
   end;
   if ((defs^.command[id-1] = ' ') AND (icode[ii] = ' ')) then
    while icode[ii] = ' ' do ii := ii+1 else
   begin
   {if ((defs^.command[id] <> '(')) then break;}
   if ((defs^.command[id] = '%') AND (defs^.command[id-1] = '(')) then
   begin
    id := id-1; ii := ii-1;
   end;
   if defs^.command[id] = '(' then
   begin
    id := id+1;
    if defs^.command[id] <> '%' then break;
    if defs^.command[id+1] = 's' then
     single := true;
    typeTemp := nil;
    while defs^.command[id] <> ')' do
    begin
     id := id+1;
{     if defs^.command[id] = '%' then
     begin
      placeHold := defs^.command+id+1;
      while defs^.command[id] <> ')' do id := id+1;
      defs^.command[id] := #0;
      getMem(typeTemp, strLen(placeHold)+1);
      strCopy(typeTemp, placeHold);
      defs^.command[id] := ')';
     end;}
    end;
    id := id+1;
    dumbSyn^.nextSyntax := new(PSyn);
    dumbSyn := dumbSyn^.nextSyntax;
    dumbSyn^.synType := nil;
    dumbSyn^.synVal := nil;
    dumbSyn^.nextSyntax := nil;
    i := strLen(typeTemp);
    if typeTemp <> nil then
    begin
     getMem(dumbSyn^.synType, strLen(typeTemp)+1);
     strCopy(dumbSyn^.synType, typeTemp);
    end;
    placeHold := icode+ii;
{    if ((defs^.command[id] = ' ')) then
     while defs^.command[id] = ' ' do
      id := id+1;}
    while icode[ii] <> defs^.command[id] do
    begin
     ii := ii+1;
     if ((icode[ii] = #0) AND (defs^.command[id] <> #0)) then break;
     if ((icode[ii] = ' ') AND (single = true)) then
     begin
      if defs^.command[id] <> ' ' then
       while icode[ii] = ' ' do
        ii := ii+1;
      break;
     end;
    end;
    if ((icode[ii] = #0) AND (defs^.command[id] <> #0)) then break;
    iis := ii; if ((icode[ii-1] = ' ') {AND (single = false)}) then while icode[ii-1] = ' ' do ii := ii-1;
    saveC := icode[ii]; icode[ii] := #0;
    getMem(dumbSyn^.synVal, strLen(placeHold)+1);
    strCopy(dumbSyn^.synVal, placeHold);
{    icode[ii] := defs^.command[id];}
    icode[ii] := saveC;
    ii := iis;
    end;
   end;
{   while ((icode[ii] = ' ') AND (defs^.command[id] = #0)) do ii := ii+1;}
   if ((icode[ii] <> defs^.command[id]){ AND (defs^.command[id] <> '(')}) then break;
  end;
  if ((icode[ii] = #0) AND (defs^.command[id] = #0)) then
  begin
   checkSyntax := saveSyn;
   retDef^.nextDef := defs;
   exit;
  end;

 { release(markPtr);}
  destroySyn(saveSyn);
  defs := defs^.nextDef;
 end;
 error(5);
end;

procedure handleAct(def: PDef; syns: PSyn);
var acts: PAct;
begin
 acts := def^.actions^.nextAct;
{ replaceSyn(acts^.asmLn, syns);}
 while acts <> nil do
 begin
  i := 0; while acts^.asmLn[i] =' ' do i := i+1;
  gdefChar := def^.command[0]; actCase(acts, syns);
  acts := acts^.nextAct;
 end;
end;

procedure actCase(acts: PAct; syns: PSyn);
var actLn: PChar; o, i, ii: word; dumbSyn: PSyn;
var a1: pchar;
begin
i := 0; while acts^.asmLn[i] =' ' do i := i+1;
case acts^.asmLn[i] of
 '+':
 begin
  actLn := replaceSyn(acts^.asmLn, syns);
  if gdefChar = '!' then
   writeLn(outCode, strPas(actLn));
  if gdefChar = '@' then
   writeLn(outData, strPas(actLn));
 end;
 '_':
 begin
  getMem(actLn, 255); i := 0; ii := 0;
  while acts^.asmLn[i] <> #0 do
  begin
   while ((acts^.asmLn[i] <> '%') AND (acts^.asmLn[i] <> #0)) do
   begin
    actLn[ii] := acts^.asmLn[i]; ii:= ii+1; i := i+1;
   end;
   if acts^.asmLn[i] = #0 then break;
   if acts^.asmLn[i+1] <> '%' then
   begin
    getMem(a1, 2); a1[0] := acts^.asmLn[i+1]; a1[1] := #0;
    o := vala(a1);
    dumbSyn := syns; for o := 1 to vala(a1) do
     dumbSyn := dumbSyn^.nextSyntax;
    if ((strComp(dumbSyn^.synVal, 'byte') <> 0) AND (strComp(dumbSyn^.synVal, 'word') <> 0)
     AND (strComp(dumbSyn^.synVal, 'dword') <> 0) AND (strComp(dumbSyn^.synVal, 'qword') <> 0)) then
    begin
     actLn[ii] := '_'; actLn[ii+1] := '%'; ii:= ii+2; i := i+1;
    end else begin actLn[ii] := '%'; ii:= ii+1; i := i+1; end;
   end else begin actLn[ii] := '%'; actLn[ii+1] := '%'; ii := ii+2; i := i+2; end;
  end; actLn[ii] := #0; actLn := replaceSyn(actLn, syns);
  if gdefChar = '!' then
   writeLn(outCode, strPas(actLn));
  if gdefChar = '@' then
   writeLn(outData, strPas(actLn));
 end;
 '!': handleCmd(acts, syns);
 '&': handleDira(acts, syns);
 end;
end;

procedure destroySyn(inSyn: PSyn);
var tempSyn, nextSyn: PSyn;
begin
 tempSyn := inSyn;
 while tempSyn <> nil do
 begin
  nextSyn := tempSyn^.nextSyntax;
  if tempSyn^.synVal <> nil then freeMem(tempSyn^.synVal, strLen(tempSyn^.synVal)+1);
  if tempSyn^.synType <> nil then freeMem(tempSyn^.synType, strLen(tempSyn^.synType)+1);
  dispose(tempSyn);
  tempSyn := nextSyn;
 end;
end;