/* For C token parsing */!!

inherit(String, #CString, nil, 0, 0)!!

now(class(CString))!!

/* PUBLIC -- given an actor string, copy it. */
Def newFromString(self, textStr | newInstance)
{
  newInstance := new( self, size( textStr ) ) ;
  ^initializeFromString( newInstance, textStr ) ;
}
!!

now(CString)!!

/* 11/20/1992 16:44 */
Def scanArrow(self, chrPos, left1, right1, maxChar | auxSet)
{ 
  auxSet := asSet( "->" );
  if self[chrPos] in auxSet then
    /* NOTES: Nghia - 09/02/92 Revised */
    loop while (right1+2 < maxChar) cand ((self[right1] = '-') cand (self[right1+1] = '>')) cor
      ((self[left1] = '-') cand (self[right1] = '>'))
    begin
      right1 := (right1 + 1); /* printLine(asString(right1)); */
    endLoop;
      
    loop while (left1 > 2) cand ((self[left1-1] = '>') cand (self[left1-2] = '-'))  
     cor ((self[right1] = '>') cand (self[left1] = '-'))
    begin
      left1 := (left1 - 1); /* printLine(asString(left1)); */
    endLoop;
    ^tuple(left1, right1);
  endif;
  ^nil;
}
!!

/* PRIVATE -- due to Actor bug, the resultant string prints as "" */
Def initializeFromString(self, textStr | pos)
{
  do(over(0, size(textStr)),
  {using(index)
    put( self, at(textStr, index), index ) ;
  });
/*@@{
  replace(self, textStr, 0, size(self), 0, size(textStr)) ;
  should work, but it does not (Actor bug)
}@@*/
  ^self
}
!!

/* PRIVATE
  C-language-specific parse function
  returns #(tokStr, chrPos, textStartPos, textEndPos, nil )
  selected is tokStr.
*/
Def tokenInfo(self, chrPos | inAux? looking?
    left left1 right right1 idCharSet validSet maxChar retPos point?)
{
  if (maxChar := size(self)) = 0 then 
    ^tuple("", 0, left, right)
  endif ;

  idCharSet := asSet( "abcdefghijklmnopqrstuvwxyz" +
                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789_." ) ;
  left1  := right1 := chrPos;
  inAux? := nil;
  if (retPos := scanArrow(self, chrPos, left1, right1, maxChar)) then
    inAux? := #true;
    left1  := retPos[0];
    right1 := retPos[1];
  endif;
  validSet := idCharSet;

  /* find inner (or only) field */
  loop while (left1 > 0) cand (self[left1-1] in validSet)
  begin left1 := (left1 - 1) ;
  endLoop;
  loop while (right1 < maxChar) cand (self[right1] in validSet)
  begin right1 := (right1 + 1) ;
  endLoop;

  /* find maximal token */
  left  := left1 ;
  right := right1 ;
  looking? := #true; point? := nil;
  loop while (left > 0) cand looking?
  begin 
    if (self[left-1] in validSet) then
      left := (left - 1);
      point? := nil;
    else if (left > 2) cand ((self[left-1] = '>') cand (self[left-2] = '-')) then
      left := (left - 2); point? := #true;
    else
      looking? := nil;
      /* handle [(*t)->var] back out */
      if point? then left := left + 2; endif;
      endif ;
    endif ;
  endLoop;
    
  looking? := #true ;
  loop while (right < maxChar) cand looking?
  begin 
    if (self[right] in validSet) then
      right := (right + 1);
    else 
      if ((right+2) < maxChar) cand (self[right] = '-') cand (self[right+1] = '>') then 
        right := (right + 2) ;
      else
        looking? := nil ;
      endif;
    endif;
  endLoop;
    
  if inAux? cand (left <> right) then
    if self[right] cand (right > 0) cand 
         ((self[right] = '-') cand not(self[right-1] in validSet)) then 
      right := right-1; 
    endif;
    if self[left] cand (left+2 <= right) cand (self[left] = '-') then
      left := left+2; 
    endif;  
  endif;
  /* Return the found token or nothing found */  
  if (left = right) cor (left > right) then 
    ^tuple("", 0, left, right, nil);
  endif;
  ^tuple(subString(self, left, right), 0, left, right, nil);

} !!
