Discard empty lines at tokenizer level

This commit is contained in:
Rene Saarsoo 2020-09-22 22:17:14 +03:00
parent eb4d0a3735
commit c1eaae4b26
2 changed files with 24 additions and 13 deletions

View File

@ -27,10 +27,7 @@ const parseHeader = (tokens: Token[]): [Header, Token[]] => {
while (tokens[0]) { while (tokens[0]) {
const token = tokens[0]; const token = tokens[0];
if (token.type === "text" && token.value === "") { if (token.type === "header" && token.value === "Name") {
// Ignore empty lines before header
tokens.shift();
} else if (token.type === "header" && token.value === "Name") {
tokens.shift(); tokens.shift();
const [name, rest] = extractText(tokens); const [name, rest] = extractText(tokens);
header.name = name; header.name = name;
@ -73,9 +70,6 @@ const parseIntervalComments = (tokens: Token[]): [Comment[], Token[]] => {
text: text.value, text: text.value,
}); });
tokens = rest; tokens = rest;
} else if (start.type === "text" && start.value === "") {
// skip empty lines
tokens.shift();
} else { } else {
break; break;
} }
@ -135,8 +129,6 @@ const parseIntervals = (tokens: Token[]): Interval[] => {
comments, comments,
}); });
tokens = rest; tokens = rest;
} else if (token.type === "text" && token.value === "") {
// Ignore empty lines
} else { } else {
throw new ParseError(`Unexpected token ${tokenToString(token)}`, token.loc); throw new ParseError(`Unexpected token ${tokenToString(token)}`, token.loc);
} }

View File

@ -150,19 +150,38 @@ const tokenizeLabeledLine = (line: string, row: number): Token[] | undefined =>
throw new ParseError(`Unknown label "${label}:"`, { row, col: 0 }); throw new ParseError(`Unknown label "${label}:"`, { row, col: 0 });
}; };
const tokenizeText = (line: string, row: number): TextToken[] => { const tokenizeText = (line: string, row: number, afterDescription: boolean): TextToken[] => {
if (!afterDescription && line.trim() === "") {
// Ignore empty lines in most cases.
// They're only significant inside description.
return [];
}
return [{ type: "text", value: line.trim(), loc: { row, col: 0 } }]; return [{ type: "text", value: line.trim(), loc: { row, col: 0 } }];
}; };
const tokenizeRule = (line: string, row: number): Token[] => { const tokenizeRule = (line: string, row: number, afterDescription: boolean): Token[] => {
return tokenizeLabeledLine(line, row) || tokenizeComment(line, row) || tokenizeText(line, row); return tokenizeLabeledLine(line, row) || tokenizeComment(line, row) || tokenizeText(line, row, afterDescription);
};
// True when last token is "Description:" (optionally followed by any number of text tokens)
const isAfterDescription = (tokens: Token[]): boolean => {
for (let i = tokens.length - 1; i >= 0; i--) {
const token = tokens[i];
if (token.type === "text") {
// skip
}
if (token.type === "header" && token.value === "Description") {
return true;
}
}
return false;
}; };
export const tokenize = (file: string): Token[] => { export const tokenize = (file: string): Token[] => {
const tokens: Token[] = []; const tokens: Token[] = [];
file.split("\n").map((line, row) => { file.split("\n").map((line, row) => {
tokens.push(...tokenizeRule(line, row)); tokens.push(...tokenizeRule(line, row, isAfterDescription(tokens)));
}); });
return tokens; return tokens;