Select Git revision
-
Fredrik Hübinette (Hubbe) authored
Rev: tutorial/Makefile:1.16 Rev: tutorial/Sgml.pmod:1.10 Rev: tutorial/Wmml.pmod:1.22
Fredrik Hübinette (Hubbe) authoredRev: tutorial/Makefile:1.16 Rev: tutorial/Sgml.pmod:1.10 Rev: tutorial/Wmml.pmod:1.22
Sgml.pmod 4.17 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;
string file;
string location()
{
#if 1
if(file && file!="stdin")
{
Stdio.File f=Stdio.File();
if(f->open(file,"r"))
{
string *x=f->read(pos-1)/"\n";
return sprintf("line %d col %d in file %s",sizeof(x)+1,strlen(x[-1])+1,file);
}
}
#endif
return "pos "+pos+" in file "+file;
}
void create(string t,
void|mapping p,
void|int po,
void|array(object|string) d, void|string f)
{
tag=t;
pos=po;
params=p||([]);
data=d;
file=f;
}
};
#define TAG object(Tag)|string
#define SGML array(TAG)
SGML lex(string data, string file)
{
mixed foo=data/"<";
SGML ret=({ unquote(foo[0]) });
int nextpos=strlen(foo[0]);
for(int e=1;e<sizeof(foo);e++)
{
int pos;
string tag;
string s=foo[e];
pos=++nextpos;
if(s[0..2]=="!--")
{
nextpos+=strlen(foo[e]);
while(sscanf(s,"%*s-->%s",s)!=2)
{
e++;
s+="<"+foo[e];
nextpos+=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 in %s)\n",pos,file));
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 in %s)\n",nextpos,file));
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)
{
nextpos+=strlen(foo[e])+1;
e++;
s+="<"+foo[e];
}
break;
case '\"':
while(sscanf(s,"=\"%s\"%s",val,s)!=2)
{
nextpos+=strlen(foo[e])+1;
e++;
s+="<"+foo[e];
}
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;
}
}
}
// werror("Fount tag "+tag+" at pos "+pos+".\n");
ret+=({ Tag(tag,params,pos,0,file), unquote(s) });
nextpos+=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..];
string t;
int d;
if (sscanf(tag,"%[^ \t\r\n>]%*s",t)==2) foo->tag=tag=t;
for(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 mktag(string tag, mapping params)
{
string ret="<"+tag;
foreach(indices(params),string i)
{
ret+=" "+i;
if(stringp(params[i]))ret+="="+params[i];
}
return ret+">";
}
string generate(SGML data, void|function mkt)
{
string ret="";
if(!mkt)
{
mkt=mktag;
}
foreach(data, TAG foo)
{
if(stringp(foo))
{
ret+=quote(foo);
}else{
ret+=mkt(foo->tag,foo->params);
if(foo->data)
{
ret+=generate(foo->data,mkt);
ret+=mkt("/"+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),t->file)});
}
}
return ret;
}
string get_text(SGML data)
{
string ret="";
foreach(data,TAG t)
{
if(stringp(t))
{
ret+=t;
}else{
ret+="<"+t->tag;
foreach(indices(t->params), string name)
ret+=" "+name+"="+t->params[name];
ret+=">";
if(t->data)
{
ret+=get_text(t->data);
ret+="</"+t->tag+">";
}
}
}
return ret;
}
#ifdef TEST
int main()
{
write(sprintf("%O\n",group(lex(Stdio.read_file("tutorial.wmml")))));
}
#endif