in lib/lexer.js [280:532]
scan() {
this.skipWhitespaces();
let start = this.loc();
if (this.peek === '/') {
if (this.readch(1) === '/') {
// consume the //
this.getch();
this.getch();
// comments
let str = '//';
while (this.peek !== '\n' && this.peek) {
str += this.peek;
this.getch();
}
return new Comment(str, {
start: start,
end: this.loc()
});
}
if (this.readch(1) === '*') {
if(this.readch(2) === '*') {
// consume the /**
this.getch();
this.getch();
this.getch();
let str = '/**';
do {
str += this.peek;
this.getch();
} while (!(this.peek === '*' && this.readch(1) === '/')); // ends with '*/'
// consume */
str += '*/';
this.getch();
this.getch();
return new Annotation(str, {
start: start,
end: this.loc()
});
}
//only /*
this.error(`Only '//' or '/**' allowed`);
}
}
if (this.inTemplate) {
if (this.peek === '}') {
let str = '';
this.getch();
let start = this.loc();
while (this.peek) {
if (this.peek === '$') {
if (this.readch(1) === '{') {
let end = this.loc();
// consume '${'
this.getch();
this.getch();
return new TemplateElement(str, false, {
start, end
});
}
}
if (this.peek === '`') {
let end = this.loc();
this.inTemplate = false;
this.getch();
return new TemplateElement(str, true, {
start, end
});
}
str += this.peek;
this.getch();
}
this.error('Unexpect end of file');
}
}
if (this.peek === '+' && this.readch(1) === '+') {
// consume '++'
this.getch();
this.getch();
return new OperatorToken(Tag.INCREMENT, '++', {
start,
end: this.loc()
});
}
if (this.peek === '-' && this.readch(1) === '-') {
// consume '--'
this.getch();
this.getch();
return new OperatorToken(Tag.DECREMENT, '--', {
start,
end: this.loc()
});
}
if (this.peek === '=' && this.readch(1) === '=') {
// consume '=='
this.getch();
this.getch();
return new OperatorToken(Tag.EQ, '==', {
start,
end: this.loc()
});
}
if(this.peek === '!' && this.readch(1) === '=') {
// consume '!='
this.getch();
this.getch();
return new OperatorToken(Tag.NEQ, '!=', {
start,
end: this.loc()
});
}
if(this.peek === '>') {
this.getch();
if(this.peek === '=') {
// consume '>='
this.getch();
return new OperatorToken(Tag.GTE, '>=', {
start,
end: this.loc()
});
}
return new OperatorToken(Tag.GT, '>', {
start,
end: this.loc()
});
}
if(this.peek === '<') {
this.getch();
if(this.peek === '=') {
// consume '>='
this.getch();
return new OperatorToken(Tag.LTE, '<=', {
start,
end: this.loc()
});
}
return new OperatorToken(Tag.LT, '<', {
start,
end: this.loc()
});
}
switch (this.peek) {
case '\'':
case '"':
return this.parseString();
case '`': {
this.inTemplate = true;
return this.parseTemplateString();
}
}
// number = optionalSign decimalLit optionalFraction optionalType
// optionalFraction = .decimalLit | ε
// decimalLit = decimalDigit { decimalDigit }
// optionalType = "L" | "f" | "d" | ε
// decimalDigit = "0" … "9"
// optionalSign = "-" | ε
if (isDecimalDigit(this.peek) ||
(this.peek === '-' && isDecimalDigit(this.readch(1)))) {
return this.parseNumber();
}
if (isLetter(this.peek) || this.peek === '_' ||
this.peek === '$') {
let str = '';
do {
if(this.peek === '-' && !isLetter(this.readch(1))) {
break;
}
str += this.peek;
this.getch();
} while (isLetter(this.peek) ||
isDecimalDigit(this.peek) ||
this.peek === '_' ||
this.peek === '-');
// reserve words
if (this.words.has(str)) {
var keyword = this.words.get(str);
return new WordToken(keyword.tag, keyword.lexeme, {
start: start,
end: this.loc()
});
}
return new WordToken(Tag.ID, str, {
start: start,
end: this.loc()
});
}
if (this.peek === '@') {
const vid = this.parseVID();
if(this.peek === '('){
return new WordToken(Tag.NOTE, vid, {
start,
end: this.loc()
});
}
return new WordToken(Tag.VID, vid, {
start,
end: this.loc()
});
}
if (this.peek === '&') {
this.getch();
if (this.peek === '&') {
this.getch();
return new OperatorToken(Tag.AND, '&&', {
start,
end: this.loc()
});
}
this.error(`Unexpect ${this.peek} after '&', expect '&'`);
}
if (this.peek === '|') {
this.getch();
if (this.peek === '|') {
this.getch();
return new OperatorToken(Tag.OR, '||', {
start,
end: this.loc()
});
}
this.error(`Unexpect ${this.peek} after '|', expect '|'`);
}
var tok = new Token(this.peek, {
start,
end: this.loc()
});
this.peek = ' ';
return tok;
}