pike.git / lib / modules / Parser.pmod / Pike.pmod

version» Context lines:

pike.git/lib/modules/Parser.pmod/Pike.pmod:1: - #pike __REAL_VERSION__ + // + // This file needs to support old pikes that e.g. don't understand + // "#pike". Some of them fail when they see an unknown cpp directive. + // + // #pike __REAL_VERSION__ + //    -  + //! This module parses and tokenizes Pike source code. +    inherit "C.pmod";    - #define UNKNOWN_TOKEN \ -  throw( ({sprintf("Unknown token %O\n",data[pos..pos+20]) }) ) -  - static mapping(string : int) backquoteops = - (["/":1, -  "%":1, -  "*":1, -  "*=":2, -  "&":1, -  "|":1, -  "^":1, -  "~":1, -  "+=":2, "+":1, -  "<<":2, "<=":2, "<":1, -  ">>":2, ">=":2, ">":1, -  "!=":2, "!":1, -  "==":2, "=":1, -  "()":2, -  "->=":3, "->":2, "-":1, -  "[]=":3, "[]":2 ]); -  - array(string) split(string data) + array(string) low_split(string data, void|mapping state)   { -  int start; -  int line=1; -  array(string) ret=({}); -  int pos; -  data += "\n\0"; /* End sentinel. */ -  -  while(1) -  { -  int start=pos; -  - // werror("::::%c\n",data[pos]); -  -  switch(data[pos]) -  { -  case '\0': +  if(state && state->remains) +  data = m_delete(state, "remains") + data; +  array ret; +  string rem; +  [ret, rem] = Parser._parser._Pike.tokenize(data); +  if(sizeof(rem)) { +  if(rem[0]=='"') +  throw(UnterminatedStringError(ret*"", rem)); +  if(state) state->remains=rem; +  }    return ret; -  -  case '#': -  { -  pos+=1; -  if(data[pos]=='\"') -  break; -  pos=search(data,"\n",pos); -  if(pos==-1) -  error("Failed to find end of preprocessor statement.\n"); -  -  while(data[pos-1]=='\\') pos=search(data,"\n",pos+1); -  sscanf(data[start..pos], -  "#%*[ \t]charset%*[ \t\\]%s%*[ \n]", string charset); -  if(charset) -  data = (data[0..pos]+ -  master()->decode_charset(data[pos+1..sizeof(data)-3], -  charset) -  +"\n\0"); // New end sentinel. -  break; -  -  case 'a'..'z': -  case 'A'..'Z': -  case 128..: // Lets simplify things for now... -  case '_': -  while(1) -  { -  switch(data[pos]) -  { -  case 'a'..'z': -  case 'A'..'Z': -  case '0'..'9': -  case 128..: // Lets simplify things for now... -  case '_': -  pos++; -  continue; +    } -  break; -  } -  break; +     -  case '.': -  if(data[start..start+2]=="...") -  { -  pos+=3; -  break; -  } -  if(data[start..start+1]=="..") -  { -  pos+=2; -  break; -  } -  pos++; -  break; + //! Splits the @[data] string into an array of tokens. An additional + //! element with a newline will be added to the resulting array of + //! tokens. If the optional argument @[state] is provided the split + //! function is able to pause and resume splitting inside #"" and + //! /**/ tokens. The @[state] argument should be an initially empty + //! mapping, in which split will store its state between successive + //! calls. + array(string) split(string data, void|mapping state) { +  array r = low_split(data, state);    -  case '0'..'9': -  if(data[pos]=='0' && (data[pos+1]=='x' || data[pos+1]=='X')) -  { -  pos+=2; -  while(1) -  { -  switch(data[pos]) -  { -  case '0'..'9': -  case 'a'..'f': -  case 'A'..'F': -  pos++; -  continue; -  } -  break; -  } -  break; -  } -  while(data[pos]>='0' && data[pos]<='9') pos++; -  if(data[pos]=='.' && data[pos+1]>='0' && data[pos+1]<='9') -  { -  pos++; -  while(data[pos]>='0' && data[pos]<='9') pos++; -  if(data[pos]=='e' || data[pos]=='E') -  { -  pos++; -  while(data[pos]>='0' && data[pos]<='9') pos++; -  } -  } -  break; +  array new = ({}); +  for(int i; i<sizeof(r); i++) +  if(r[i][..1]=="//" && r[i][-1]=='\n') +  new += ({ r[i][..<1], "\n" }); +  else +  new += ({ r[i] });    -  default: -  UNKNOWN_TOKEN; -  -  case '`': -  { -  int bqstart = pos; -  while(data[pos]=='`') -  ++pos; -  if (pos - bqstart > 3) // max. three ``` -  UNKNOWN_TOKEN; -  int chars = backquoteops[data[pos..pos+2]] -  || backquoteops[data[pos..pos+1]] -  || backquoteops[data[pos..pos]]; -  if (chars) -  pos += chars; +  if(sizeof(new) && (< "\n", " " >)[new[-1]]) +  new[-1] += "\n";    else -  UNKNOWN_TOKEN; +  new += ({ "\n" }); +  return new;   } -  break; +     -  case '/': -  case '{': case '}': -  case '[': case ']': -  case '(': case ')': -  case ';': -  case ',': -  case '*': case '%': -  case '?': case ':': -  case '&': case '|': case '^': -  case '!': case '~': -  case '=': -  case '+': -  case '-': -  case '@': -  case '<': case '>': -  switch(data[pos..pos+1]) + class UnterminatedStringError + //! Error thrown when an unterminated string token is encountered.   { -  case "//": -  pos=search(data,"\n",pos); -  break; +  inherit Error.Generic; +  constant error_type = "unterminated_string"; +  constant is_unterminated_string_error = 1;    -  case "/*": -  pos=search(data,"*/",pos); -  pos+=2; -  break; +  string err_str; +  //! The string that failed to be tokenized    -  case "<<": case ">>": -  if(data[pos+2]=='=') pos++; -  case "==": case "<=": case ">=": -  case "*=": case "/=": case "%=": -  case "&=": case "|=": case "^=": -  case "+=": case "-=": -  case "++": case "--": -  case "&&": case "||": -  case "->": -  case "::": -  pos++; -  default: -  pos++; -  } -  break; -  -  -  case ' ': -  case '\n': -  case '\r': -  case '\t': -  while(1) +  protected void create(string pre, string post)    { -  switch(data[pos]) -  { -  case ' ': -  case '\n': -  case '\r': -  case '\t': -  pos++; -  continue; +  int line = String.count(pre, "\n")+1; +  err_str = pre+post; +  if( sizeof(post) > 100 ) +  ::create(sprintf("Unterminated string %O[%d] at line %d\n", +  post[..100], sizeof(post)-100, line)); +  else +  ::create(sprintf("Unterminated string %O at line %d\n", +  post, line));    } -  break; +    } -  break; -  -  case '\'': -  pos++; -  if(data[pos]=='\\') pos++; -  int end=search(data, "'", pos)+1; -  if (!end) { -  --pos; -  UNKNOWN_TOKEN; -  } -  pos=end; -  break; -  -  case '"': -  { -  int q,s; -  while(1) -  { -  q=search(data,"\"",pos+1); -  s=search(data,"\\",pos+1); -  if(q==-1) q=strlen(data)-1; -  if(s==-1) s=strlen(data)-1; -  -  if(q<s) -  { -  pos=q+1; -  break; -  }else{ -  pos=s+1; -  } -  } -  break; -  } -  } -  } -  -  ret+=({ data[start..pos-1] }); -  } - } -  +