@abaplint/core
Version:
abaplint - Core API
358 lines • 13.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Lexer = void 0;
const position_1 = require("../../position");
const virtual_position_1 = require("../../virtual_position");
const tokens_1 = require("./tokens");
const lexer_buffer_1 = require("./lexer_buffer");
const lexer_stream_1 = require("./lexer_stream");
class Lexer {
constructor() {
this.ModeNormal = 1;
this.ModePing = 2;
this.ModeStr = 3;
this.ModeTemplate = 4;
this.ModeComment = 5;
this.ModePragma = 6;
}
run(file, virtual) {
this.virtual = virtual;
this.tokens = [];
this.m = this.ModeNormal;
this.process(file.getRaw());
return { file, tokens: this.tokens };
}
add() {
const s = this.buffer.get().trim();
if (s.length > 0) {
const col = this.stream.getCol();
const row = this.stream.getRow();
let whiteBefore = false;
if (this.stream.getOffset() - s.length >= 0) {
const prev = this.stream.getRaw().substr(this.stream.getOffset() - s.length, 1);
if (prev === " " || prev === "\n" || prev === "\t" || prev === ":") {
whiteBefore = true;
}
}
let whiteAfter = false;
const next = this.stream.nextChar();
if (next === " " || next === "\n" || next === "\t" || next === ":" || next === "," || next === "." || next === "" || next === "\"") {
whiteAfter = true;
}
let pos = new position_1.Position(row, col - s.length);
if (this.virtual) {
pos = new virtual_position_1.VirtualPosition(this.virtual, pos.getRow(), pos.getCol());
}
let tok = undefined;
if (this.m === this.ModeComment) {
tok = new tokens_1.Comment(pos, s);
}
else if (this.m === this.ModePing || this.m === this.ModeStr) {
tok = new tokens_1.StringToken(pos, s);
}
else if (this.m === this.ModeTemplate) {
const first = s.charAt(0);
const last = s.charAt(s.length - 1);
if (first === "|" && last === "|") {
tok = new tokens_1.StringTemplate(pos, s);
}
else if (first === "|" && last === "{" && whiteAfter === true) {
tok = new tokens_1.StringTemplateBegin(pos, s);
}
else if (first === "}" && last === "|" && whiteBefore === true) {
tok = new tokens_1.StringTemplateEnd(pos, s);
}
else if (first === "}" && last === "{" && whiteAfter === true && whiteBefore === true) {
tok = new tokens_1.StringTemplateMiddle(pos, s);
}
else {
tok = new tokens_1.Identifier(pos, s);
}
}
else if (s.length > 2 && s.substr(0, 2) === "##") {
tok = new tokens_1.Pragma(pos, s);
}
else if (s.length === 1) {
if (s === "." || s === ",") {
tok = new tokens_1.Punctuation(pos, s);
}
else if (s === "[") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WBracketLeftW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WBracketLeft(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.BracketLeftW(pos, s);
}
else {
tok = new tokens_1.BracketLeft(pos, s);
}
}
else if (s === "(") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WParenLeftW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WParenLeft(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.ParenLeftW(pos, s);
}
else {
tok = new tokens_1.ParenLeft(pos, s);
}
}
else if (s === "]") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WBracketRightW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WBracketRight(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.BracketRightW(pos, s);
}
else {
tok = new tokens_1.BracketRight(pos, s);
}
}
else if (s === ")") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WParenRightW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WParenRight(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.ParenRightW(pos, s);
}
else {
tok = new tokens_1.ParenRight(pos, s);
}
}
else if (s === "-") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WDashW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WDash(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.DashW(pos, s);
}
else {
tok = new tokens_1.Dash(pos, s);
}
}
else if (s === "+") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WPlusW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WPlus(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.PlusW(pos, s);
}
else {
tok = new tokens_1.Plus(pos, s);
}
}
else if (s === "@") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WAtW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WAt(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.AtW(pos, s);
}
else {
tok = new tokens_1.At(pos, s);
}
}
}
else if (s.length === 2) {
if (s === "->") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WInstanceArrowW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WInstanceArrow(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.InstanceArrowW(pos, s);
}
else {
tok = new tokens_1.InstanceArrow(pos, s);
}
}
else if (s === "=>") {
if (whiteBefore === true && whiteAfter === true) {
tok = new tokens_1.WStaticArrowW(pos, s);
}
else if (whiteBefore === true) {
tok = new tokens_1.WStaticArrow(pos, s);
}
else if (whiteAfter === true) {
tok = new tokens_1.StaticArrowW(pos, s);
}
else {
tok = new tokens_1.StaticArrow(pos, s);
}
}
}
if (tok === undefined) {
tok = new tokens_1.Identifier(pos, s);
}
this.tokens.push(tok);
}
this.buffer.clear();
}
process(raw) {
this.stream = new lexer_stream_1.LexerStream(raw.replace(/\r/g, ""));
this.buffer = new lexer_buffer_1.LexerBuffer();
const splits = {};
splits[" "] = true;
splits[":"] = true;
splits["."] = true;
splits[","] = true;
splits["-"] = true;
splits["+"] = true;
splits["("] = true;
splits[")"] = true;
splits["["] = true;
splits["]"] = true;
splits["\t"] = true;
splits["\n"] = true;
const bufs = {};
bufs["."] = true;
bufs[","] = true;
bufs[":"] = true;
bufs["("] = true;
bufs[")"] = true;
bufs["["] = true;
bufs["]"] = true;
bufs["+"] = true;
bufs["@"] = true;
for (;;) {
const current = this.stream.currentChar();
const buf = this.buffer.add(current);
const ahead = this.stream.nextChar();
const aahead = this.stream.nextNextChar();
if (this.m === this.ModeNormal) {
if (splits[ahead]) {
this.add();
}
else if (ahead === "'") {
// start string
this.add();
this.m = this.ModeStr;
}
else if (ahead === "|" || ahead === "}") {
// start template
this.add();
this.m = this.ModeTemplate;
}
else if (ahead === "`") {
// start ping
this.add();
this.m = this.ModePing;
}
else if (aahead === "##") {
// start pragma
this.add();
this.m = this.ModePragma;
}
else if (ahead === "\""
|| (ahead === "*" && current === "\n")) {
// start comment
this.add();
this.m = this.ModeComment;
}
else if (ahead === "@" && buf.trim().length === 0) {
this.add();
}
else if (aahead === "->"
|| aahead === "=>") {
this.add();
}
else if (current === ">"
&& ahead !== " "
&& (this.stream.prevChar() === "-" || this.stream.prevChar() === "=")) {
// arrows
this.add();
}
else if (buf.length === 1
&& (bufs[buf]
|| (buf === "-" && ahead !== ">"))) {
this.add();
}
}
else if (this.m === this.ModePragma && (ahead === "," || ahead === ":" || ahead === "." || ahead === " " || ahead === "\n")) {
// end of pragma
this.add();
this.m = this.ModeNormal;
}
else if (this.m === this.ModePing
&& buf.length > 1
&& current === "`"
&& aahead !== "``"
&& ahead !== "`"
&& this.buffer.countIsEven("`")) {
// end of ping
this.add();
if (ahead === `"`) {
this.m = this.ModeComment;
}
else {
this.m = this.ModeNormal;
}
}
else if (this.m === this.ModeTemplate
&& buf.length > 1
&& (current === "|" || current === "{")
&& (this.stream.prevChar() !== "\\" || this.stream.prevPrevChar() === "\\\\")) {
// end of template
this.add();
this.m = this.ModeNormal;
}
else if (this.m === this.ModeTemplate
&& ahead === "}"
&& current !== "\\") {
this.add();
}
else if (this.m === this.ModeStr
&& current === "'"
&& buf.length > 1
&& aahead !== "''"
&& ahead !== "'"
&& this.buffer.countIsEven("'")) {
// end of string
this.add();
if (ahead === "\"") {
this.m = this.ModeComment;
}
else {
this.m = this.ModeNormal;
}
}
else if (ahead === "\n" && this.m !== this.ModeTemplate) {
this.add();
this.m = this.ModeNormal;
}
else if (this.m === this.ModeTemplate && current === "\n") {
this.add();
}
if (!this.stream.advance()) {
break;
}
}
this.add();
}
}
exports.Lexer = Lexer;
//# sourceMappingURL=lexer.js.map