Skip to content
Snippets Groups Projects
Select Git revision
21 results Searching

Sgml.pmod

Blame
  • Sgml.pmod 3.06 KiB
    string *from=({" ","&","<",">"});
    string *to=({"","&","<",">"});
    
    string unquote(string x) { return replace(x,from,to); }
    string quote(string x) { return replace(x,to,from); }
    
    class Tag
    {
      string tag;
      int pos;
      mapping(string:mixed) params=([]);
    //  array(Tag) data;
      array(object) data;
    
      varargs void create(string t, mapping p, int po, array(object) d)
      {
        tag=t; pos=po; params=p||([]); data=d;
      }
    };
    
    #define TAG object(Tag)|string
    #define SGML array(TAG)
    
    SGML lex(string data)
    {
      mixed foo=data/"<";
      SGML ret=({ unquote(foo[0]) });
      int pos=strlen(foo[0]);
      for(int e=1;e<sizeof(foo);e++)
      {
        string tag;
        string s=foo[e];
        pos++;
    
        if(s[0..2]=="!--")
        {
          pos+=strlen(foo[e]);
          while(sscanf(s,"%*s-->%s",s)!=2)
          {
    	e++;
    	s+="<"+foo[e];
    	pos+=strlen(foo[e])+1;
          }
          ret[-1]+=unquote(s);
          continue;
        }
        
        if(sscanf(s,"%[^ \t\n\r>]%s",tag,s)!=2)
          werror(sprintf("Missing end > (around pos %d)\n",pos));
    
        tag=lower_case(tag);
        mapping params=([]);
    
        while(1)
        {
          sscanf(s,"%*[ \t\r\n]%s",s);
          if(!strlen(s))
          {
    	write(sprintf("Missing end > (around pos %d)\n",pos));
    	break;
          }
          if(s[0]=='>')
          {
    	s=s[1..];
    	break;
          }
    
          if(sscanf(s,"%[^ \t\r\n>=]%s",string key,s) && strlen(key))
          {
    	key=lower_case(key);
    	if(s[0]=='=')
    	{
    	  string val;
    	  switch(s[1])
    	  {
    	  case '\'':
    	    while(sscanf(s,"='%s'%s",val,s)!=2)
    	    {
    	      e++;
    	      s+="<"+foo[e];
    	      pos+=strlen(foo[e])+1;
    	    }
    	    break;
    	  case '\"':
    	    while(sscanf(s,"=\"%s\"%s",val,s)!=2)
    	    {
    	      e++;
    	      s+="<"+foo[e];
    	      pos+=strlen(foo[e])+1;
    	    }
    	    break;
    	  default:
    	    sscanf(s,"=%[^ \t\r\n>]%s",val,s);
    	    break;
    	  }
    	  if(!val)
    	  {
    	    werror("Missing end quote parameter\n"); 
    	  }
    	  params[key]=val;
    	}else{
    	  params[key]=1;
    	}
          }
        }
    
        ret+=({ Tag(tag,params,pos), unquote(s) });
        pos+=sizeof(foo[e]);
      }
    
      return ret;
    }
    
    
    SGML group(SGML data)
    {
      SGML ret=({});
      foreach(data,TAG foo)
      {
        if(objectp(foo))
        {
          if(strlen(foo->tag) && foo->tag[0]=='/')
          {
    	string tag=foo->tag[1..];
    	for(int d=sizeof(ret)-1;d>=0;d--)
    	{
    	  if(objectp(ret[d]) && !ret[d]->data && ret[d]->tag==tag)
    	  {
    	    ret[d]->data=ret[d+1..];
    	    ret=ret[..d];
    	    break;
    	  }
    	}
    	if(d>=0) continue;
          }
        }
        ret+=({foo});
      }
      return ret;
    }
    
    
    string generate(SGML data)
    {
      string ret="";
      foreach(data, TAG foo)
        {
          if(stringp(foo))
          {
    	ret+=quote(foo);
          }else{
    	ret+="<"+foo->tag;
    	foreach(indices(foo->params), string name)
    	  ret+=" "+name+"="+foo->params[name];
    
    	ret+=">";
    	if(foo->data)
    	{
    	  ret+=generate(foo->data);
    	  ret+="</"+foo->tag+">";
    	}
          }
        }
    
      return ret;
    }
    
    SGML copy(SGML data)
    {
      if(!data) return 0;
      SGML ret=({});
      foreach(data,TAG t)
        {
          if(stringp(t))
          {
    	ret+=({t});
          }else{
    	ret+=({Tag(t->tag,t->params+([]),t->pos,copy(t->data))});
          }
        }
      return ret;
    }
    
    
    #ifdef TEST
    int main()
    {
      write(sprintf("%O\n",group(lex(Stdio.read_file("tutorial.wmml")))));
    }
    #endif