// ---- Преобразование текущего символа для констукций типа: \n, \x00, т.п. byte ConvertChar() dword hold; { IF(cha!='\\')return(cha); NextChar(); // Обработка следующего за \ IF(AL>='0')&&(AL<='9'){ // Десятичная константа EDX=0; AL-='0'; EAX=AL; EDX+=EAX; ECX=2; loop(ECX){ EBX=EDX; EDX<<=1; EBX<<=3; EDX+=EBX; NextChar(); EAX=AL; IF(AL<'0')||(AL>'9')GOTO ERR; AL-='0'; EDX+=EAX; } return(DL); ERR: expectederror("decimal digit"); return(0); } IF(cha=='a')return('\a'); IF(cha=='b') return('\b'); IF(cha=='f') return('\f'); IF(cha=='l') return(10); IF(cha=='n') return(13); IF(cha=='p') return('_'); IF(cha=='r') return(13); IF(cha=='t') return('\t'); IF(cha=='v') return('\v'); IF(cha=='x'){ // HEX константа ECX=2; hold=0; loop(ECX){ $PUSH ECX; NextChar(); CharUpperA(AL); EBX=AL; IF(AL>='0')&&(AL<='9')GOTO LX1; IF(AL<'A')&&(AL>'F')GOTO ERR1; LX1: EDX=hold; EDX<<=4; IF(BL>='A')BL-='A'-10-'0'; BL-='0'; EDX+=EBX; hold=EDX; $POP ECX; } return(hold); ERR1: $POP ECX; expectederror("hexdecimal digit"); return(0); } return(cha); } // ---- Разделители byte Delim1={'#','\"','\'','-','+','*','/','%','|','&','!','^','=','>','<','@',0}; byte Delim2={':',';','(',')','{','}','[',']',',','.','$','?','~',0}; // ---- Определение типа token TokScan(dword tok4,type4,src4,post4,string4,number4) dword useme,strptr; dword next; dword dirPrefix,locPrefix;// Флаги обнаружения #directive или @LocalLabel { dirPrefix=0; locPrefix=0; SC_0: strptr=string4; next=1; EAX=number4; DSDWORD[EAX] = 0; EAX=type4; DSDWORD[EAX] = 0; EAX=src4; DSDWORD[EAX] = 0; EAX=post4; DSDWORD[EAX] = 0; WhiteSpaces(); ESI=string4; DSBYTE[ESI]=0; ECX=17; EDI=#Delim1; AL=cha; $REPNZ $SCASB; $JCXZ SC00 // Не первая группа разделителе EDI=EDI-#Delim1-1<<2+#Jmp_Delim1; $JMP NEAR DSDWORD[EDI]; SC00: ECX=14; EDI=#Delim2; AL=cha; $REPNZ $SCASB; $JCXZ SC01 // Не вторая группа разделителе EDI=EDI-#Delim2-1+#tk_delim2; EAX=DSBYTE[EDI]; EBX=tok4; DSDWORD[EBX]=EAX; $JMP ScEx SC01: IF(locPrefix){ EDI>=IDLENGTH){ preerror("Maximum length for an identifier exceeded"); strptr = string4 + IDLENGTH - 1; } EDI=strptr; AL=0; $STOSB EBX=tok4; DSDWORD[EBX]=tk_id; IF(locPrefix)goto FL; FastSearch(string4,#St_Directives); // Это зарезервированное слово? IF(CARRYFLAG){ // Команда обнаружена в списке EBX=number4; DSDWORD[EBX]=EAX; // Запомним порядковый номер EBX=tok4; // Укажем соответствующий token IF(dirPrefix)DSDWORD[EBX]=tk_directive; ELSE DSDWORD[EBX]=tk_command; dirPrefix=0; next=0; $JMP ScEx } FastSearch(string4,#St_Mnemonics); // Это мнемоника? IF(CARRYFLAG){ // Мнемоника ассемблера EBX=number4; DSDWORD[EBX]=EAX; // Запомним номер мнемоники EBX=tok4; DSDWORD[EBX]=tk_mnemonics; next=0; $JMP ScEx } FastSearch(string4,#St_Registers); // Это имя регистра? IF(CARRYFLAG){ // Регистр EBX=number4; DSDWORD[EBX]=EAX; // Запомним номер региста EAX>>=3; $CMP EAX,2; $JG R0 // Управляющие регистры? EBX=tok4; DSDWORD[EBX]=tk_reg; EBX=type4; EAX<<=1; DSDWORD[EBX] = EAX + tk_byte; GOTO R1; R0: EBX=tok4; EAX-=3; DSDWORD[EBX]=EAX+tk_controlreg; R1: next=0; $JMP ScEx } FL: EAX=tok4; EAX=DSDWORD[EAX]; IF(AL==tk_id){ SearchLocals(tok4,type4,string4,number4); // Есть в списке локальных? EAX=tok4; EAX=DSDWORD[EAX]; IF(AL==tk_id){ IF(locPrefix){ // @label EBX=tok4; DSDWORD[EBX]=tk_locallabel; IF(displaytokerrors)AddLocalvar(#string,tk_locallabel,0,0); locPrefix=0; GOTO FL; } SearchTree(tok4,type4,src4,post4,string4,number4); } } IF(dirPrefix){ // Конструкция: #ident dirPrefix=0; EBX=tok4; EAX=DSDWORD[EBX]; IF(AL==tk_id){ // Есть в списке? IF(displaytokerrors){ EAX=post4; DSDWORD[EAX] = 1; // Добавим в список EBX=tok4; DSDWORD[EBX]=tk_undefproc; AddToTree(string4); } } // Идентификатор есть в списке EAX=post4; EAX=DSDWORD[EAX]; EBX=tok4; IF(EAX){ // Еще не обработанный идентификатор? DSDWORD[EBX] = tk_postnumber; } ELSE{ EAX=tok4; EAX=DSDWORD[EAX]; IF(EAX==tk_param)DSDWORD[EBX] = tk_locnumber; ELSE IF(EAX==tk_local)DSDWORD[EBX] = tk_locnumber; ELSE DSDWORD[EBX] = tk_number; } } next=0; $JMP ScEx } else if(IsNumber(cha)){ // Идентификатор начинается с цифры EAX=tok4; DSDWORD[EAX]=tokens; // Пока неизвестный token if(cha=='0'){ NextChar(); IF(cha=='X')||(cha=='x'){ // hex - число EAX=tok4; DSDWORD[EAX]=tk_number; HEX: NextChar(); CharUpperA(AL); $CMP AL,'0'; $JL EHEX; $CMP AL,'9'; $JA HEXAF AL-='0'; for(;;){ EBX=number4; ECX=DSDWORD[EBX]; ECX<<=4; EAX+=ECX; DSDWORD[EBX]=EAX; GOTO HEX; HEXAF: IF(AL<'A')||(AL>'F')BREAK; AL-='7'; } EHEX: } ELSE IF(cha=='B')||(cha=='b'){ // binary число EAX=tok4; DSDWORD[EAX]=tk_number; for(;;){ NextChar(); IF(AL!='0')||(AL!='1')BREAK; AL-='0'; EBX=number4; ECX=DSDWORD[EBX]; ECX<<=1; EAX+=ECX; DSDWORD[EBX]=EAX; } EBIN: } ELSE IF(cha=='O')||(cha=='o'){ // octal число EAX=tok4; DSDWORD[EAX]=tk_number; for(;;){ NextChar(); IF(AL<'0')||(AL>'7')BREAK; AL-='0'; EBX=number4; ECX=DSDWORD[EBX]; ECX<<=3; EAX+=ECX; DSDWORD[EBX]=EAX; } EOCT: } } EAX=tok4; EAX=DSDWORD[EAX]; IF(EAX!=tk_number){ // decimal число for(;;){ EAX=cha; IF(AL<'0')||(AL>'9')BREAK; AL-='0'; EBX=number4; EDX=DSDWORD[EBX]; ECX=EDX; EDX<<=1; ECX<<=3; EDX+=ECX; EAX+=EDX; DSDWORD[EBX]=EAX; NextChar(); } EAX=tok4; DSDWORD[EAX]=tk_number; } next=0; } ELSE{ IF(displaytokerrors)preerror("tokenizer: bad character value"); NextChar(); TokScan(tok4,type4,src4,post4,string4,number4); next=0; } $JMP ScEx Jmp_Number: // #directive || #identifier NextChar(); dirPrefix=1; $JMP SC_0 Jmp_Local: // @LocalLabel NextChar(); locPrefix=1; $JMP SC01 Jmp_String: // Строка символов в "" do{ NextChar(); IF(cha=='\"') // Закрывающая кавычка BREAK; EAX=strptr-string4; IF(EAX0){ WhiteSpaces(); IF( cha == '*' ){ NextChar(); IF(cha == '/' ){ // Закрытие комментария IF(useme > 0)useme--; // Уменишим счетчик NextChar(); } } ELSE{ IF( cha == '/' ){ NextChar(); IF( cha == '*' ){ // Вложенный комментарий useme++; NextChar(); } } ELSE // Не ограничители комментария NextChar(); } } IF(endoffile){ EAX=tok4; DSDWORD[EAX]=tk_eof; IF(useme > 0)&&(displaytokerrors)unexpectedeof(); } ELSE TokScan(tok4,type4,src4,post4,string4,number4); } ELSE IF(cha=='/'){ // Комментарий до конца строки // do{ NextChar(); IF(endoffile)BREAK; } while(cha!=10 ); IF(endoffile){ EAX=tok4; DSDWORD[EAX]=tk_eof; } ELSE{ WhiteSpaces(); TokScan(tok4,type4,src4,post4,string4,number4); } } ELSE{ WhiteSpaces(); IF(cha=='-'){ EAX=tok4; DSDWORD[EAX]=tk_divminus; // /- NextChar(); } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_div; // / } } next = 0; $JMP ScEx Jmp_Mod: // % NextChar(); WhiteSpaces(); IF(cha == '-'){ EAX=tok4; DSDWORD[EAX] = tk_modminus; // %- } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_mod; next=0; } $JMP ScEx Jmp_Or: // | NextChar(); IF(cha=='='){ EAX=tok4; DSDWORD[EAX]=tk_orequals; // |= } ELSE IF(cha=='|'){ EAX=tok4; DSDWORD[EAX]=tk_oror; // || } ELSE{ WhiteSpaces(); IF(cha=='-'){ EAX=tok4; DSDWORD[EAX]=tk_orminus; // |- } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_or; next=0; // | } } $JMP ScEx Jmp_And: // & NextChar(); IF(cha=='='){ EAX=tok4; DSDWORD[EAX]=tk_andequals; // &= } ELSE IF(cha=='&'){ EAX=tok4; DSDWORD[EAX]=tk_andand; // && } ELSE{ WhiteSpaces(); IF(cha == '-'){ EAX=tok4; DSDWORD[EAX]=tk_andminus; // &- } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_and; next=0;// & } } $JMP ScEx Jmp_Not: // ! NextChar(); IF(cha == '='){ EAX=tok4; DSDWORD[EAX]=tk_notequal; // != } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_not; next=0; // ! } $JMP ScEx Jmp_Xor: // ^ NextChar(); IF(cha == '='){ EAX=tok4; DSDWORD[EAX]=tk_xorequals; // ^= } ELSE{ WhiteSpaces(); IF(cha == '-'){ EAX=tok4; DSDWORD[EAX]=tk_xorminus; // ^- } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_xor; next=0; // ^ } } $JMP ScEx Jmp_Equal: // = NextChar(); IF(cha == '='){ EAX=tok4; DSDWORD[EAX]=tk_equalto; // == } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_assign; next=0; // = } $JMP ScEx Jmp_Great: // > NextChar(); IF(cha=='>'){ NextChar(); IF( cha == '=' ){ EAX=tok4; DSDWORD[EAX]=tk_rrequals; // >>= } ELSE{ WhiteSpaces(); IF(cha == '-'){ EAX=tok4; DSDWORD[EAX]=tk_rrminus; // >>- } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_rr; next=0;// >> } } } ELSE IF(cha=='<'){ EAX=tok4; DSDWORD[EAX]=tk_swap; // >< } ELSE IF(cha=='='){ EAX=tok4; DSDWORD[EAX]=tk_greaterequal; // >= } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_greater; next= 0; // > } GOTO ScEx; Jmp_Less: // < NextChar(); IF(cha=='<'){ NextChar(); IF(cha=='='){ EAX=tok4; DSDWORD[EAX]=tk_llequals; // <<= } ELSE{ WhiteSpaces(); IF(cha == '-'){ EAX=tok4; DSDWORD[EAX]=tk_llminus; // <<- } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_ll; next=0; } } } ELSE IF(cha=='>'){ EAX=tok4; DSDWORD[EAX]=tk_notequal; // <> } ELSE IF(cha=='='){ EAX=tok4; DSDWORD[EAX]=tk_lessequal; // <= } ELSE{ EAX=tok4; DSDWORD[EAX]=tk_less; next=0; // < } ScEx: IF(next)NextChar(); } // '#','\"','\'','-','+','*','/','%','|','&','!','^','=','>','<','@' dword Jmp_Delim1={#Jmp_Number,#Jmp_String,#Jmp_Const,#Jmp_Minus, #Jmp_Plus,#Jmp_Mul,#Jmp_Div,#Jmp_Mod,#Jmp_Or,#Jmp_And, #Jmp_Not,#Jmp_Xor,#Jmp_Equal,#Jmp_Great,#Jmp_Less,#Jmp_Local}; // ':', ';', '(', ')', byte tk_delim2={tk_colon,tk_semicolon,tk_openbracket,tk_closebracket, // '{', '}', '[', ']', ',', tk_openbrace,tk_closebrace,tk_openblock,tk_closeblock,tk_comma, //'.', '$', '?', '~' tk_period,tk_dollar,tk_question,tk_tilda};