UNPKG

@npmstuff/argdown-core

Version:

A pluggable parser for the Argdown argumentation syntax

1,007 lines 54.3 kB
"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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModelPlugin = exports.InterpretationModes = void 0; const chevrotain_1 = require("chevrotain"); const argdownLexer = __importStar(require("./../lexer")); const ArgdownPluginError_1 = require("../ArgdownPluginError"); const lodash_defaultsdeep_1 = __importDefault(require("lodash.defaultsdeep")); const lodash_last_1 = __importDefault(require("lodash.last")); const lodash_union_1 = __importDefault(require("lodash.union")); const lodash_merge_1 = __importDefault(require("lodash.merge")); const model_1 = require("../model/model"); const RuleNames_1 = require("../RuleNames"); const TokenNames_1 = require("../TokenNames"); const utils_1 = require("../utils"); const utils_2 = require("../utils"); const shortcodes_1 = require("./shortcodes"); var InterpretationModes; (function (InterpretationModes) { InterpretationModes["LOOSE"] = "loose"; InterpretationModes["STRICT"] = "strict"; })(InterpretationModes = exports.InterpretationModes || (exports.InterpretationModes = {})); const defaultSettings = { mode: InterpretationModes.LOOSE, removeTagsFromText: false, transformArgumentRelations: true, shortcodes: utils_1.ensure.object(shortcodes_1.shortcodes) }; class ModelPlugin { constructor(config) { this.name = "ModelPlugin"; this.defaults = {}; this.getSettings = (request) => { if (!(0, utils_1.isObject)(request.model)) { request.model = {}; } return request.model; }; this.prepare = request => { (0, utils_1.mergeDefaults)(this.getSettings(request), this.defaults); }; this.transformArgumentRelations = (response) => { const newRelations = []; for (let relation of response.relations) { let addRelation = true; if (!relation.from) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-relation-source", "Relation without source."); } if (!relation.to) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-relation-target", "Relation without target."); } const fromIsReconstructedArgument = relation.from.type === model_1.ArgdownTypes.ARGUMENT && (0, model_1.isReconstructed)(relation.from); const toIsReconstructedArgument = relation.to.type === model_1.ArgdownTypes.ARGUMENT && (0, model_1.isReconstructed)(relation.to); if (fromIsReconstructedArgument) { let argument = relation.from; this.removeRelationFromSource(relation); let conclusionStatement = argument.pcs[argument.pcs.length - 1]; let equivalenceClass = response.statements[conclusionStatement.title]; relation.from = equivalenceClass; let relationExists = false; for (let existingRelation of equivalenceClass.relations) { if (relation.to == existingRelation.to && relation.relationType === existingRelation.relationType) { relationExists = true; existingRelation.occurrences.push(...relation.occurrences); break; } } if (!relationExists) { equivalenceClass.relations.push(relation); } else { this.removeRelationFromTarget(relation); addRelation = false; } } if (toIsReconstructedArgument && relation.relationType === model_1.RelationType.UNDERCUT) { let argument = relation.to; let inference = (0, lodash_last_1.default)(argument.pcs).inference; relation.to = inference; this.removeRelationFromTarget(relation); let relationExists = false; for (let existingRelation of inference.relations) { if (relation.from == existingRelation.from && relation.relationType === existingRelation.relationType) { relationExists = true; existingRelation.occurrences.push(...relation.occurrences); break; } } if (!relationExists) { inference.relations.push(relation); } else { this.removeRelationFromSource(relation); addRelation = false; } } if (addRelation) { newRelations.push(relation); } } response.relations = newRelations; }; this.transformStatementRelations = (response) => { const newRelations = []; for (let relation of response.relations) { let addRelation = true; const isS2SRelation = relation.from.type === model_1.ArgdownTypes.EQUIVALENCE_CLASS && relation.to.type === model_1.ArgdownTypes.EQUIVALENCE_CLASS; if (isS2SRelation) { if (relation.relationType === model_1.RelationType.SUPPORT) { relation.relationType = model_1.RelationType.ENTAILS; } else if (relation.relationType === model_1.RelationType.ATTACK) { const relationExists = relation.from.relations.find(r => { return (r.relationType === model_1.RelationType.CONTRARY && ((r.from === relation.from && r.to === relation.to) || (r.from === relation.to && r.to === relation.from))); }); if (relationExists !== undefined) { this.removeRelationFromSource(relation); this.removeRelationFromTarget(relation); addRelation = false; } else { relation.relationType = model_1.RelationType.CONTRARY; } } } if (addRelation) { newRelations.push(relation); } } response.relations = newRelations; }; this.removeRelationFromSource = (relation) => { let indexSource = relation.from.relations.indexOf(relation); relation.from.relations.splice(indexSource, 1); }; this.removeRelationFromTarget = (relation) => { let indexTarget = relation.to.relations.indexOf(relation); relation.to.relations.splice(indexTarget, 1); }; this.removeRedundantEC2ARelations = (response) => { const newRelations = []; for (let relation of response.relations) { if (relation.from.type !== model_1.ArgdownTypes.EQUIVALENCE_CLASS || relation.relationType !== model_1.RelationType.ATTACK || relation.to.type !== model_1.ArgdownTypes.ARGUMENT) { newRelations.push(relation); continue; } const argument = relation.to; if (!argument.pcs) { newRelations.push(relation); continue; } const ec = relation.from; const ec2ecRelation = ec.relations.find(otherRelation => (0, utils_2.other)(otherRelation, ec).type === model_1.ArgdownTypes.EQUIVALENCE_CLASS && ((otherRelation.relationType === model_1.RelationType.ATTACK && otherRelation.from === ec) || otherRelation.relationType === model_1.RelationType.CONTRADICTORY || otherRelation.relationType === model_1.RelationType.CONTRARY) && !!argument.pcs.find(s => s.title === (0, utils_2.other)(otherRelation, ec).title && s.role === model_1.StatementRole.PREMISE)); if (ec2ecRelation) { this.removeRelationFromSource(relation); this.removeRelationFromTarget(relation); ec2ecRelation.occurrences.push(...relation.occurrences); continue; } else { newRelations.push(relation); continue; } } response.relations = newRelations; }; this.assignSectionOfFirstMemberIfWithoutSection = (node) => { if (!node.section && node.members && node.members.length > 0) { node.section = node.members[0].section; } }; this.run = (request, response) => { (0, ArgdownPluginError_1.checkResponseFields)(this, response, [ "ast", "statements", "arguments", "relations" ]); for (let ec of Object.values(response.statements)) { this.assignSectionOfFirstMemberIfWithoutSection(ec); } for (let argument of Object.values(response.arguments)) { this.assignSectionOfFirstMemberIfWithoutSection(argument); } const settings = this.getSettings(request); if (settings.transformArgumentRelations) { this.transformArgumentRelations(response); } if (settings.mode === InterpretationModes.STRICT) { this.transformStatementRelations(response); } this.removeRedundantEC2ARelations(response); return response; }; this.defaults = (0, lodash_defaultsdeep_1.default)({}, config, defaultSettings); this.name = "ModelPlugin"; let $ = this; const statementReferencePattern = /\[(.+)\]/; const statementDefinitionPattern = /\[(.+)\]\:/; const statementMentionPattern = /\@\[(.+)\](\s?)/; const argumentReferencePattern = /\<(.+)\>/; const argumentDefinitionPattern = /\<(.+)\>\:/; const argumentMentionPattern = /\@\<(.+)\>(\s?)/; const linkPattern = /\[(.+)\]\((.+)\)/; const tagPattern = /#(?:\(([^\)]+)\)|([a-zA-z0-9-\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+))/; let uniqueTitleCounter = 0; function getUniqueTitle() { uniqueTitleCounter++; return "Untitled " + uniqueTitleCounter; } let currentStatement = null; let currentRelationParent = null; let currentArgument = null; let currentPCS = null; let currentInference = null; let rangesStack = []; let relationParentsStack = []; let currentRelation = null; let currentHeading = null; let currentSection = null; let sectionCounter = 0; let tagCounter = 0; const getRelationMember = (response, relationParent) => { let target = relationParent; if (relationParent.type === model_1.ArgdownTypes.STATEMENT) { if (!relationParent.title) relationParent.title = getUniqueTitle(); if (relationParent.role === model_1.StatementRole.ARGUMENT_DESCRIPTION) { return getArgument(response.arguments, relationParent.title); } else { return getEquivalenceClass(response.statements, relationParent.title); } } else { return target; } }; const getArgument = (argumentsDict, title) => { if (title) { currentArgument = argumentsDict[title]; } if (!title || !currentArgument) { currentArgument = { type: model_1.ArgdownTypes.ARGUMENT, relations: [], members: [], pcs: [] }; if (!title) { currentArgument.title = getUniqueTitle(); } else { currentArgument.title = title; } argumentsDict[currentArgument.title] = currentArgument; } currentRelationParent = currentArgument; return currentArgument; }; const addTags = (newTags, object) => { if (!object.tags) { object.tags = []; } object.tags = (0, lodash_union_1.default)(object.tags, newTags); }; const onRelationExit = (_request, response, node) => { let relation = node.relation; if (!node.children || node.children.length < 2) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-ast-node-children", "Relation without children."); } let contentNode = node.children[1]; let content = contentNode.argument || contentNode.statement; if (!content) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-ast-node-relation-member", "Relation member not found."); } let target = getRelationMember(response, content); if (relation) { if (relation.from) { relation.to = target; } else { relation.from = target; } let relationExists = false; const relationSource = relation.from; for (let existingRelation of relationSource.relations) { if (relation.to === existingRelation.to && relation.relationType === existingRelation.relationType) { relationExists = true; existingRelation.occurrences.push(...relation.occurrences); break; } else if (relation.relationType === model_1.RelationType.CONTRADICTORY && relation.relationType === existingRelation.relationType && relation.from === existingRelation.to && relation.to === existingRelation.from) { relationExists = true; existingRelation.occurrences.push(...relation.occurrences); break; } } if (!relationExists) { if (!relation.from || !relation.to) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-relation-member", "Missing relation source or target."); } response.relations.push(relation); relation.from.relations.push(relation); relation.to.relations.push(relation); } } }; this.tokenListeners = { [TokenNames_1.TokenNames.STATEMENT_DEFINITION]: (_request, _response, token, parentNode) => { let match = statementDefinitionPattern.exec(token.image); if (match != null && currentStatement) { currentStatement.title = match[1]; token.title = currentStatement.title; parentNode.statement = currentStatement; } }, [TokenNames_1.TokenNames.STATEMENT_REFERENCE]: (_request, _response, token, parentNode) => { let match = statementReferencePattern.exec(token.image); if (match != null && currentStatement) { currentStatement.title = match[1]; currentStatement.isReference = true; token.title = currentStatement.title; parentNode.statement = currentStatement; } }, [TokenNames_1.TokenNames.STATEMENT_MENTION]: (_request, _response, token) => { let match = statementMentionPattern.exec(token.image); if (match) { token.title = match[1]; if (token.image[token.image.length - 1] == " ") { token.trailingWhitespace = " "; } else { token.trailingWhitespace = ""; } const target = currentHeading || currentStatement; if (target) { const previousText = target.text || ""; const newText = previousText + token.image; target.text = newText; if (!target.ranges) { target.ranges = []; } let range = { type: model_1.RangeType.STATEMENT_MENTION, title: token.title, start: previousText.length, stop: newText.length - 1 }; target.ranges.push(range); } } }, [TokenNames_1.TokenNames.ARGUMENT_REFERENCE]: (_request, _response, token) => { let match = argumentReferencePattern.exec(token.image); if (match != null && currentStatement) { let title = match[1]; currentStatement.title = title; currentStatement.isReference = true; token.title = title; } }, [TokenNames_1.TokenNames.ARGUMENT_DEFINITION]: (_request, _response, token) => { let match = argumentDefinitionPattern.exec(token.image); if (match != null && currentStatement) { let title = match[1]; currentStatement.title = title; token.title = title; } }, [TokenNames_1.TokenNames.ARGUMENT_MENTION]: (_request, _response, token) => { const target = currentHeading ? currentHeading : currentStatement; let match = argumentMentionPattern.exec(token.image); if (match) { token.title = match[1]; if (token.image[token.image.length - 1] == " ") { token.trailingWhitespace = " "; } else { token.trailingWhitespace = ""; } if (target) { const previousText = target.text || ""; const newText = previousText + token.image; target.text = newText; if (!target.ranges) { target.ranges = []; } let range = { type: model_1.RangeType.ARGUMENT_MENTION, title: token.title, start: previousText.length, stop: newText.length - 1 }; target.ranges.push(range); } } }, [TokenNames_1.TokenNames.LINK]: (_request, _response, token) => { const target = currentHeading ? currentHeading : currentStatement; if (!target) { return; } let match = linkPattern.exec(token.image); if (!match || match.length < 3) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "invalid-link", "Could not match link."); } token.url = match[2]; token.text = match[1]; const oldText = target.text || ""; const newText = oldText + token.text; target.text = newText; let linkRange = { type: "link", start: oldText.length, stop: newText.length - 1 }; linkRange.url = token.url; if (token.image[token.image.length - 1] == " ") { target.text += " "; token.trailingWhitespace = " "; } else { token.trailingWhitespace = ""; } if (!target.ranges) { target.ranges = []; } target.ranges.push(linkRange); }, [TokenNames_1.TokenNames.TAG]: (request, response, token) => { const target = currentHeading || currentStatement; if (!target) { return; } let match = tagPattern.exec(token.image); if (!match || match.length < 2) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "invalid-tag", "Could not parse tag."); } let tag = match[1] || match[2]; const settings = $.getSettings(request); token.tag = tag; if (!settings.removeTagsFromText) { const oldText = target.text || ""; const newText = oldText + token.image; let tagRange = { type: model_1.RangeType.TAG, start: oldText.length, stop: newText.length - 1 }; token.text = token.image; target.text = newText; tagRange.tag = token.tag; if (!target.ranges) { target.ranges = []; } target.ranges.push(tagRange); } target.tags = target.tags || []; let tags = target.tags; if (target.tags.indexOf(tag) === -1) { tags.push(tag); } let tagData = response.tags[tag]; if (!tagData) { tagData = { tag: tag, cssClass: (0, utils_1.stringToClassName)("tag-" + tag), occurrenceIndex: tagCounter }; response.tags[tag] = tagData; tagCounter++; } }, [TokenNames_1.TokenNames.NEWLINE]: (_request, _response, _token, parentNode, childIndex) => { const target = currentHeading ? currentHeading : currentStatement; if (!target) { return; } const oldText = target.text || ""; if (childIndex !== parentNode.children.length - 1 && oldText.charAt(oldText.length - 1) !== " ") { target.text = oldText + " "; } } }; this.ruleListeners = { [RuleNames_1.RuleNames.ARGDOWN + "Entry"]: (_request, response) => { response.statements = {}; response.arguments = {}; response.sections = []; response.relations = []; response.tags = {}; uniqueTitleCounter = 0; currentHeading = null; currentSection = null; currentRelationParent = null; currentPCS = null; currentInference = null; currentArgument = null; rangesStack = []; relationParentsStack = []; currentRelation = null; sectionCounter = 0; tagCounter = 0; }, [RuleNames_1.RuleNames.ARGDOWN + "Exit"]: (_req, _resp, token) => { const lastChild = token.children && token.children.length > 0 ? token.children[token.children.length - 1] : null; while (currentSection && lastChild && lastChild.endLine) { currentSection.endLine = lastChild.endLine; currentSection.endOffset = lastChild.endOffset; currentSection.endColumn = lastChild.endColumn; currentSection = currentSection.parent || null; } }, [RuleNames_1.RuleNames.HEADING + "Entry"]: (_request, _response, node) => { currentHeading = node; currentHeading.text = ""; currentHeading.ranges = []; }, [RuleNames_1.RuleNames.HEADING + "Exit"]: (request, response, node) => { if (!currentHeading) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-heading", "Missing heading."); } if (node.children) { let headingStart = node.children[0]; currentHeading.level = headingStart.image.length - 1; sectionCounter++; let sectionId = "s" + sectionCounter; const title = currentHeading.text ? currentHeading.text.trim() : ""; let newSection = { type: model_1.ArgdownTypes.SECTION, id: sectionId, level: currentHeading.level, title: title, children: [] }; if (!response.maxSectionLevel || currentHeading.level > response.maxSectionLevel) { response.maxSectionLevel = currentHeading.level; } newSection.tags = currentHeading.tags; newSection.ranges = currentHeading.ranges; newSection.startLine = node.startLine; newSection.startColumn = node.startColumn; newSection.heading = currentHeading; newSection.data = currentHeading.data; const groupSettings = request.group; if (newSection.data) { if (newSection.data.isGroup !== undefined && (!groupSettings || !groupSettings.ignoreIsGroup)) { newSection.isGroup = newSection.data.isGroup; } if (newSection.data.isClosed !== undefined && (!groupSettings || !groupSettings.ignoreIsClosed)) { newSection.isClosed = newSection.data.isClosed; } } if (groupSettings && (0, utils_1.isObject)(groupSettings.sections)) { const groupConfig = groupSettings.sections[newSection.title]; if (groupConfig) { newSection.isGroup = groupConfig.isGroup; newSection.isClosed = groupConfig.isClosed; } else { newSection.isGroup = newSection.isGroup === undefined ? false : newSection.isGroup; } } if (!currentSection) { response.sections.push(newSection); } else { let previous = currentSection; while (previous && previous.level >= newSection.level) { previous.endOffset = newSection.startOffset - 1; previous.endLine = newSection.startLine - 1; previous.endColumn = 0; previous = previous.parent || null; } if (previous && previous.level < newSection.level) { previous.children.push(newSection); newSection.parent = previous; } else { response.sections.push(newSection); } } currentSection = newSection; currentHeading.section = newSection; currentHeading = null; } }, [RuleNames_1.RuleNames.STATEMENT + "Entry"]: (_request, _response, node, parentNode) => { currentStatement = { type: model_1.ArgdownTypes.STATEMENT }; if (parentNode.name === "argdown") { currentStatement.role = model_1.StatementRole.TOP_LEVEL_STATEMENT; currentStatement.isTopLevel = true; } else if (currentRelation) { currentStatement.role = model_1.StatementRole.RELATION_STATEMENT; } currentRelationParent = currentStatement; node.statement = currentStatement; }, [RuleNames_1.RuleNames.STATEMENT + "Exit"]: (_request, response, node) => { let statement = node.statement; if (!statement) { return; } statement.startLine = node.startLine; statement.startColumn = node.startColumn; statement.endLine = node.endLine; statement.endColumn = node.endColumn; statement.data = node.data; if (!statement.title || statement.title == "") { statement.title = getUniqueTitle(); } let equivalenceClass = getEquivalenceClass(response.statements, statement.title); node.equivalenceClass = equivalenceClass; if (statement.tags) { addTags(statement.tags, equivalenceClass); } if (statement.data) { equivalenceClass.data = (0, lodash_merge_1.default)(equivalenceClass.data, statement.data); } if (currentSection) { statement.section = currentSection; } equivalenceClass.members.push(statement); const isInGroup = statement.data && statement.data.isInGroup !== undefined ? statement.data.isInGroup : undefined; const ecTakesSection = isInGroup === true || (!statement.isReference && isInGroup === undefined && equivalenceClass.section === undefined); if (ecTakesSection) { equivalenceClass.section = statement.section; } if (statement.role === model_1.StatementRole.TOP_LEVEL_STATEMENT) { equivalenceClass.isUsedAsTopLevelStatement = true; } else if (statement.role === model_1.StatementRole.RELATION_STATEMENT) { equivalenceClass.isUsedAsRelationStatement = true; } currentStatement = null; }, [RuleNames_1.RuleNames.ARGUMENT + "Entry"]: (_request, _response, node, parentNode) => { const desc = { type: model_1.ArgdownTypes.STATEMENT, role: model_1.StatementRole.ARGUMENT_DESCRIPTION, text: "" }; currentStatement = desc; desc.startLine = node.startLine; desc.endLine = node.endLine; desc.startColumn = node.startColumn; desc.endColumn = node.endColumn; desc.isTopLevel = !parentNode || parentNode.name === RuleNames_1.RuleNames.ARGDOWN; if (currentSection) { currentStatement.section = currentSection; } currentRelationParent = currentStatement; node.statement = desc; }, [RuleNames_1.RuleNames.ARGUMENT + "Exit"]: (_request, response, node) => { let desc = node.statement; if (!desc) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-argument-description", "Missing argument description."); } desc.startLine = node.startLine; desc.startColumn = node.startColumn; desc.endLine = node.endLine; desc.endColumn = node.endColumn; desc.data = node.data; if (!desc.title || desc.title == "") { desc.title = getUniqueTitle(); } const argument = getArgument(response.arguments, desc.title); node.argument = argument; if (desc.tags) { addTags(desc.tags, argument); } if (desc.data) { argument.data = (0, lodash_merge_1.default)(argument.data, desc.data); } if (currentSection) { desc.section = currentSection; } argument.members.push(desc); const isInGroup = desc.data && desc.data.isInGroup !== undefined ? desc.data.isInGroup : undefined; const argumentTakesSection = isInGroup === true || (!desc.isReference && isInGroup === undefined && argument.section === undefined); if (argumentTakesSection) { argument.section = desc.section; } response.arguments[argument.title] = argument; currentStatement = null; currentArgument = null; }, [RuleNames_1.RuleNames.PCS + "Entry"]: (_request, response, node, parentNode, childIndex) => { let argument = null; let argumentDescription; if (childIndex !== null && childIndex > 0 && parentNode && parentNode.children) { let precedingSibling = parentNode.children[childIndex - 1]; if ((0, model_1.isRuleNode)(precedingSibling) && precedingSibling.name === RuleNames_1.RuleNames.ARGUMENT) { argumentDescription = precedingSibling.statement; argument = precedingSibling.argument; } else if ((0, model_1.isTokenNode)(precedingSibling) && (0, chevrotain_1.tokenMatcher)(precedingSibling, argdownLexer.Emptyline)) { precedingSibling = parentNode.children[childIndex - 2]; if ((0, model_1.isRuleNode)(precedingSibling) && precedingSibling.name === RuleNames_1.RuleNames.ARGUMENT) { argumentDescription = precedingSibling.statement; argument = precedingSibling.argument; } } } if (!argument) { argument = getArgument(response.arguments); } if (currentSection) { argument.section = currentSection; } if (argument.pcs.length > 0) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "multiple-pcs-assignments", `Multiple premise-conclusion-structures assigned to argument <${argument.title}>. You can only assign one pcs per argument.`); } argument.pcs = []; if (argumentDescription) { argumentDescription.pcs = argument.pcs; } node.argument = argument; currentPCS = argument; }, [RuleNames_1.RuleNames.PCS + "Exit"]: (_request, response, node) => { const argument = node.argument; if (!argument) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-argument", "Missing argument."); } if (argument.pcs.length == 0) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-argument-statements", "Missing argument statements."); } const lastStatement = argument.pcs[argument.pcs.length - 1]; if (lastStatement.role === model_1.StatementRole.INTERMEDIARY_CONCLUSION) { lastStatement.role = model_1.StatementRole.MAIN_CONCLUSION; const ec = response.statements[lastStatement.title]; ec.isUsedAsMainConclusion = true; if (!ec.members.find(s => s.role === model_1.StatementRole.INTERMEDIARY_CONCLUSION)) { ec.isUsedAsIntermediaryConclusion = false; } } else { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-main-conclusion", "Missing main conclusions."); } argument.startLine = node.startLine; argument.startColumn = node.startColumn; argument.endLine = node.endLine; argument.endColumn = node.endColumn; currentStatement = null; currentArgument = null; currentPCS = null; }, [RuleNames_1.RuleNames.PCS_STATEMENT + "Exit"]: (_request, response, node, parentNode, childIndex) => { if (!currentPCS) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-argument-reconstruction", "Missing argument reconstruction."); } if (node.children && node.children.length > 1) { let statementNode = node.children[1]; let statement = statementNode.statement; if (!statement) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-statement", "Missing statement."); } let ec = getEquivalenceClass(response.statements, statement.title); statement.role = model_1.StatementRole.PREMISE; statement.argumentTitle = currentPCS.title; if (childIndex !== null && childIndex > 0 && parentNode && parentNode.children) { let precedingSibling = parentNode.children[childIndex - 1]; if (precedingSibling.name === RuleNames_1.RuleNames.INFERENCE) { statement.role = model_1.StatementRole.INTERMEDIARY_CONCLUSION; const conclusion = statement; ec.isUsedAsIntermediaryConclusion = true; conclusion.inference = precedingSibling.inference; conclusion.inference.conclusionIndex = currentPCS.pcs.length; conclusion.inference.argumentTitle = currentPCS.title; } } if (statement.role == model_1.StatementRole.PREMISE) { ec.isUsedAsPremise = true; } currentPCS.pcs.push(statement); node.statement = statement; node.statementNr = currentPCS.pcs.length; } }, [RuleNames_1.RuleNames.INFERENCE + "Entry"]: (_request, _response, node) => { currentInference = { type: model_1.ArgdownTypes.INFERENCE, relations: [] }; currentInference.relations = []; currentInference.inferenceRules = []; currentInference.startLine = node.startLine; currentInference.startColumn = node.startColumn; currentInference.endLine = node.endLine; currentInference.endColumn = node.endColumn; node.inference = currentInference; currentRelationParent = currentInference; relationParentsStack.push(currentInference); }, [RuleNames_1.RuleNames.INFERENCE + "Exit"]: (_request, _response, node) => { if (!currentInference) { return; } currentInference.data = node.data; }, [RuleNames_1.RuleNames.INFERENCE_RULES + "Exit"]: (_request, _response, node) => { if (!currentInference) { return; } if (node.children) { for (let child of node.children) { if ((0, model_1.isRuleNode)(child) && child.name == RuleNames_1.RuleNames.FREESTYLE_TEXT) { if (!currentInference.inferenceRules) { currentInference.inferenceRules = []; } const text = child.text ? child.text.trim() : ""; currentInference.inferenceRules.push(text); } } } }, [RuleNames_1.RuleNames.INCOMING_SUPPORT + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.SUPPORT, occurrences: [node] }; currentRelation.from = target; node.relation = currentRelation; }, [RuleNames_1.RuleNames.INCOMING_SUPPORT + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.INCOMING_ATTACK + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.ATTACK, occurrences: [node] }; currentRelation.from = target; node.relation = currentRelation; }, [RuleNames_1.RuleNames.INCOMING_ATTACK + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.OUTGOING_SUPPORT + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.SUPPORT, occurrences: [node] }; currentRelation.to = target; node.relation = currentRelation; }, [RuleNames_1.RuleNames.OUTGOING_SUPPORT + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.OUTGOING_ATTACK + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.ATTACK, occurrences: [node] }; currentRelation.to = target; node.relation = currentRelation; }, [RuleNames_1.RuleNames.OUTGOING_ATTACK + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.CONTRADICTION + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.CONTRADICTORY, occurrences: [node] }; currentRelation.from = target; node.relation = currentRelation; }, [RuleNames_1.RuleNames.CONTRADICTION + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.OUTGOING_UNDERCUT + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.UNDERCUT, occurrences: [node] }; if (target && target.type === model_1.ArgdownTypes.EQUIVALENCE_CLASS) { if (currentInference) { currentRelation.to = currentInference; } else { currentRelation.to = target; } } else { currentRelation.to = target; } node.relation = currentRelation; }, [RuleNames_1.RuleNames.OUTGOING_UNDERCUT + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.INCOMING_UNDERCUT + "Entry"]: (_request, _response, node) => { const target = (0, lodash_last_1.default)(relationParentsStack); currentRelation = { type: model_1.ArgdownTypes.RELATION, relationType: model_1.RelationType.UNDERCUT, occurrences: [node] }; currentRelation.from = target; node.relation = currentRelation; }, [RuleNames_1.RuleNames.INCOMING_UNDERCUT + "Exit"]: onRelationExit, [RuleNames_1.RuleNames.RELATIONS + "Entry"]: (_request, response) => { if (!currentRelationParent) { throw new ArgdownPluginError_1.ArgdownPluginError(this.name, "missing-ast-node-relation-parent", "Parent of relation missing."); } relationParentsStack.push(getRelationMember(response, currentRelationParent)); }, [RuleNames_1.RuleNames.RELATIONS + "Exit"]: () => { currentRelation = null; relationParentsStack.pop(); }, [RuleNames_1.RuleNames.FREESTYLE_TEXT + "Entry"]: (request, _response, node) => { const target = currentHeading ? currentHeading : currentStatement; node.text = ""; const settings = $.getSettings(request); if (node.children) { for (let child of node.children) { if ((0, model_1.isTokenNode)(child) && child.image !== undefined) { if ((0, chevrotain_1.tokenMatcher)(child, argdownLexer.EscapedChar)) { node.text += child.image.substring(1, child.image.length); } else if ((0, chevrotain_1.tokenMatcher)(child, argdownLexer.SpecialChar)) { const specialCharTrimmed = child.image.trim(); const specialCharInfo = settings.shortcodes[specialCharTrimmed]; if (specialCharInfo) { const startPos = node.text ? node.text.length : 0; node.text += specialCharInfo.unicode; if (child.image[child.image.length - 1] == " ") { node.text += " "; } let specialCharRange