@npmstuff/argdown-core
Version:
A pluggable parser for the Argdown argumentation syntax
268 lines • 16.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.errorMessageProvider = exports.INVALID_TEXT_POSITION_ERROR = exports.INCOMPLETE_PCS_ERROR = exports.INVALID_PCS_STATEMENT_CONTENT_ERROR = exports.INVALID_PCS_POSITION_ERROR = exports.MISSING_CONCLUSION_ERROR = exports.MISSING_INFERENCE_ERROR = exports.INVALID_INFERENCE_POSITION_ERROR = exports.MISSING_INFERENCE_END_ERROR = exports.MISSING_RELATION_CONTENT_ERROR = exports.INVALID_INDENTATION_ERROR = exports.INVALID_RELATION_ERROR = exports.INVALID_INFERENCE_ERROR = exports.MISSING_TEXT_CONTENT_ERROR = void 0;
const chevrotain = __importStar(require("chevrotain"));
const ArgdownLexer = __importStar(require("./lexer"));
const defaultParserErrorProvider = chevrotain.defaultParserErrorProvider;
const tokenMatcher = chevrotain.tokenMatcher;
exports.MISSING_TEXT_CONTENT_ERROR = `Missing text content. Please add a line of text or refer to an existing statement or argument instead by replacing the content in this line with [Statement Title] or <Argument Title> (without a colon). If you want to define a statement ([Statement Title]:) or argument (<Argument Title>:), the defining text content has to follow the defined element title without any empty lines in between.`;
exports.INVALID_INFERENCE_ERROR = `Invalid inference. Inferences can either be marked by four hyphens (----) or have the following format:
--Inference Rule 1, Inference Rule 2 (my meta data property 1: 1, 2, 3; my meta data property 2: value) --`;
exports.INVALID_RELATION_ERROR = `Invalid relation syntax. This may either be caused by a) an invalid relation parent or b) invalid indentation. a) Invalid relation parent: Only statements and arguments can have relations as child elements. b) Invalid Indentation tree: Please check that if there are preceding relations in this paragraph, there is at least one with equal or less indentation.`;
exports.INVALID_INDENTATION_ERROR = `Invalid indentation.`;
exports.MISSING_RELATION_CONTENT_ERROR = `Missing relation content. Please define or refer to a statement or argument (you can define a statement by simply adding a line of text).`;
exports.MISSING_INFERENCE_END_ERROR = `Invalid inference syntax. Please end your inference with two hyphens (--)`;
exports.INVALID_INFERENCE_POSITION_ERROR = `Invalid inference position. An inference may only occur within a premise-conclusion-structure, in which it is preceded by a premise and followed by a conclusion (both of which have to be numbered statements: '(1) Statement').`;
exports.MISSING_INFERENCE_ERROR = `Missing inference. Use four hyphens (----) between two numbered statements to insert an inference in your premise-conclusion-structure and mark the latter statement as a conclusion.`;
exports.MISSING_CONCLUSION_ERROR = `Missing conclusion. Please add a numbered statement after the inference.`;
exports.INVALID_PCS_POSITION_ERROR = `Invalid position of premise conclusion structure (pcs). Make sure the pcs is preceded by an empty line.`;
exports.INVALID_PCS_STATEMENT_CONTENT_ERROR = `Invalid statement content. An argument reference (<Argument Title>) or definition (<Argument Title>:) can not be used as premise or conclusion within a premise-conclusion-structure. Use statement references ([Statement Title]) or definitions ([Statement Title]:) instead.`;
exports.INCOMPLETE_PCS_ERROR = `Incomplete premise-conclusion-structure (pcs). A pcs has to consist of at least one premise (a numbered statement: '(1) Statement Text'), one inference (marked by four hyphens ----) and one conclusion (a numbered statement after an inference). There may no be any empty lines between these elements.`;
exports.INVALID_TEXT_POSITION_ERROR = `Invalid position of text content. Make sure it is not preceded by a statement reference ([Statement Title]) or argument reference (<Argument Title>).`;
const buildMissingEndError = (tokenType) => {
let tokenDesc = "TOKEN DESCRIPTION MISSING";
let ruleDesc = "RULE DESCRIPTION MISSING";
let escapedChar = "ESCAPED CHAR MISSING";
switch (tokenType.tokenTypeIdx) {
case ArgdownLexer.UnderscoreBoldEnd.tokenTypeIdx:
tokenDesc = "two underscores (__)";
ruleDesc = "bold text range";
escapedChar = "_";
break;
case ArgdownLexer.AsteriskBoldEnd.tokenTypeIdx:
tokenDesc = "two asterisks (**)";
ruleDesc = "bold text range";
escapedChar = "*";
break;
case ArgdownLexer.UnderscoreItalicEnd.tokenTypeIdx:
tokenDesc = "an underscore (_)";
ruleDesc = "italic text range";
escapedChar = "_";
break;
case ArgdownLexer.AsteriskItalicEnd.tokenTypeIdx:
tokenDesc = "an asterisk (*)";
ruleDesc = "italic text range";
escapedChar = "*";
break;
}
return `Incomplete ${ruleDesc}. Append ${tokenDesc} to complete the range. If you want to use this character for other purposes, use ${escapedChar} (you can use \ to escape any character in Argdown).`;
};
const buildInvalidElementPositionError = (token) => {
const tokenDescription = getTokenDescription(token, true);
return `Invalid element position. ${tokenDescription} may only occur at the beginning of a line or after a relation symbol.`;
};
const buildInvalidParagraphStartError = (token) => {
const tokenDescription = getTokenDescription(token);
return `Invalid paragraph start. Argdown paragraphs may not start with ${tokenDescription}. If you do not want to start a new paragraph, remove any empty lines above this one. If you do want to start a new paragraph, try starting with normal text, a statement title, argument title or a list item (using * for unordered or 1. for ordered lists).`;
};
const buildInvalidRelationTextContentError = (token) => {
if (tokenMatcher(token, ArgdownLexer.ArgumentReference)) {
return "Invalid relation text content. An argument reference (<Argument Title>) may not be preceded or followed by other content. If you want to start a new paragraph, insert an empty line before the reference. If you want to mention a statement or argument, without directly using it, use @[Statement Title] or @<Argument Title>.";
}
else if (tokenMatcher(token, ArgdownLexer.ArgumentDefinition)) {
return "Invalid relation text content. An argument definition (<Argument Title>:) may not be preceded by other content. If you want to start a new paragraph, insert an empty line before the definition. If you want to mention a statement or argument, without directly using it, use @[Statement Title] or @<Argument Title>.";
}
else if (tokenMatcher(token, ArgdownLexer.StatementReference)) {
return "Invalid relation text content. A statement reference ([Statement Title]) may not be preceded or followed by other content. If you want to start a new paragraph, insert an empty line before the reference. If you want to mention a statement or argument, without directly using it, use @[Statement Title] or @<Argument Title>.";
}
else if (tokenMatcher(token, ArgdownLexer.StatementDefinition)) {
return "Invalid relation text content. A statement definition ([Statement Title]:) may not be preceded by other content. If you want to start a new paragraph, insert an empty line before the definition. If you want to mention a statement or argument, without directly using it, use @[Statement Title] or @<Argument Title>.";
}
else {
return "Invalid relation text content. Check that the content is not preceded by a statement reference ([Statement Title]) or argument reference (<Argument Title>). If you want to mention a statement or argument, without directly using it, use @[Statement Title] or @<Argument Title>.";
}
};
const capitalizeFirstLetter = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
const getTokenDescription = (token, capitalize = false) => {
let description = "MISSING DESCRIPTION";
if (tokenMatcher(token, ArgdownLexer.OutgoingSupport)) {
description = "an outgoing support relation (+ or <+)";
}
else if (tokenMatcher(token, ArgdownLexer.IncomingSupport)) {
description = "an incoming support relation (+>)";
}
else if (tokenMatcher(token, ArgdownLexer.OutgoingAttack)) {
description = "an outgoing attack relation (- or <-)";
}
else if (tokenMatcher(token, ArgdownLexer.IncomingAttack)) {
description = "an incoming attack relation (->)";
}
else if (tokenMatcher(token, ArgdownLexer.Contradiction)) {
description = "a contradictory relation (><)";
}
else if (tokenMatcher(token, ArgdownLexer.IncomingUndercut)) {
description = "an incoming undercut relation (_>)";
}
else if (tokenMatcher(token, ArgdownLexer.OutgoingUndercut)) {
description = "an incoming undercut relation (<_)";
}
else if (tokenMatcher(token, ArgdownLexer.ArgumentDefinition)) {
description = "an argument definition (<Argument Title>:)";
}
else if (tokenMatcher(token, ArgdownLexer.ArgumentReference)) {
description = "an argument reference (<Argument Title>)";
}
else if (tokenMatcher(token, ArgdownLexer.StatementDefinition)) {
description = "a statement definition ([Statement Title]:)";
}
else if (tokenMatcher(token, ArgdownLexer.StatementReference)) {
description = "a statement reference ([Statement Title])";
}
if (capitalize) {
description = capitalizeFirstLetter(description);
}
return description;
};
const isRelationToken = (token) => {
return (tokenMatcher(token, ArgdownLexer.IncomingSupport) ||
tokenMatcher(token, ArgdownLexer.OutgoingSupport) ||
tokenMatcher(token, ArgdownLexer.IncomingAttack) ||
tokenMatcher(token, ArgdownLexer.OutgoingAttack) ||
tokenMatcher(token, ArgdownLexer.IncomingUndercut) ||
tokenMatcher(token, ArgdownLexer.OutgoingUndercut) ||
tokenMatcher(token, ArgdownLexer.Contradiction));
};
const isRelationRule = (ruleName) => {
return (ruleName.endsWith("Support") ||
ruleName.endsWith("Attack") ||
ruleName.endsWith("Undercut") ||
ruleName == "Contradiction");
};
exports.errorMessageProvider = {
isRelationToken,
isRelationRule,
getTokenDescription,
buildInvalidElementPositionError,
buildInvalidParagraphStartError,
buildInvalidRelationTextContentError,
buildMismatchTokenMessage: (options) => {
if (options.ruleName == "inference") {
if (options.expected == ArgdownLexer.InferenceStart) {
return exports.MISSING_INFERENCE_ERROR;
}
else if (options.expected == ArgdownLexer.InferenceEnd) {
return exports.MISSING_INFERENCE_END_ERROR;
}
}
else if (options.expected == ArgdownLexer.Dedent &&
(options.ruleName == "statementRelations" ||
options.ruleName == "argumentRelations")) {
return buildInvalidRelationTextContentError(options.actual);
}
else if (options.ruleName == "argumentStatement") {
if (options.expected == ArgdownLexer.StatementNumber) {
return exports.MISSING_CONCLUSION_ERROR;
}
}
else if (options.ruleName == "bold" || options.ruleName == "italic") {
return buildMissingEndError(options.expected);
}
return defaultParserErrorProvider.buildMismatchTokenMessage(options);
},
buildNotAllInputParsedMessage: (options) => {
if (tokenMatcher(options.firstRedundant, ArgdownLexer.Indent) ||
isRelationToken(options.firstRedundant)) {
return exports.INVALID_RELATION_ERROR;
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.InferenceStart)) {
return exports.INVALID_INFERENCE_POSITION_ERROR;
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.StatementNumber)) {
return exports.INVALID_PCS_POSITION_ERROR;
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.ArgumentReference)) {
return buildInvalidElementPositionError(options.firstRedundant);
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.ArgumentDefinition)) {
return buildInvalidElementPositionError(options.firstRedundant);
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.StatementReference)) {
return buildInvalidElementPositionError(options.firstRedundant);
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.StatementDefinition)) {
return buildInvalidElementPositionError(options.firstRedundant);
}
else if (tokenMatcher(options.firstRedundant, ArgdownLexer.Freestyle)) {
return exports.INVALID_TEXT_POSITION_ERROR;
}
else {
return defaultParserErrorProvider.buildNotAllInputParsedMessage(options);
}
},
buildNoViableAltMessage: (options) => {
const tokens = options.actual;
if (options.ruleName == "argdown" && tokens.length > 0) {
if (tokens.length >= 2 &&
tokenMatcher(tokens[0], ArgdownLexer.Indent)) {
let secondToken = tokens[1];
return buildInvalidParagraphStartError(secondToken);
}
else if (tokens.length > 0) {
return buildInvalidParagraphStartError(tokens[0]);
}
}
else if (isRelationRule(options.ruleName)) {
return exports.MISSING_RELATION_CONTENT_ERROR;
}
else if (options.ruleName == "statement") {
if (tokens.length > 0 &&
(tokenMatcher(tokens[0], ArgdownLexer.ArgumentReference) ||
tokenMatcher(tokens[0], ArgdownLexer.ArgumentDefinition))) {
return exports.INVALID_PCS_STATEMENT_CONTENT_ERROR;
}
return exports.MISSING_TEXT_CONTENT_ERROR;
}
return defaultParserErrorProvider.buildNoViableAltMessage(options);
},
buildEarlyExitMessage: (options) => {
var firstToken = options.actual.length > 0 ? options.actual[0] : null;
if (options.ruleName == "argdown") {
if (firstToken && isRelationToken(firstToken)) {
return exports.INVALID_RELATION_ERROR;
}
else if (firstToken &&
tokenMatcher(firstToken, ArgdownLexer.InferenceStart)) {
return exports.INVALID_INFERENCE_POSITION_ERROR;
}
}
else if (options.ruleName == "statementContent") {
return exports.MISSING_TEXT_CONTENT_ERROR;
}
else if (options.ruleName == "pcs") {
if (firstToken && isRelationToken(firstToken)) {
return exports.INVALID_INDENTATION_ERROR;
}
return exports.INCOMPLETE_PCS_ERROR;
}
else if (options.ruleName == "data") {
return exports.INVALID_INFERENCE_ERROR;
}
else if (firstToken &&
tokenMatcher(firstToken, ArgdownLexer.InferenceEnd)) {
return exports.INVALID_INFERENCE_ERROR;
}
return defaultParserErrorProvider.buildEarlyExitMessage(options);
}
};
//# sourceMappingURL=ArgdownErrorMessageProvider.js.map