TokenT *_decimal(TokenizerT *tk) { nextChar(tk); if(isdigit(tk->inputIter[0])) { return _decimal(tk); } else if(tk->inputIter[0] == '.') { return _float(tk, 1); } else if(tk->inputIter[0] == 'e' || tk->inputIter[0] == 'E') { return _expofloat(tk, 1, 0); } else { return makeToken(tk, "decimal integer"); } }
static inline char *_toNumber(char *str,long long value,_bool sign, HexBase base,int size,int style,int mask){ char signString = '+'; const char *dig = _lowerDigits; int tmp[64]; //缓存转换后的值.还不是ASCII int length = 0; if(style & STYLE_LARGE) dig = _upperDigits; if(style & STYLE_LEFT) style &= (~STYLE_ZEROPAD); //左对齐就不能使用0填充 //如果不是10进制,则都按无符号处理 ,并且无正负符号显示 //如果是10进制,则去除前缀属性 if(DECIMAL != base){ sign = _false; style &= ~STYLE_SIGN; } else { style &= ~STYLE_SPECIAL; } if(style & STYLE_SPECIAL){ if(HEX == base) size -= 2; else if(OCTAL == base) size -= 1; } //如果是有符号数,却小于0,则取其补码,并设置符号标志,非16进制在前面已经去除 //符号,所以不会受影响 if((_true == sign) && ((long long)value) < 0){ style |= STYLE_SIGN; value = ~value + 1; signString = '-'; } value &= mask; if(style & STYLE_SIGN) size --; switch(base){ case OCTAL:length = _octal(tmp,value);break; case DECIMAL:length = _decimal(tmp,value);break; case HEX:length = _hex(tmp,value);break; } size -= length; if(!(style & (STYLE_ZEROPAD|STYLE_LEFT))) while(size-- > 0) *str++ = ' '; if(style & STYLE_SIGN) *str++ = signString; if(style & STYLE_SPECIAL){ *str++ = '0'; if(HEX == base) *str++ = dig[0x10]; } if(style & STYLE_ZEROPAD) while(size-- > 0) *str++ = '0'; while(length-- > 0) *str++ = dig[tmp[length]]; if(style & STYLE_LEFT) while(size-- > 0) *str++ = ' '; return str; }
/* * TKGetNextToken returns the next token from the token stream as a * character string. Space for the returned token should be dynamically * allocated. The caller is responsible for freeing the space once it is * no longer needed. * * If the function succeeds, it returns a C string (delimited by '\0') * containing the token. Else it returns 0. * * You need to fill in this function as part of your implementation. */ TokenT *TKGetNextToken(TokenizerT *tk) { clearBuffer(tk); char curr = tk->inputIter[0]; // skip all whitespace before next token while(isspace(curr)) { nextChar(tk); clearBuffer(tk); curr = tk->inputIter[0]; } if(curr == '\0') { return NULL; } else if(isalpha(curr) || curr == '_') { return _word(tk); } else if(curr == '0') { return _zero(tk); } else if(isdigit(curr)) { return _decimal(tk); } else if(curr == '!') { // neq return _neq(tk); } else if(curr == '"') { // double_quote return _double_quote(tk); } else if(curr == '#') { return _pound(tk); } else if(curr == '$') { // INVALID return _invalid(tk); } else if(curr == '%') { // mod, mod_eq return _mod(tk); } else if(curr == '&') { // bit_and, log_and, address (?) return _bit_and(tk); } else if(curr == '\'') { // single_quote return _single_quote(tk); } else if(curr == '(') { // open_paren return _open_paren(tk); } else if(curr == ')') { // close_paren return _close_paren(tk); } else if(curr == '*') { // mult, mult_eq, pointer (?) return _mult(tk); } else if(curr == '+') { // plus, plus_eq, inc return _plus(tk); } else if(curr == ',') { // comma return _comma(tk); } else if(curr == '-') { // minus, minus_eq, dec, struct_pointer return _minus(tk); } else if(curr == '.') { // dot return _dot(tk); } else if(curr == '/') { // div, div_eq return _div(tk); } else if(curr == ':') { // ternary_colon return _ternary_colon(tk); } else if(curr == ';') { // semicolon return _semicolon(tk); } else if(curr == '<') { // lt, lshift, lt_eq return _lt(tk); } else if(curr == '=') { // eq, assign return _eq(tk); } else if(curr == '>') { // gt, rshift, gt_eq return _gt(tk); } else if(curr == '?') { // ternary_qmark return _ternary_qmark(tk); } else if(curr == '@') { // INVALID return _invalid(tk); } else if(curr == '[') { // open_bracket return _open_bracket(tk); } else if(curr == '\\') { // backslash (?) return _invalid(tk); } else if(curr == ']') { // close_bracket return _close_bracket(tk); } else if(curr == '^') { // bit_xor return _bit_xor(tk); } else if(curr == '`') { // INVALID return _invalid(tk); } else if(curr == '{') { // open_brace return _open_brace(tk); } else if(curr == '|') { // bit_or, log_or return _bit_or(tk); } else if(curr == '}') { // close_brace return _close_brace(tk); } else if(curr == '~') { // bit_not return _bit_not(tk); } else { return _invalid(tk); } }
int nmea_parse(char c) { // avoid runaway sentences (>99 chars or >29 terms) and terms (>14 chars) if ((n >= 100) || (_terms >= 30) || (_nt >= 15)) { _state = 0; } // LF and CR always reset parser if ((c == 0x0A) || (c == 0x0D)) { _state = 0; } // '$' always starts a new sentence if (c == '$') { _gprmc_tag = 0; _parity = 0; _terms = 0; _nt = 0; _sentence[0] = c; n = 1; _state = 1; return 0; } // parse other chars according to parser state switch(_state) { case 0: // waiting for '$', do nothing break; case 1: // decode chars after '$' and before '*' found if (n < 7) { // see if first seven chars match "$GPRMC," if (c == _GPRMC_TERM[n]) { _gprmc_tag++; } } // add received char to sentence _sentence[n++] = c; switch (c) { case ',': // ',' delimits the individual terms (_term[_terms++])[_nt] = 0; _nt = 0; _parity = _parity ^ c; break; case '*': // '*' delimits term and precedes checksum term (_term[_terms++])[_nt] = 0; _nt = 0; _state++; break; default: // all other chars between '$' and '*' are part of a term (_term[_terms])[_nt++] = c; _parity = _parity ^ c; break; } break; case 2: // first char following '*' is checksum MSB _sentence[n++] = c; (_term[_terms])[_nt++] = c; _parity = _parity - (16 * _dehex(c)); // replace with bitshift? _state++; break; case 3: // second char after '*' completes the checksum (LSB) _sentence[n++] = c; _sentence[n++] = 0; (_term[_terms])[_nt++] = c; (_term[_terms++])[_nt] = 0; _state = 0; _parity = _parity - _dehex(c); // when parity is zero, checksum was correct! if (_parity == 0) { // accept all sentences, or only GPRMC datatype? if ((!_gprmc_only) || (_gprmc_tag == 6)) { // copy _sentence[] to f_sentence[] while ((--n) >= 0) { f_sentence[n] = _sentence[n]; } // copy all _terms[] to f_terms[] for (f_terms=0; f_terms<_terms; f_terms++) { _nt = 0; while ((_term[f_terms])[_nt]) { (f_term[f_terms])[_nt] = (_term[f_terms])[_nt]; _nt++; } (f_term[f_terms])[_nt] = 0; } // when sentence is of datatype GPRMC if (_gprmc_tag == 6) { // store values of relevant GPRMC terms _gprmc_utc = _decimal(_term[1]); _gprmc_status = (_term[2])[0]; // calculate signed degree-decimal value of latitude term _gprmc_lat = _decimal(_term[3]) / 100.0; _degs = floor(_gprmc_lat); _gprmc_lat = (100.0 * (_gprmc_lat - _degs)) / 60.0; _gprmc_lat += _degs; // southern hemisphere is negative-valued if ((_term[4])[0] == 'S') { _gprmc_lat = 0.0 - _gprmc_lat; } // calculate signed degree-decimal value of longitude term _gprmc_long = _decimal(_term[5]) / 100.0; _degs = floor(_gprmc_long); _gprmc_long = (100.0 * (_gprmc_long - _degs)) / 60.0; _gprmc_long += _degs; // western hemisphere is negative-valued if ((_term[6])[0] == 'W') { _gprmc_long = 0.0 - _gprmc_long; } _gprmc_speed = _decimal(_term[7]); _gprmc_angle = _decimal(_term[8]); } // sentence accepted! return 1; } } break; default: _state = 0; break; } return 0; }
float nmea_term_decimal(int t) { // returns value of decimally coded term t return _decimal(f_term[t]); }