Roxen.git/
server/
etc/
modules/
Roxen.pmod
Branch:
Tag:
Non-build tags
All tags
No tags
2000-08-09
2000-08-09 11:12:15 by Per Hedbor <ph@opera.com>
c166228bbd0689784c8766642f5ad8858df9fdc6 (
428
lines) (+
420
/-
8
)
[
Show
|
Annotate
]
Branch:
5.2
Added C parser
Rev: server/etc/modules/Roxen.pmod:1.23
1:
/*
-
* $Id: Roxen.pmod,v 1.
22
2000/08/09
02
:
35
:
10
per Exp $
+
* $Id: Roxen.pmod,v 1.
23
2000/08/09
11
:
12
:
15
per Exp $
* * Various helper functions. *
636:
return scope == "_" ? ctx->current_scope() : scope; }
-
static mixed `[]( string what )
+
/*
static
*/
mixed `[]( string what )
{ RXML.Context ctx = RXML.get_context( ); return ctx->get_var( what, scope ); }
-
static mixed `->( string what )
+
/*
static
*/
mixed `->( string what )
{ return `[]( what ); }
-
static mixed `[]=( string what, mixed nval )
+
/*
static
*/
mixed `[]=( string what, mixed nval )
{ RXML.Context ctx = RXML.get_context( ); ctx->set_var( what, nval, scope ); return nval; }
-
static mixed `->=( string what, mixed nval )
+
/*
static
*/
mixed `->=( string what, mixed nval )
{ return `[]=( what, nval ); }
-
static array(string) _indices( )
+
/*
static
*/
array(string) _indices( )
{ RXML.Context ctx = RXML.get_context( ); return ctx->list_var( scope ); }
-
static array(string) _values( )
+
/*
static
*/
array(string) _values( )
{ RXML.Context ctx = RXML.get_context( ); return map( ctx->list_var( scope ), `[] ); }
-
static void create( string _scope )
+
/*
static
*/
void create( string _scope )
{ scope = _scope; }
978:
if(port) return sprintf("%s://%s:%d/%s", protocol, server, port, path); return sprintf("%s://%s/%s", protocol, server, path); }
+
+
+
#if !constant(Parser.C)
+
object Parser =
+
class
+
{
+
object C =
+
class
+
{
+
mapping(string:string) global_groupings=(["{":"}","(":")","[":"]"]);
+
+
array(string) split(string data)
+
{
+
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':
+
return ret;
+
+
case '#':
+
{
+
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);
+
break;
+
+
case 'a'..'z':
+
case 'A'..'Z':
+
case 128..65536: // Lets simplify things for now...
+
case '_':
+
while(1)
+
{
+
switch(data[pos])
+
{
+
case '$': // allowed in some C (notably digital)
+
case 'a'..'z':
+
case 'A'..'Z':
+
case '0'..'9':
+
case 128..65536: // 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+=3;
+
break;
+
}
+
+
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]=='.')
+
{
+
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;
+
+
default:
+
werror("%O\n",ret);
+
werror("Unknown token %O\n",data[pos..pos+20]);
+
exit(1);
+
+
case '`':
+
while(data[pos]=='`') data[pos]++;
+
+
case '\\': pos++; continue; /* IGNORED */
+
+
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])
+
{
+
case "//":
+
pos=search(data,"\n",pos);
+
break;
+
+
case "/*":
+
pos=search(data,"*/",pos);
+
pos+=2;
+
break;
+
+
case "<<": case ">>":
+
if(data[pos+2]=='=') pos++;
+
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':
+
case '\14':
+
while(1)
+
{
+
switch(data[pos])
+
{
+
case ' ':
+
case '\n':
+
case '\r':
+
case '\t':
+
case '\14':
+
pos++;
+
continue;
+
}
+
break;
+
}
+
break;
+
+
case '\'':
+
pos++;
+
if(data[pos]=='\\') pos++;
+
pos=search(data, "'", pos+1)+1;
+
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] });
+
}
+
}
+
+
+
class Token
+
{
+
int line;
+
string text;
+
string file;
+
string trailing_whitespaces="";
+
+
void create(string t, int l, void|string f, void|string space)
+
{
+
text=t;
+
line=l;
+
file=f;
+
if(space) trailing_whitespaces=space;
+
}
+
+
string _sprintf(int how)
+
{
+
switch(how)
+
{
+
case 's':
+
return text;
+
case 'O':
+
return sprintf("Token(%O,%O,%d)",text,file,line);
+
}
+
}
+
+
int `==(mixed foo)
+
{
+
return (objectp(foo) ? foo->text : foo) == text;
+
}
+
+
string `+(string ... s)
+
{
+
return predef::`+(text,@s);
+
}
+
+
string ``+(string ... s)
+
{
+
return predef::`+(@s,text);
+
}
+
+
mixed cast(string to)
+
{
+
if(to=="string") return text;
+
}
+
}
+
+
array(Token) tokenize(array(string) s, void|string file)
+
{
+
array(Token) ret=allocate(sizeof(s));
+
int line=1;
+
for(int e=0;e<sizeof(s);e++)
+
{
+
ret[e]=Token(s[e],line,file);
+
if(s[e][0]=='#')
+
{
+
sscanf(s[e],"#%*[ \t\14]%d%*[ \t\14]\"%s\"", line,file);
+
sscanf(s[e],"#%*[ \t\14]line%*[ \t\14]%d%*[ \t\14]\"%s\"",
+
line,file);
+
line--;
+
}
+
line+=sizeof(s[e]/"\n")-1;
+
}
+
return ret;
+
}
+
+
array group(array(string|Token) tokens, void|mapping groupings)
+
{
+
Stack.stack stack=Stack.stack();
+
array(Token) ret=({});
+
mapping actions=([]);
+
+
if(!groupings) groupings=global_groupings;
+
+
foreach((array)groupings,[string x, string y])
+
{
+
actions[x]=1;
+
actions[y]=2;
+
}
+
+
foreach(tokens, Token token)
+
{
+
switch(actions[(string)token])
+
{
+
case 0: ret+=({token}); break;
+
case 1: stack->push(ret); ret=({token}); break;
+
case 2:
+
if (!sizeof(ret) || !stack->ptr ||
+
(groupings[(string)ret[0]] != (string)token)) {
+
// Mismatch
+
werror(sprintf("**** Grouping mismatch token=%O\n"
+
"**** tokens: ({ %{%O, %}})\n"
+
"**** ret: ({ %{%O, %}})\n"
+
"**** stackdepth: %d\n",
+
token->text, tokens->text,
+
ret->text, stack->ptr));
+
return ret;
+
}
+
ret=stack->pop()+({ ret + ({token}) });
+
}
+
}
+
return ret;
+
}
+
+
/* FIXME:
+
* This actually strips all preprocessing tokens
+
*/
+
array strip_line_statements(array tokens)
+
{
+
array(Token) ret=({});
+
foreach(tokens, array|object(Token) t)
+
{
+
if(arrayp(t))
+
{
+
ret+=({ strip_line_statements(t) });
+
}else{
+
if( ((string)t) [0] != '#')
+
ret+=({t});
+
}
+
}
+
return ret;
+
+
}
+
+
array hide_whitespaces(array tokens)
+
{
+
array(Token) ret=({tokens[0]});
+
foreach(tokens[1..], array|object(Token) t)
+
{
+
if(arrayp(t))
+
{
+
ret+=({ hide_whitespaces(t) });
+
}else{
+
switch( ((string)t) [0])
+
{
+
case ' ':
+
case '\t':
+
case '\14':
+
case '\n':
+
mixed tmp=ret[-1];
+
while(arrayp(tmp)) tmp=tmp[-1];
+
tmp->trailing_whitespaces+=(string)t;
+
break;
+
+
default:
+
ret+=({t});
+
}
+
}
+
}
+
return ret;
+
}
+
+
array flatten(array a)
+
{
+
array ret=({});
+
foreach(a, a) ret+=arrayp(a)?flatten(a):({a});
+
return ret;
+
}
+
+
string simple_reconstitute(array(string|object(Token)|array) tokens)
+
{
+
string ret="";
+
foreach(flatten(tokens), mixed tok)
+
{
+
if(objectp(tok))
+
tok=tok->text + tok->trailing_whitespaces;
+
ret+=tok;
+
}
+
+
return ret;
+
}
+
+
string reconstitute_with_line_numbers(array(string|object(Token)|array)
+
tokens)
+
{
+
int line=1;
+
string file;
+
string ret="";
+
foreach(flatten(tokens), mixed tok)
+
{
+
if(objectp(tok))
+
{
+
if((tok->line && tok->line != line) ||
+
(tok->file && tok->file != file))
+
{
+
if(strlen(ret) && ret[-1]!='\n') ret+="\n";
+
line=tok->line;
+
if(tok->file) file=tok->file;
+
ret+=sprintf("#line %d %O\n",line,file);
+
}
+
tok=tok->text + tok->trailing_whitespaces;
+
}
+
ret+=tok;
+
line+=sizeof(tok/"\n")-1;
+
}
+
+
return ret;
+
}
+
}();
+
}();
+
#endif