Parsing of workout header
This commit is contained in:
parent
220ca26c97
commit
2a362e6362
|
|
@ -1,4 +1,5 @@
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
import { parse } from "./parser";
|
||||||
import { tokenizeFile } from "./tokenizer";
|
import { tokenizeFile } from "./tokenizer";
|
||||||
|
|
||||||
const filename = process.argv[2];
|
const filename = process.argv[2];
|
||||||
|
|
@ -7,6 +8,6 @@ console.log(`Parsing: ${filename}`);
|
||||||
|
|
||||||
const file = fs.readFileSync(filename, "utf8");
|
const file = fs.readFileSync(filename, "utf8");
|
||||||
|
|
||||||
tokenizeFile(file).forEach((token) => {
|
const workout = parse(tokenizeFile(file));
|
||||||
console.log(token.type, token.value);
|
|
||||||
});
|
console.log(workout);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Interval, Workout } from "./ast";
|
||||||
|
import { LabelTokenValue, Token } from "./tokenizer";
|
||||||
|
|
||||||
|
type Header = {
|
||||||
|
name?: string;
|
||||||
|
author?: string;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const extractText = (tokens: Token[]): [string, Token[]] => {
|
||||||
|
let text;
|
||||||
|
while (tokens[0] && tokens[0].type === "text") {
|
||||||
|
if (text === undefined) {
|
||||||
|
text = tokens[0].value;
|
||||||
|
} else {
|
||||||
|
text += "\n" + tokens[0].value;
|
||||||
|
}
|
||||||
|
tokens.shift();
|
||||||
|
}
|
||||||
|
return [text || "", tokens];
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseHeader = (tokens: Token[]): [Header, Token[]] => {
|
||||||
|
const header: Header = {};
|
||||||
|
|
||||||
|
while (tokens[0]) {
|
||||||
|
const token = tokens[0];
|
||||||
|
if (token.type === "label" && token.value === LabelTokenValue.Name) {
|
||||||
|
tokens.shift();
|
||||||
|
const [name, rest] = extractText(tokens);
|
||||||
|
header.name = name;
|
||||||
|
tokens = rest;
|
||||||
|
} else if (
|
||||||
|
token.type === "label" &&
|
||||||
|
token.value === LabelTokenValue.Author
|
||||||
|
) {
|
||||||
|
tokens.shift();
|
||||||
|
const [author, rest] = extractText(tokens);
|
||||||
|
header.author = author;
|
||||||
|
tokens = rest;
|
||||||
|
} else if (
|
||||||
|
token.type === "label" &&
|
||||||
|
token.value === LabelTokenValue.Description
|
||||||
|
) {
|
||||||
|
tokens.shift();
|
||||||
|
const [description, rest] = extractText(tokens);
|
||||||
|
header.description = description;
|
||||||
|
tokens = rest;
|
||||||
|
} else {
|
||||||
|
// End of header
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [header, tokens];
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseIntervals = (tokens: Token[]): Interval[] => {
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const parse = (tokens: Token[]): Workout => {
|
||||||
|
const [header, intervalTokens] = parseHeader(tokens);
|
||||||
|
return {
|
||||||
|
name: header.name || "",
|
||||||
|
author: header.author || "",
|
||||||
|
description: header.description || "",
|
||||||
|
intervals: parseIntervals(intervalTokens),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
enum LabelTokenValue {
|
export enum LabelTokenValue {
|
||||||
Name = "Name",
|
Name = "Name",
|
||||||
Author = "Author",
|
Author = "Author",
|
||||||
Description = "Description",
|
Description = "Description",
|
||||||
|
|
@ -7,23 +7,23 @@ enum LabelTokenValue {
|
||||||
Interval = "Interval",
|
Interval = "Interval",
|
||||||
Cooldown = "Cooldown",
|
Cooldown = "Cooldown",
|
||||||
}
|
}
|
||||||
type LabelToken = {
|
export type LabelToken = {
|
||||||
type: "label";
|
type: "label";
|
||||||
value: LabelTokenValue;
|
value: LabelTokenValue;
|
||||||
};
|
};
|
||||||
type TextToken = {
|
export type TextToken = {
|
||||||
type: "text";
|
type: "text";
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
type NumberToken = {
|
export type NumberToken = {
|
||||||
type: "power" | "cadence" | "duration";
|
type: "power" | "cadence" | "duration";
|
||||||
value: number;
|
value: number;
|
||||||
};
|
};
|
||||||
type PowerRangeToken = {
|
export type PowerRangeToken = {
|
||||||
type: "power-range";
|
type: "power-range";
|
||||||
value: [number, number];
|
value: [number, number];
|
||||||
};
|
};
|
||||||
type Token = LabelToken | TextToken | NumberToken | PowerRangeToken;
|
export type Token = LabelToken | TextToken | NumberToken | PowerRangeToken;
|
||||||
|
|
||||||
const toInteger = (str: string): number => {
|
const toInteger = (str: string): number => {
|
||||||
return parseInt(str.replace(/[^0-9]/, ""), 10);
|
return parseInt(str.replace(/[^0-9]/, ""), 10);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue