-enum CYTokenType {
- CYTokenBreak, CYTokenCase, CYTokenCatch, CYTokenContinue, CYTokenDefault,
- CYTokenDelete, CYTokenDo, CYTokenElse, CYTokenFinally, CYTokenFor,
- CYTokenFunction, CYTokenIf, CYTokenIn, CYTokenInstanceOf, CYTokenNew,
- CYTokenReturn, CYTokenSwitch, CYTokenThis, CYTokenThrow, CYTokenTry,
- CYTokenTypeOf, CYTokenVar, CYTokenVoid, CYTokenWhile, CYTokenWith,
-
- CYTokenOpenBrace, CYTokenOpenParen, CYTokenOpenBracket,
- CYTokenCloseBrace, CYTokenCloseParen, CYTokenCloseBracket,
-
- CYTokenPeriod, CYTokenSemiColon, CYTokenComma, CYTokenLeft, CYTokenRight,
- CYTokenLeftEqual, CYTokenRightEqual, CYTokenEqualEqual, CYTokenExclamationEqual,
- CYTokenEqualEqualEqual, CYTokenExclamationEqualEqual, CYTokenPlus, CYTokenHyphen,
- CYTokenStar, CYTokenPercent, CYTokenPlusPlus, CYTokenHyphenHyphen, CYTokenLeftLeft,
- CYTokenRightRight, CYTokenRightRightRight, CYTokenAmpersand, CYTokenPipe,
- CYTokenCarrot, CYTokenExclamation, CYTokenTilde, CYTokenAmpersandAmpersand,
- CYTokenPipePipe, CYTokenQuestion, CYTokenColon, CYTokenEqual, CYTokenPlusEqual,
- CYTokenHyphenEqual, CYTokenStarEqual, CYTokenPercentEqual, CYTokenLeftLeftEqual,
- CYTokenRightRightEqual, CYTokenRightRightRightEqual, CYTokenAmpersandEqual,
- CYTokenPipeEqual, CYTokenCarrotEqual, CYTokenSlash, CYTokenSlashEqual,
-
- CYTokenIdentifier, CYTokenLiteral
-};
-
-typedef std::map<const char *, CYTokenType> TokenMap;
-TokenMap Tokens_;
-
-struct CYToken {
- enum CYTokenType type_;
- char *value_;
- CYToken *next_;
- CYToken **prev_;
-};
-
-struct CYExpression {
-};
-
-struct CYRange {
- uint64_t lo_;
- uint64_t hi_;
-
- CYRange(uint64_t lo, uint64_t hi) :
- lo_(lo), hi_(hi)
- {
- }
-
- bool operator [](uint8_t value) const {
- return !(value >> 7) && (value >> 6 ? hi_ : lo_) >> (value & 0x3f) & 0x1;
- }
-
- void operator()(uint8_t value) {
- if (value >> 7)
- return;
- (value >> 6 ? hi_ : lo_) |= uint64_t(0x1) << (value & 0x3f);
- }
-};
-
-CYRange WordStartRange_(0x1000000000LLU,0x7fffffe87fffffeLLU); // A-Za-z_$
-CYRange WordEndRange_(0x3ff001000000000LLU,0x7fffffe87fffffeLLU); // A-Za-z_$0-9
-CYRange NumberRange_(0x3ff400000000000LLU,0x100007e0100007eLLU); // 0-9.eExXA-Fa-f
-CYRange PunctuationRange_(0xfc00fc6200000000LLU,0x5000000040000000LLU); // -.,;<>=!+*/%&|^~?:
-
-struct CStringMapLess :
- std::binary_function<const char *, const char *, bool>
-{
- _finline bool operator ()(const char *lhs, const char *rhs) const {
- return strcmp(lhs, rhs) < 0;
- }
-};
-
-std::set<const char *, CStringMapLess> OperatorWords_;
-
-struct CYParser {
- FILE *fin_;
- FILE *fout_;
-
- size_t capacity_;
- char *data_;
-
- size_t offset_;
- size_t size_;
-
- CYParser(FILE *fin, FILE *fout) :
- fin_(fin),
- fout_(fout),
- capacity_(1024),
- data_(reinterpret_cast<char *>(malloc(capacity_))),
- offset_(0),
- size_(0)
- {
- }
-
- ~CYParser() {
- // XXX: this will not deconstruct in constructor failures
- free(data_);
- }
-
- bool ReadLine(const char *prompt) {
- offset_ = 0;
- data_[capacity_ - 1] = ~'\0';
-
- start:
- if (fout_ != NULL) {
- fputs(prompt, fout_);
- fputs(" ", fout_);
- fflush(fout_);
- }
-
- if (fgets(data_, capacity_, fin_) == NULL)
- return false;
-
- check:
- if (data_[capacity_ - 1] != '\0') {
- size_ = strlen(data_);
- if (size_ == 0)
- goto start;
- if (data_[size_ - 1] == '\n') {
- --size_;
- goto newline;
- }
- } else if (data_[capacity_ - 2] == '\n') {
- size_ = capacity_ - 2;
- newline:
- data_[size_] = '\0';
- } else {
- size_t capacity(capacity_ * 2);
- char *data(reinterpret_cast<char *>(realloc(data_, capacity)));
- _assert(data != NULL);
- data_ = data;
- size_ = capacity_ - 1;
- capacity_ = capacity;
- fgets(data_ + size_, capacity_ - size_, fin_);
- goto check;
- }
-
- return true;
- }
-
- _finline void ScanRange(const CYRange &range) {
- while (range[data_[++offset_]]);
- }
-
- CYToken *ParseToken(apr_pool_t *pool, const char *prompt) {
- char next;
-
- for (;;) {
- if (offset_ == size_ && (prompt == NULL || !ReadLine(prompt)))
- return false;
- next = data_[offset_];
- if (next != ' ' && next != '\t')
- break;
- ++offset_;
- }
-
- CYTokenType type;
- size_t index(offset_);
-
- if (WordStartRange_[next]) {
- ScanRange(WordEndRange_);
- type = CYTokenWord;
- } else if (next == '.') {
- char after(data_[offset_ + 1]);
- if (after >= '0' && next <= '9')
- goto number;
- goto punctuation;
- } else if (next >= '0' && next <= '9') {
- number:
- ScanRange(NumberRange_);
- type = CYTokenLiteral;
- } else if (PunctuationRange_[next]) {
- punctuation:
- ScanRange(PunctuationRange_);
- type = CYTokenPunctuation;
- } else if (next == '"' || next == '\'') {
- for (;;) {
- char after(data_[++offset_]);
- if (after == '\\') {
- after = data_[offset_];
- _assert(after != '\0');
- if (after == 'u') {
- offset_ += 4;
- _assert(offset_ < size_);
- }
- } else if (after == next)
- break;
- }
-
- ++offset_;
- type = CYTokenLiteral;
- } else if (next == '(' || next == '{' || next == '[') {
- ++offset_;
- type = CYTokenOpen;
- } else if (next == ')' || next == '}' || next == ']') {
- ++offset_;
- type = CYTokenClose;
- } else if (next == ';') {
- ++offset_;
- type = CYTokenSemiColon;
- } else {
- printf(":( %u\n", next);
- _assert(false);
- }
-
- char *value(apr_pstrndup(pool, data_ + index, offset_ - index));
-
- if (type == CYTokenWord && OperatorWords_.find(value) != OperatorWords_.end())
- type = CYTokenPunctuation;
-
- CYToken *token(new(pool) CYToken());
- token->type_ = type;
- token->value_ = value;
- token->next_ = token;
- token->prev_ = &token->next_;
- return token;
- }
-
- CYToken *ParseExpression(apr_pool_t *pool, const char *prompt) {
- CYToken *token(ParseToken(pool, prompt));
- return token;
- }
-};