static void eatComment (lexingState * st) { boolean unfinished = TRUE; boolean lastIsStar = FALSE; const unsigned char *c = st->cp + 2; while (unfinished) { /* we've reached the end of the line.. * so we have to reload a line... */ if (c == NULL || *c == '\0') { st->cp = fileReadLine (); /* WOOPS... no more input... * we return, next lexing read * will be null and ok */ if (st->cp == NULL) return; c = st->cp; } /* we've reached the end of the comment */ else if (*c == ')' && lastIsStar) unfinished = FALSE; /* here we deal with imbricated comment, which * are allowed in OCaml */ else if (c[0] == '(' && c[1] == '*') { st->cp = c; eatComment (st); c = st->cp; if (c == NULL) return; lastIsStar = FALSE; c++; } /* OCaml has a rule which says : * * "Comments do not occur inside string or character literals. * Nested comments are handled correctly." * * So if we encounter a string beginning, we must parse it to * get a good comment nesting (bug ID: 3117537) */ else if (*c == '"') { st->cp = c; eatString (st); c = st->cp; } else { lastIsStar = '*' == *c; c++; } } st->cp = c; }
static Value eatObject(std::istream& stream) { Value obj(Type::objectValue); while (!stream.eof()) { ltrim(stream); char token = stream.get(); if (token == '}') break; //empty object if (token == '/') { eatComment(stream); token = stream.get(); } assert(token == '"'); Value key = eatString(stream); ltrim(stream); token = stream.get(); assert(token == ':'); ltrim(stream); Value val = eatValue(stream); obj[key.asString()] = val; ltrim(stream); token = stream.get(); if (token == '}') break; if (token != ',') throw "arg"; assert(token == ','); } return obj; };
void eatIgnored() { bool stop(false); while (!stop){ while (isIgnored(pickChar())) eatChar(); if (_ignore_flag == ignoreFlag::None) return; stop = true; if (_ignore_flag == ignoreFlag::CppC) { if (pickString(sizeof("//") - 1) == "//") { eatString(sizeof("//") - 1); while (stream_cursor != stream_buffer.end() || pickChar() != '\n') eatChar(); stop = false; } if (pickString(sizeof("/*") - 1) == "/*") {eatString(sizeof("/*") - 1); while (pickString(sizeof("*/")-1) != "*/") eatChar(); eatString(sizeof("/*") - 1); stop = false; } } } }
std::string eatAndConvertString(void) { std::string res; auto str = eatString(); if (str.second) { v8::String::Utf8Value val(str.first); res = std::string(*val, val.length()); } return res; }
static Value eatValue(std::istream& stream) { ltrim(stream); char token = stream.get(); if (token == '{') return eatObject(stream); if (token == '[') return eatArray(stream); if ((token >= '0' && token <= '9') || token == '.' || token == '-') return eatNumeric(stream, token); if (token == '"') return eatString(stream); if (token == 't' || token == 'f') return eatBool(stream); if (token == 'n') return eatNull(stream); if (token == '/') { eatComment(stream); return eatValue(stream); } throw "Unable to parse json"; };
/* The lexer is in charge of reading the file. * Some of sub-lexer (like eatComment) also read file. * lexing is finished when the lexer return Tok_EOF */ static objcKeyword lex (lexingState * st) { int retType; /* handling data input here */ while (st->cp == NULL || st->cp[0] == '\0') { st->cp = readLineFromInputFile (); if (st->cp == NULL) return Tok_EOF; return Tok_EOL; } if (isAlpha (*st->cp) || (*st->cp == '_')) { readIdentifier (st); retType = lookupKeyword (vStringValue (st->name), Lang_ObjectiveC); if (retType == -1) /* If it's not a keyword */ { return ObjcIDENTIFIER; } else { return retType; } } else if (*st->cp == '@') { readIdentifierObjcDirective (st); retType = lookupKeyword (vStringValue (st->name), Lang_ObjectiveC); if (retType == -1) /* If it's not a keyword */ { return Tok_any; } else { return retType; } } else if (isSpace (*st->cp)) { eatWhiteSpace (st); return lex (st); } else switch (*st->cp) { case '(': st->cp++; return Tok_PARL; case '\\': st->cp++; return Tok_Backslash; case '#': st->cp++; return Tok_Sharp; case '/': if (st->cp[1] == '*') /* ergl, a comment */ { eatComment (st); return lex (st); } else if (st->cp[1] == '/') { st->cp = NULL; return lex (st); } else { st->cp++; return Tok_any; } break; case ')': st->cp++; return Tok_PARR; case '{': st->cp++; return Tok_CurlL; case '}': st->cp++; return Tok_CurlR; case '[': st->cp++; return Tok_SQUAREL; case ']': st->cp++; return Tok_SQUARER; case ',': st->cp++; return Tok_COMA; case ';': st->cp++; return Tok_semi; case ':': st->cp++; return Tok_dpoint; case '"': eatString (st); return Tok_any; case '+': st->cp++; return Tok_PLUS; case '-': st->cp++; return Tok_MINUS; case '*': st->cp++; return Tok_Asterisk; case '<': st->cp++; return Tok_ANGLEL; case '>': st->cp++; return Tok_ANGLER; default: st->cp++; break; } /* default return if nothing is recognized, * shouldn't happen, but at least, it will * be handled without destroying the parsing. */ return Tok_any; }
/* The lexer is in charge of reading the file. * Some of sub-lexer (like eatComment) also read file. * lexing is finished when the lexer return Tok_EOF */ static ocamlKeyword lex (lexingState * st) { int retType; /* handling data input here */ while (st->cp == NULL || st->cp[0] == '\0') { st->cp = fileReadLine (); if (st->cp == NULL) return Tok_EOF; } if (isAlpha (*st->cp)) { readIdentifier (st); retType = lookupKeyword (vStringValue (st->name), Lang_Ocaml); if (retType == -1) /* If it's not a keyword */ { return OcaIDENTIFIER; } else { return retType; } } else if (isNum (*st->cp)) return eatNumber (st); else if (isSpace (*st->cp)) { eatWhiteSpace (st); return lex (st); } /* OCaml permit the definition of our own operators * so here we check all the consecuting chars which * are operators to discard them. */ else if (isOperator[*st->cp]) return eatOperator (st); else switch (*st->cp) { case '(': if (st->cp[1] == '*') /* ergl, a comment */ { eatComment (st); return lex (st); } else { st->cp++; return Tok_PARL; } case ')': st->cp++; return Tok_PARR; case '[': st->cp++; return Tok_BRL; case ']': st->cp++; return Tok_BRR; case '{': st->cp++; return Tok_CurlL; case '}': st->cp++; return Tok_CurlR; case '\'': st->cp++; return Tok_Prime; case ',': st->cp++; return Tok_comma; case '=': st->cp++; return Tok_EQ; case ';': st->cp++; return Tok_semi; case '"': eatString (st); return Tok_Val; case '_': st->cp++; return Tok_Val; case '#': st->cp++; return Tok_Sharp; case '\\': st->cp++; return Tok_Backslash; default: st->cp++; break; } /* default return if nothing is recognized, * shouldn't happen, but at least, it will * be handled without destroying the parsing. */ return Tok_Val; }
String cursorToString(CXCursor cursor, unsigned flags) { const CXCursorKind kind = clang_getCursorKind(cursor); String ret; ret.reserve(256); ret += eatString(clang_getCursorKindSpelling(kind)); if (clang_isInvalid(kind)) return ret; switch (RTags::cursorType(kind)) { case Reference: ret += " r"; break; case Cursor: ret += " c"; break; case Other: ret += " o"; break; case Include: ret += " i"; break; } const String name = eatString(clang_getCursorDisplayName(cursor)); const String other = eatString(clang_getCursorSpelling(cursor)); if (!name.isEmpty()) ret += " " + name; if (other != name && !other.isEmpty()) ret += " " + other; if (clang_isCursorDefinition(cursor)) ret += " def"; if (flags & IncludeUSR) ret += " " + eatString(clang_getCursorUSR(cursor)); CXFile file; unsigned off, line, col; //presumedLine, presumedCol, instantiationLoc, expansionLoc; CXSourceLocation location = clang_getCursorLocation(cursor); clang_getSpellingLocation(location, &file, &line, &col, &off); // clang_getPresumedLocation(location, 0, &presumedLine, &presumedCol); // clang_getInstantiationLocation(location, 0, 0, 0, &instantiationLoc); // clang_getExpansionLocation(location, 0, 0, 0, &expansionLoc); const Str fileName(clang_getFileName(file)); if (fileName.data() && *fileName.data()) { ret += ' '; ret += fileName.data(); ret += ','; ret += String::number(off); if (flags & IncludeRange) { ret += " ("; CXSourceRange range = clang_getCursorExtent(cursor); unsigned start, end; clang_getSpellingLocation(clang_getRangeStart(range), 0, 0, 0, &start); clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &end); ret += String::number(start); ret += '-'; ret += String::number(end); ret += ')'; } // if (presumedLine != line || presumedCol != col) // ret += String::snprintf<32>("presumed: %d:%d", presumedLine, presumedCol); // if (instantiationLoc != off) // ret += String::snprintf<32>("instantiation: %d", instantiationLoc); // if (expansionLoc != off) // ret += String::snprintf<32>("expansion: %d", expansionLoc); } return ret; }