blob: dc47d653f08fd5e5fe4c18b8b04da9165822bbf6 [file] [log] [blame]
// PARSER.C -- parser for parenthesis expressions
// (c) 1994 by Hate@MorgenGrauen, TUBmud, NightFall
// --
// Copy, change and distribute this bit of software as much as you like,
// but keep the name of the original author in the header.
#pragma strong_types
#include "tweak.h"
private inherit HOME("lex");
#include "stack.h"
#include "types.h"
private nosave mixed code;
private nosave mixed stack;
private nosave int quot, assume;
nomask static void initialize()
{
INITSTACK(stack);
code = ({});
quot = 0;
}
static void create()
{
lex::create();
initialize();
}
nomask private mixed CodeGen(mixed token)
{
switch(pre_parse(&code))
{
case 1: PUSH(stack, "'"); // standard autoquote
quot++;
break;
case 2: PUSH(stack, "'CODE"); // special QUOTE for code generation
break;
}
if(stringp(token))
switch(token)
{
case "'": PUSH(stack, token); quot++; return;
case "(": PUSH(stack, code); code = ({}); break;
case ")":
{
mixed tmp;
if(SP(stack) && pointerp(TOP(stack))) POP(stack, tmp);
else tmp = ({});
if(SP(stack) && TOP(stack) == "'")
/* do nothing */ ;
else
if(sizeof(code))
{
code[0] = prog_parse(code[0]);
if(CL_LAMBDA(code[0]) || symbolp(code[0]) || pointerp(code[0]))
code = ({#'funcall}) + code;
}
code = tmp + ({ code });
break;
}
default : code += ({ token[1..<2] }); break;
}
else
code += ({ quot ? token : prog_parse(token, !sizeof(code)) });
while(SP(stack) && (TOP(stack) == "'" || TOP(stack) == "'CODE") &&
sizeof(code))
{
int q;
if(stringp(code[<1]) || symbolp(code[<1]) || pointerp(code[<1]) ||
get_type_info(code[<1])[0] == 10) // quoted array
code[<1] = quote(code[<1]);
POPX(stack);
}
}
// parse() -- non-threaded parsing (continue on input)
nomask static int parse(mixed msg, int interactive)
{
mixed token, res;
int lexing, missing_par;
do {
if(lexing = lex(&token))
{ // try to assume outer "("
if(!SP(stack) && token != "(") { CodeGen("("); assume = 1; }
CodeGen(token);
}
else // add ")" if "(" is assumed
if(sizeof(stack) == 1 && assume) { CodeGen(")"); assume = 0; lexing = 1; }
if(lexing && !SP(stack)) // complete expression found
{
mixed exec_code; exec_code = code; initialize();
if(sizeof(exec_code) && pointerp(exec_code[0]))
exec_code = ({#',}) + exec_code;// more than one expr on one line
if(msg = catch(res = eval(exec_code)))
return -2; // execution error
if(interactive) printf(output(res));
else msg = res;
}
}
while(lexing);
if(missing_par = SP(stack))
return (msg = sprintf("*Missing %d )\n", missing_par), -3);
return 0;
}