Index: class.c ================================================================== --- class.c +++ class.c @@ -969,10 +969,90 @@ } free(labelptr); labelstack=0; labelptr=0; } + +static int parse_pattern(int cla,int ptr,Hash*hash) { + Class*cl=classes[cla]; + Uint8 depth=0; + Uint16 nest[32]; + int x,y; + for(;;) { + nxttok(); + if(Tokenf(TF_MACRO)) ParseError("Unexpected macro\n"); + if(Tokenf(TF_DIR)) { + cl->codes[ptr++]=tokenv&15; + } else if(Tokenf(TF_NAME)) { + switch(tokenv) { + case OP_ADD: case OP_CLIMB: case OP_EIGHT: case OP_FOUR: + case OP_HEIGHT: case OP_LOC: case OP_MARK: case OP_SUB: + case OP_DIR: case OP_DIR_C: case OP_DIR_E: case OP_DIR_EC: + case 0x0200 ... 0x02FF: // message + case 0x4000 ... 0x7FFF: // class + case 0xC000 ... 0xFFFF: // message + cl->codes[ptr++]=tokenv; + break; + case OP_BEGIN: case OP_IF: + if(depth==31) ParseError("Too much pattern nesting\n"); + nest[depth++]=ptr; + cl->codes[ptr++]=tokenv; + cl->codes[ptr++]=0; + break; + case OP_ELSE: + if(!depth) ParseError("Premature end of subpattern\n"); + cl->codes[nest[depth-1]+1]=ptr; + cl->codes[ptr++]=cl->codes[nest[depth-1]]; + cl->codes[nest[depth-1]]=OP_ELSE; + cl->codes[ptr++]=0; + break; + case OP_THEN: + if(!depth) ParseError("Premature end of subpattern\n"); + cl->codes[nest[--depth]+1]=ptr; + break; + case OP_AGAIN: + if(!depth) ParseError("Premature end of subpattern\n"); + cl->codes[ptr++]=OP_GOTO; + cl->codes[ptr++]=nest[depth-1]; + cl->codes[nest[--depth]+1]=ptr; + break; + case OP_USERFLAG: + x=look_hash(glohash,HASH_SIZE,0x1000,0x10FF,0,"user flags"); + if(!x) ParseError("User flag ^%s not defined\n",tokenstr); + if(Tokenf(TF_COMMA)) x+=0x100; + if(Tokenf(TF_EQUAL)) ParseError("Improper token in pattern\n"); + cl->codes[ptr++]=x; + break; + default: ParseError("Improper token in pattern\n"); + } + } else if(tokent==TF_OPEN) { + nxttok(); + if(Tokenf(TF_MACRO) || !Tokenf(TF_NAME)) ParseError("Improper token in pattern\n"); + switch(tokenv) { + case OP_HEIGHT: case OP_CLIMB: + cl->codes[ptr++]=tokenv+0x0800; // OP_HEIGHT_C or OP_CLIMB_C + nxttok(); + if(tokent!=TF_INT) ParseError("Number expected\n"); + if(tokenv&~0xFFFF) ParseError("Number out of range\n"); + cl->codes[ptr++]=tokenv; + nxttok(); + if(tokent!=TF_CLOSE) ParseError("Close parentheses expected\n"); + break; + default: ParseError("Improper token in pattern\n"); + } + } else if(tokent==TF_CLOSE) { + if(depth) ParseError("Premature end of pattern\n"); + cl->codes[ptr++]=OP_RET; + return ptr; + } else if(Tokenf(TF_EOF)) { + ParseError("Unexpected end of file\n"); + } else { + ParseError("Improper token in pattern\n"); + } + if(ptr>=0xFFEF) ParseError("Out of code space\n"); + } +} #define AddInst(x) (cl->codes[ptr++]=(x),prflag=0) #define AddInst2(x,y) (cl->codes[ptr++]=(x),cl->codes[ptr++]=(y),prflag=0,peep=ptr) #define AddInstF(x,y) (cl->codes[ptr++]=(x),prflag=(y)) #define ChangeInst(x) (cl->codes[ptr-1]x,prflag=0) @@ -1178,10 +1258,17 @@ nxttok(); if(tokent!=TF_INT || tokenv<0 || tokenv>32) ParseError("Expected number from 0 to 32"); if(tokenv) AddInst2(OP_POPUPARGS,tokenv); else AddInst(OP_POPUP); nxttok(); if(tokent!=TF_CLOSE) ParseError("Unterminated (PopUp)\n"); + break; + case OP_PATTERN: case OP_PATTERNS: + case OP_PATTERN_C: case OP_PATTERNS_C: + case OP_PATTERN_E: case OP_PATTERNS_E: + AddInst(tokenv); + cl->codes[ptr]=peep=parse_pattern(cla,ptr+1,hash); + ptr=peep; break; case OP_BROADCAST: nxttok(); if(Tokenf(TF_MACRO) || !Tokenf(TF_NAME) || tokenv<0x4000 || tokenv>0x7FFF) ParseError("Class name expected\n"); AddInst2(OP_BROADCASTCLASS,tokenv-0x4000); Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -2072,10 +2072,15 @@ The return value of HITBY can also be an object instead of a number. In this case, a warp occurs. The movement is restarted, using the specified object as the origin of the movement, and that object's direction as the direction of movement. + +=== Pattern matching === + +(TODO) + === Compatibility === Compatible objects have the following differences from the default: Index: instruc ================================================================== --- instruc +++ instruc @@ -277,10 +277,16 @@ -Array GetArray InitArray SetArray ArrayCell + +; Pattern matching +-,=Pattern "P" +-,=PatternS "P*" +-Four +-Eight ; Specials *Function *Local *Label Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -405,18 +405,28 @@ #define OP_ARRAY 32969 #define OP_GETARRAY 32970 #define OP_INITARRAY 32971 #define OP_SETARRAY 32972 #define OP_ARRAYCELL 32973 -#define OP_FUNCTION 32974 -#define OP_LOCAL 32975 -#define OP_LABEL 32976 -#define OP_STRING 32977 -#define OP_INT16 32978 -#define OP_INT32 32979 -#define OP_DISPATCH 32980 -#define OP_USERFLAG 32981 +#define OP_PATTERN 32974 +#define OP_PATTERN_C 35022 +#define OP_PATTERN_E 37070 +#define OP_PATTERN_EC 39118 +#define OP_PATTERNS 32975 +#define OP_PATTERNS_C 35023 +#define OP_PATTERNS_E 37071 +#define OP_PATTERNS_EC 39119 +#define OP_FOUR 32976 +#define OP_EIGHT 32977 +#define OP_FUNCTION 32978 +#define OP_LOCAL 32979 +#define OP_LABEL 32980 +#define OP_STRING 32981 +#define OP_INT16 32982 +#define OP_INT32 32983 +#define OP_DISPATCH 32984 +#define OP_USERFLAG 32985 #ifdef HEROMESH_CLASS static const Op_Names op_names[]={ {"*",8486937}, {"+",8421399}, {"+Move",10584230}, @@ -491,18 +501,20 @@ {"Distance",9142340}, {"Done",8618097}, {"E",9437184}, {"END_TURN",8389139}, {"EditorHelp",8683654}, +{"Eight",8683729}, {"F",9437192}, {"FAROUT",8389421}, {"FFFFTT",8389399}, {"FLOATED",8389132}, {"FROG",8389383}, {"Finished",8552575}, {"FlushClass",8421527}, {"FlushObj",8487064}, +{"Four",8683728}, {"From",8421496}, {"GLASS",8389379}, {"GLISSANT",8389419}, {"GetArray",8421578}, {"GetInventory",8421529}, @@ -576,10 +588,12 @@ {"ObjClassAt",8421550}, {"ObjDir",8487087}, {"ObjLayerAt",8421552}, {"ObjMovingTo",8421553}, {"ObjTopAt",8421554}, +{"P",8880334}, +{"P*",8880335}, {"PLAYERMOVING",8389133}, {"POSTINIT",8389138}, {"POUR",8389377}, {"POWER",8389386}, {"Player",8487027}, @@ -730,7 +744,7 @@ {"tmark",8421572}, {"tuck",8421380}, {"until",8683535}, {"while",8683536}, }; -#define N_OP_NAMES 314 +#define N_OP_NAMES 318 #endif