mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 21:10:38 +03:00
Implement template argument substitutions
This commit is contained in:
parent
0e5b013e4e
commit
93136b4843
32
rsconcept/frontend/src/models/rslangAPI.test.ts
Normal file
32
rsconcept/frontend/src/models/rslangAPI.test.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { extractGlobals, splitTemplateDefinition } from './rslangAPI';
|
||||||
|
|
||||||
|
const globalsData = [
|
||||||
|
['', ''],
|
||||||
|
['X1', 'X1'],
|
||||||
|
['X11 X1 X11', 'X11 X1'],
|
||||||
|
['∀α∈S1 ∀β∈F1[α] Pr1,1(β)∩β=∅', 'S1 F1'],
|
||||||
|
]
|
||||||
|
describe('Testing extract globals', () => {
|
||||||
|
it.each(globalsData)('Extract globals %p',
|
||||||
|
(input: string, expected: string) => {
|
||||||
|
const result = extractGlobals(input);
|
||||||
|
expect([...result].join(' ')).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const splitData = [
|
||||||
|
['', '||'],
|
||||||
|
['[α∈ℬ(R1)] α⊆red(σ)', 'α∈ℬ(R1)||α⊆red(σ)'],
|
||||||
|
['[α∈ℬ(R1)] α⊆red(σ) ', 'α∈ℬ(R1)||α⊆red(σ)'],
|
||||||
|
[' [α∈ℬ(R1)] α⊆red(σ)', 'α∈ℬ(R1)||α⊆red(σ)'],
|
||||||
|
['[α∈ℬ(R1)]α⊆red(σ)', 'α∈ℬ(R1)||α⊆red(σ)'],
|
||||||
|
['[α∈ℬ(R1), σ∈ℬℬ(R1)] α⊆red(σ)', 'α∈ℬ(R1), σ∈ℬℬ(R1)||α⊆red(σ)'],
|
||||||
|
]
|
||||||
|
describe('Testing split template', () => {
|
||||||
|
it.each(splitData)('Split %p',
|
||||||
|
(input: string, expected: string) => {
|
||||||
|
const result = splitTemplateDefinition(input);
|
||||||
|
expect(`${result.head}||${result.body}`).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,8 +1,11 @@
|
||||||
// Module: RSLang model API
|
// Module: RSLang model API
|
||||||
|
|
||||||
|
import { applyPattern } from '../utils/utils';
|
||||||
import { CstType } from './rsform';
|
import { CstType } from './rsform';
|
||||||
import { IArgumentValue } from './rslang'
|
import { IArgumentValue } from './rslang'
|
||||||
|
|
||||||
|
const LOCALS_REGEXP = /[_a-zα-ω][a-zα-ω]*\d*/g;
|
||||||
|
|
||||||
export function extractGlobals(expression: string): Set<string> {
|
export function extractGlobals(expression: string): Set<string> {
|
||||||
return new Set(expression.match(/[XCSADFPT]\d+/g) ?? []);
|
return new Set(expression.match(/[XCSADFPT]\d+/g) ?? []);
|
||||||
}
|
}
|
||||||
|
@ -17,20 +20,6 @@ export function inferTemplatedType(templateType: CstType, args: IArgumentValue[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function substituteTemplateArgs(expression: string, args: IArgumentValue[]): string {
|
|
||||||
if (args.every(arg => !arg.value)) {
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapping: { [key: string]: string } = {};
|
|
||||||
args.filter(arg => !!arg.value).forEach(arg => { mapping[arg.alias] = arg.value!; })
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: figure out actual substitution
|
|
||||||
return expression
|
|
||||||
}
|
|
||||||
|
|
||||||
export function splitTemplateDefinition(target: string) {
|
export function splitTemplateDefinition(target: string) {
|
||||||
let start = 0;
|
let start = 0;
|
||||||
for (; start < target.length && target[start] !== '['; ++start) ;
|
for (; start < target.length && target[start] !== '['; ++start) ;
|
||||||
|
@ -42,7 +31,10 @@ export function splitTemplateDefinition(target: string) {
|
||||||
if (counter !== 0) {
|
if (counter !== 0) {
|
||||||
--counter;
|
--counter;
|
||||||
} else {
|
} else {
|
||||||
|
return {
|
||||||
|
head: target.substring(start + 1, end).trim(),
|
||||||
|
body: target.substring(end + 1).trim()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,39 +45,31 @@ export function splitTemplateDefinition(target: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function applyPattern(text: string, mapping: { [key: string]: string }, pattern: RegExp): string {
|
export function substituteTemplateArgs(expression: string, args: IArgumentValue[]): string {
|
||||||
// /** Apply mapping to matching in regular expression patter subgroup 1. */
|
if (args.every(arg => !arg.value)) {
|
||||||
// if (text === '' || pattern === null) {
|
return expression;
|
||||||
// return text;
|
}
|
||||||
// }
|
|
||||||
// let posInput: number = 0;
|
|
||||||
// let output: string = '';
|
|
||||||
// const patternMatches = text.matchAll(pattern);
|
|
||||||
// for (const segment of patternMatches) {
|
|
||||||
// const entity = segment[1];
|
|
||||||
// if (entity in mapping) {
|
|
||||||
// output += text.substring(posInput, segment.index);
|
|
||||||
// output += mapping[entity];
|
|
||||||
// output += text.substring(segment.index, segment.index + segment[0].length);
|
|
||||||
// posInput = segment.index + segment[0].length;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// output += text.substring(posInput);
|
|
||||||
// return output;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// def apply_pattern(text: str, mapping: dict[str, str], pattern: re.Pattern[str]) -> str:
|
const mapping: { [key: string]: string } = {};
|
||||||
// ''' Apply mapping to matching in regular expression patter subgroup 1. '''
|
args.filter(arg => !!arg.value).forEach(arg => { mapping[arg.alias] = arg.value!; })
|
||||||
// if text == '' or pattern == '':
|
|
||||||
// return text
|
let { head, body } = splitTemplateDefinition(expression);
|
||||||
// pos_input: int = 0
|
body = applyPattern(body, mapping, LOCALS_REGEXP);
|
||||||
// output: str = ''
|
const argTexts = head.split(',').map(text => text.trim());
|
||||||
// for segment in re.finditer(pattern, text):
|
head = argTexts
|
||||||
// entity = segment.group(1)
|
.filter(
|
||||||
// if entity in mapping:
|
arg => [...arg.matchAll(LOCALS_REGEXP)]
|
||||||
// output += text[pos_input : segment.start(1)]
|
.every(local => local.every(match => !(match in mapping)))
|
||||||
// output += mapping[entity]
|
).join(', ');
|
||||||
// output += text[segment.end(1) : segment.end(0)]
|
|
||||||
// pos_input = segment.end(0)
|
console.log(body);
|
||||||
// output += text[pos_input : len(text)]
|
console.log(head);
|
||||||
// return output
|
console.log(args);
|
||||||
|
console.log(mapping);
|
||||||
|
|
||||||
|
if (!head) {
|
||||||
|
return body;
|
||||||
|
} else {
|
||||||
|
return `[${head}] ${body}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,3 +31,26 @@ export class TextMatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text substitution guided by mapping and regular explression.
|
||||||
|
*/
|
||||||
|
export function applyPattern(text: string, mapping: { [key: string]: string }, pattern: RegExp): string {
|
||||||
|
if (text === '' || pattern === null) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
let posInput = 0;
|
||||||
|
let output = '';
|
||||||
|
const patternMatches = text.matchAll(pattern);
|
||||||
|
for (const segment of patternMatches) {
|
||||||
|
const entity = segment[0];
|
||||||
|
const start = segment.index!;
|
||||||
|
if (entity in mapping) {
|
||||||
|
output += text.substring(posInput, start);
|
||||||
|
output += mapping[entity];
|
||||||
|
posInput = start + segment[0].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += text.substring(posInput);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user