MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // PARSER.C -- parser for parenthesis expressions |
| 2 | // (c) 1994 by Hate@MorgenGrauen, TUBmud, NightFall |
| 3 | // -- |
| 4 | // Copy, change and distribute this bit of software as much as you like, |
| 5 | // but keep the name of the original author in the header. |
| 6 | |
| 7 | #pragma strong_types |
| 8 | |
| 9 | #include "tweak.h" |
| 10 | |
| 11 | private inherit HOME("lex"); |
| 12 | |
| 13 | #include "stack.h" |
| 14 | #include "types.h" |
| 15 | |
| 16 | private nosave mixed code; |
| 17 | private nosave mixed stack; |
| 18 | private nosave int quot, assume; |
| 19 | |
| 20 | nomask static void initialize() |
| 21 | { |
| 22 | INITSTACK(stack); |
| 23 | code = ({}); |
| 24 | quot = 0; |
| 25 | } |
| 26 | |
| 27 | static void create() |
| 28 | { |
| 29 | lex::create(); |
| 30 | initialize(); |
| 31 | } |
| 32 | |
| 33 | nomask private mixed CodeGen(mixed token) |
| 34 | { |
| 35 | switch(pre_parse(&code)) |
| 36 | { |
| 37 | case 1: PUSH(stack, "'"); // standard autoquote |
| 38 | quot++; |
| 39 | break; |
| 40 | case 2: PUSH(stack, "'CODE"); // special QUOTE for code generation |
| 41 | break; |
| 42 | } |
| 43 | if(stringp(token)) |
| 44 | switch(token) |
| 45 | { |
| 46 | case "'": PUSH(stack, token); quot++; return; |
| 47 | case "(": PUSH(stack, code); code = ({}); break; |
| 48 | case ")": |
| 49 | { |
| 50 | mixed tmp; |
| 51 | if(SP(stack) && pointerp(TOP(stack))) POP(stack, tmp); |
| 52 | else tmp = ({}); |
| 53 | if(SP(stack) && TOP(stack) == "'") |
| 54 | /* do nothing */ ; |
| 55 | else |
| 56 | if(sizeof(code)) |
| 57 | { |
| 58 | code[0] = prog_parse(code[0]); |
| 59 | if(CL_LAMBDA(code[0]) || symbolp(code[0]) || pointerp(code[0])) |
| 60 | code = ({#'funcall}) + code; |
| 61 | } |
| 62 | code = tmp + ({ code }); |
| 63 | break; |
| 64 | } |
| 65 | default : code += ({ token[1..<2] }); break; |
| 66 | } |
| 67 | else |
| 68 | code += ({ quot ? token : prog_parse(token, !sizeof(code)) }); |
| 69 | |
| 70 | while(SP(stack) && (TOP(stack) == "'" || TOP(stack) == "'CODE") && |
| 71 | sizeof(code)) |
| 72 | { |
| 73 | int q; |
| 74 | if(stringp(code[<1]) || symbolp(code[<1]) || pointerp(code[<1]) || |
| 75 | get_type_info(code[<1])[0] == 10) // quoted array |
| 76 | code[<1] = quote(code[<1]); |
| 77 | POPX(stack); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | // parse() -- non-threaded parsing (continue on input) |
| 82 | nomask static int parse(mixed msg, int interactive) |
| 83 | { |
| 84 | mixed token, res; |
| 85 | int lexing, missing_par; |
| 86 | do { |
| 87 | if(lexing = lex(&token)) |
| 88 | { // try to assume outer "(" |
| 89 | if(!SP(stack) && token != "(") { CodeGen("("); assume = 1; } |
| 90 | CodeGen(token); |
| 91 | } |
| 92 | else // add ")" if "(" is assumed |
| 93 | if(sizeof(stack) == 1 && assume) { CodeGen(")"); assume = 0; lexing = 1; } |
| 94 | if(lexing && !SP(stack)) // complete expression found |
| 95 | { |
| 96 | mixed exec_code; exec_code = code; initialize(); |
| 97 | if(sizeof(exec_code) && pointerp(exec_code[0])) |
| 98 | exec_code = ({#',}) + exec_code;// more than one expr on one line |
| 99 | if(msg = catch(res = eval(exec_code))) |
| 100 | return -2; // execution error |
| 101 | if(interactive) printf(output(res)); |
| 102 | else msg = res; |
| 103 | } |
| 104 | } |
| 105 | while(lexing); |
| 106 | if(missing_par = SP(stack)) |
| 107 | return (msg = sprintf("*Missing %d )\n", missing_par), -3); |
| 108 | return 0; |
| 109 | } |