k2hr3-api
Version:
K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules
1,236 lines • 317 kB
JavaScript
"use strict";
/*
* K2HR3 REST API
*
* Copyright 2017 Yahoo Japan Corporation.
*
* K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
* common management information for the cloud.
* K2HR3 can dynamically manage information as "who", "what", "operate".
* These are stored as roles, resources, policies in K2hdkc, and the
* client system can dynamically read and modify these information.
*
* For the full copyright and license information, please view
* the license file that was distributed with this source code.
*
* AUTHOR: Takeshi Nakatani
* CREATE: Wed Jul 11 2017
* REVISION:
*
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isK2hr3TemplateResult = exports.isValTypeTemplateVariablesMap = exports.isReplicationStatementObject = exports.isNotEmptyStatementsArray = exports.isSafeStatementsArray = exports.isSafeStatementObject = exports.K2hr3TemplateResult = void 0;
const k2hr3apiutil_1 = __importDefault(require("./k2hr3apiutil"));
const dbglogging_1 = __importDefault(require("./dbglogging"));
//---------------------------------------------------------
// Keywords for K2HR3 Template Engine
//---------------------------------------------------------
// Engine type Keywords
const TEMPL_ENGINE_TYPE_PTN = '^{{#!(.*?)[ \t]*}}[\r\n]*'; // Regex = /^\{\{#\!(.*)[ \t]+\}\}[\r\n]*/
const TEMPL_K2HR3_TEMPLENGINE_KW = 'k2hr3template'; // This k2hr3template.js keywords
// Template area Keywords
const TEMPL_START_KW = '{{';
const TEMPL_END_KW = '}}';
const TEMPL_ESCAPE_START_KW = '{{{';
const TEMPL_ESCAPE_END_KW = '}}}';
// Special Keywords
const TEMPL_SEMICOLON_KW = ';'; // ";" for sentence or "for"
const TEMPL_COMMENT_KW = '#'; // Comment
const TEMPL_PRINT_KW = '='; // Print command, this keyword after '{{'
// Control syntax
const TEMPL_IF_KW = 'if'; // if
const TEMPL_ELIF_KW = 'elif'; // elif
const TEMPL_ELSE_KW = 'else'; // else
const TEMPL_ENDIF_KW = 'endif'; // endif
const TEMPL_WHILE_KW = 'while'; // while
const TEMPL_DO_KW = 'do'; // do(while)
const TEMPL_DONE_KW = 'done'; // done
const TEMPL_FOR_KW = 'for'; // for
const TEMPL_FOREACH_KW = 'foreach'; // foreach
const TEMPL_IN_KW = 'in'; // "in" for "foreach"
const TEMPL_BREAK_KW = 'break'; // break
const TEMPL_CONTINUE_KW = 'continue'; // continue
// Conditions
const TEMPL_AND_KW = '&&'; // Condition: AND
const TEMPL_OR_KW = '||'; // Condition: OR
const TEMPL_LESS_KW = '<'; // Condition: LESS THAN
const TEMPL_GREAT_KW = '>'; // Condition: GREATER THAN
const TEMPL_LESSEQ_KW = '<='; // Condition: LESS EQUAL THAN
const TEMPL_GREATEQ_KW = '>='; // Condition: GREATER EQUAL THAN
const TEMPL_EQUAL_KW = '=='; // Condition: EQUAL
const TEMPL_NOTEQ_KW = '!='; // Condition: NOT EQUAL
// One term operator
const TEMPL_NOT_KW = '!'; // One term operator
const TEMPL_INC_KW = '++'; // One term operator
const TEMPL_DEC_KW = '--'; // One term operator
// Binary operator
const TEMPL_SET_KW = '='; // Binary operator
const TEMPL_ADD_KW = '+'; // Binary operator
const TEMPL_SUB_KW = '-'; // Binary operator
const TEMPL_DIV_KW = '/'; // Binary operator
const TEMPL_MUL_KW = '*'; // Binary operator
const TEMPL_REM_KW = '%'; // Binary operator
const TEMPL_AMP_KW = '&'; // Binary operator
const TEMPL_VARTBAR_KW = '|'; // Binary operator
const TEMPL_LSHIFT_KW = '<<'; // Binary operator
const TEMPL_RSHIFT_KW = '>>'; // Binary operator
// Array operator
const TEMPL_SQUARE_START_KW = '['; // keywords for accessing to array member
const TEMPL_SQUARE_END_KW = ']'; //
const TEMPL_CURLY_START_KW = '{'; // keywords for accessing to object member
const TEMPL_CURLY_END_KW = '}'; //
// String area and escape for it
const TEMPL_SINGLE_QUOTE_KW = '\''; // Separator for string value
const TEMPL_DOUBLE_QUOTE_KW = '"'; // Separator for string value
const TEMPL_ESCAPE_KW = '\\'; // escape
// Variable area for K2hr3 template
const TEMPL_VALUESEP_KW = '%'; // Separator for Variable
// Length(size) property
const TEMPL_LENGTH_KW = '.length'; // length property for array or object variable
const TEMPL_SIZE_KW = '.size'; //
const TEMPL_COUNT_KW = '.count'; //
// Static values
const TEMPL_NULL_KW = 'null'; // constant null
const TEMPL_TRUE_KW = 'true'; // constant true
const TEMPL_FALSE_KW = 'false'; // constant false
// Radix for static number values
const TEMPL_HEX_PREFIX_KW = '0x'; // hex(16) radix
const TEMPL_HEX2_PREFIX_KW = 'x'; // hex(16) radix
const TEMPL_OCT_PREFIX_KW = '0o'; // octal(8) radix
const TEMPL_BIN_PREFIX_KW = '0b'; // binary(2) radix
//
// Calculation type using in Calculate Formula Class
//
const FORMULA_CALC_TYPE_UNKNOWN = -1;
const FORMULA_CALC_TYPE_NOT = 0;
const FORMULA_CALC_TYPE_INC = 1;
const FORMULA_CALC_TYPE_DEC = 2;
const FORMULA_CALC_TYPE_SET = 3;
const FORMULA_CALC_TYPE_ADD = 4;
const FORMULA_CALC_TYPE_SUB = 5;
const FORMULA_CALC_TYPE_DIV = 6;
const FORMULA_CALC_TYPE_MUL = 7;
const FORMULA_CALC_TYPE_REM = 8;
const FORMULA_CALC_TYPE_AMP = 9;
const FORMULA_CALC_TYPE_VARTBAR = 10;
const FORMULA_CALC_TYPE_LSHIFT = 11;
const FORMULA_CALC_TYPE_RSHIFT = 12;
//
// Condition type using in Condition Formula Class
//
const FORMULA_COND_TYPE_UNKNOWN = -1;
const FORMULA_COND_TYPE_AND = 100;
const FORMULA_COND_TYPE_OR = 101;
const FORMULA_COND_TYPE_LESS = 102;
const FORMULA_COND_TYPE_GREAT = 103;
const FORMULA_COND_TYPE_LESSEQ = 104;
const FORMULA_COND_TYPE_GREATEQ = 105;
const FORMULA_COND_TYPE_EQUAL = 106;
const FORMULA_COND_TYPE_NOTEQ = 107;
//
// Utility for map
//
const TEMPL_BIN_OP_MAP = {
[TEMPL_SUB_KW]: FORMULA_CALC_TYPE_SUB,
[TEMPL_DIV_KW]: FORMULA_CALC_TYPE_DIV,
[TEMPL_MUL_KW]: FORMULA_CALC_TYPE_MUL,
[TEMPL_REM_KW]: FORMULA_CALC_TYPE_REM,
[TEMPL_LSHIFT_KW]: FORMULA_CALC_TYPE_LSHIFT,
[TEMPL_RSHIFT_KW]: FORMULA_CALC_TYPE_RSHIFT
};
const FORMULA_CALAC_TYPE_STR_MAP = {
[FORMULA_CALC_TYPE_SUB]: 'SUB(-)',
[FORMULA_CALC_TYPE_DIV]: 'DIV(/)',
[FORMULA_CALC_TYPE_MUL]: 'MUL(*)',
[FORMULA_CALC_TYPE_REM]: 'REM(%)',
[FORMULA_CALC_TYPE_LSHIFT]: 'LSHIFT(<<)',
[FORMULA_CALC_TYPE_RSHIFT]: 'RSHIFT(>>)'
};
const TEMPL_COND_TYPE_MAP = {
[TEMPL_AND_KW]: FORMULA_COND_TYPE_AND,
[TEMPL_OR_KW]: FORMULA_COND_TYPE_OR,
[TEMPL_LESS_KW]: FORMULA_COND_TYPE_LESS,
[TEMPL_GREAT_KW]: FORMULA_COND_TYPE_GREAT,
[TEMPL_LESSEQ_KW]: FORMULA_COND_TYPE_LESSEQ,
[TEMPL_GREATEQ_KW]: FORMULA_COND_TYPE_GREATEQ,
[TEMPL_EQUAL_KW]: FORMULA_COND_TYPE_EQUAL,
[TEMPL_NOTEQ_KW]: FORMULA_COND_TYPE_NOTEQ
};
const FORMULA_COND_TYPE_STR_MAP = {
[FORMULA_COND_TYPE_AND]: 'AND(&&)',
[FORMULA_COND_TYPE_OR]: 'OR(||)',
[FORMULA_COND_TYPE_LESS]: 'LESS(<)',
[FORMULA_COND_TYPE_GREAT]: 'GREAT(>)',
[FORMULA_COND_TYPE_LESSEQ]: 'LESSEQ(<=)',
[FORMULA_COND_TYPE_GREATEQ]: 'GREATEQ(<=)',
[FORMULA_COND_TYPE_EQUAL]: 'EQUAL(==)',
[FORMULA_COND_TYPE_NOTEQ]: 'NOTEQ(!=)'
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility : Type chekcer
//---------------------------------------------------------
const isSafeStatementObject = (val, is_check_units) => {
if (!k2hr3apiutil_1.default.isPlainObject(val)) {
return false;
}
if (!k2hr3apiutil_1.default.isBoolean(val.isStatement) ||
!k2hr3apiutil_1.default.isString(val.origString) ||
!k2hr3apiutil_1.default.isString(val.cvtString) ||
!k2hr3apiutil_1.default.isBoolean(val.isReplication)) {
return false;
}
if (!k2hr3apiutil_1.default.isBoolean(is_check_units)) {
is_check_units = true;
}
if (is_check_units && !k2hr3apiutil_1.default.isString2DArray(val.formUnits)) {
return false;
}
return true;
};
exports.isSafeStatementObject = isSafeStatementObject;
const isSafeStatementsArray = (arr, is_check_units) => {
if (!k2hr3apiutil_1.default.isBoolean(is_check_units)) {
is_check_units = true;
}
return k2hr3apiutil_1.default.isArray(arr) && arr.every((element) => isSafeStatementObject(element, is_check_units));
};
exports.isSafeStatementsArray = isSafeStatementsArray;
const isNotEmptyStatementsArray = (arr) => {
return (isSafeStatementsArray(arr) && 0 !== arr.length);
};
exports.isNotEmptyStatementsArray = isNotEmptyStatementsArray;
const isReplicationStatementObject = (statementObj) => {
if (!isSafeStatementObject(statementObj, false) ||
!statementObj.isReplication) {
return false;
}
return true;
};
exports.isReplicationStatementObject = isReplicationStatementObject;
const isValTypeTemplateVariablesMap = (val) => {
if (!k2hr3apiutil_1.default.isPlainObject(val)) {
return false;
}
for (const [, value] of Object.entries(val)) {
if (undefined === value) {
return false;
}
}
return true;
};
exports.isValTypeTemplateVariablesMap = isValTypeTemplateVariablesMap;
const isK2hr3TemplateResult = (val) => {
return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof K2hr3TemplateResult);
};
exports.isK2hr3TemplateResult = isK2hr3TemplateResult;
const isBaseTemplateObject = (val) => {
return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof BaseTemplateObject);
};
const getSafeBaseTemplateObject = (val) => {
return (isBaseTemplateObject(val) ? val : null);
};
const isBaseFormulaObject = (val) => {
return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof BaseFormulaObject);
};
const isSyntaxFormulaObject = (val) => {
return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof SyntaxFormulaObject);
};
const isCalculateFormulaObject = (val) => {
return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof CalculateFormulaObject);
};
const isConditionFormulaObject = (val) => {
return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof ConditionFormulaObject);
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility : Create K2HR3 Template Objects
//---------------------------------------------------------
// Create one statement object tree and return top of tree object.
//
// return : following object
// {
// result: true/false
// message: null or <error message string>
// templObj: null or BaseTemplateObject object
// }
//
// [NOTE]
// If object tree is rechained(the parent was included into new object),
// this returns result=true and templObj=null.
//
const createK2hr3TemplateObject = (statementsArray, parentObject) => {
const resobj = { result: false, message: null, templObj: null };
if (!isSafeStatementsArray(statementsArray) || !isNotEmptyStatementsArray(statementsArray)) {
resobj.result = true;
resobj.templObj = null;
dbglogging_1.default.elog('templateArray is empty or wrong : ' + JSON.stringify(statementsArray));
return resobj;
}
if (null !== parentObject && !isBaseTemplateObject(parentObject)) {
resobj.result = false;
resobj.message = 'parentObject is not BaseTemplateObject class or subclass : ' + JSON.stringify(parentObject);
dbglogging_1.default.elog(resobj.message);
return resobj;
}
let lastErrorString = '';
for (let cnt = 0; cnt < k2hr3StatementObjectList.length; ++cnt) {
// create object
const assembleObject = new k2hr3StatementObjectList[cnt]();
// test assembling
if (assembleObject.testAssemble(statementsArray)) {
// try assemble
if (null !== assembleObject.assemble(statementsArray, parentObject)) {
let foundObject;
for (foundObject = assembleObject; foundObject; foundObject = foundObject.getParentTemplObject()) {
if (parentObject === foundObject.getParentTemplObject()) { // [NOTE] allow parentObject is null
break;
}
}
if (foundObject) {
// found parent object in assembleObject's parent inheritance tree.
//
resobj.result = true;
resobj.templObj = foundObject;
return resobj;
}
else {
// not found parent object in assembleObject's parent inheritance tree.
//
// This means that the parent of assembleObject points to parent object
// rather than parentObject as analysis result, and assembleObject does
// not exist in descendant tree of parentObject.
// On this case, this function returns resobj.templObj = null, then
// stop analyzing the statementArray for parentObject's child.
//
resobj.result = true;
resobj.templObj = null;
return resobj;
}
}
else {
// could not assemble or something error occurred.
// then any error message is stocked.
//
if (k2hr3apiutil_1.default.isSafeString(lastErrorString.length)) {
lastErrorString += ', ';
}
lastErrorString += '(';
lastErrorString += assembleObject.getError() + ')';
}
}
else {
// statement object is not a target
}
}
// not matched
resobj.result = false;
resobj.message = 'any template class is not matched for templateArray : ' + lastErrorString;
dbglogging_1.default.elog(resobj.message);
return resobj;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility : Check K2HR3 Template left
//---------------------------------------------------------
// Check the first template statement's unit requires left
// statements.
//
const REQUIRED_LEFT_NO = 0;
const REQUIRED_LEFT_VARIABLE = 1;
const REQUIRED_LEFT_CALCULATE = 2;
const REQUIRED_LEFT_CONDITION = 4;
const REQUIRED_LEFT_ALL = (REQUIRED_LEFT_VARIABLE | REQUIRED_LEFT_CALCULATE | REQUIRED_LEFT_CONDITION);
const isRequireLeftTemplate = (statementsArray, arg_type) => {
if (!k2hr3apiutil_1.default.isSafeNumber(arg_type)) {
dbglogging_1.default.elog('arg_type parameter is wrong : ' + JSON.stringify(arg_type));
return false;
}
if (!isNotEmptyStatementsArray(statementsArray)) {
// empty
return false;
}
// first unit(string)
const unit = statementsArray[0].formUnits[0][0];
let unit_type = REQUIRED_LEFT_NO;
switch (unit) {
case TEMPL_INC_KW:
case TEMPL_DEC_KW:
unit_type = REQUIRED_LEFT_VARIABLE;
break;
case TEMPL_AND_KW:
case TEMPL_OR_KW:
case TEMPL_LESS_KW:
case TEMPL_GREAT_KW:
case TEMPL_LESSEQ_KW:
case TEMPL_GREATEQ_KW:
case TEMPL_EQUAL_KW:
case TEMPL_NOTEQ_KW:
unit_type = REQUIRED_LEFT_ALL;
break;
case TEMPL_SET_KW:
unit_type = REQUIRED_LEFT_VARIABLE;
break;
case TEMPL_ADD_KW:
case TEMPL_SUB_KW:
case TEMPL_DIV_KW:
case TEMPL_MUL_KW:
case TEMPL_REM_KW:
unit_type = REQUIRED_LEFT_VARIABLE | REQUIRED_LEFT_CALCULATE;
break;
case TEMPL_AMP_KW:
case TEMPL_VARTBAR_KW:
unit_type = REQUIRED_LEFT_ALL;
break;
case TEMPL_LSHIFT_KW:
case TEMPL_RSHIFT_KW:
unit_type = REQUIRED_LEFT_VARIABLE;
break;
default:
break;
}
return (0 !== (arg_type & unit_type));
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Create/Modify Template Statement Objects
//---------------------------------------------------------
const createEmptyK2hr3TemplateStatement = (isStatement, isReplication) => {
const areaobj = {
isStatement: (k2hr3apiutil_1.default.isBoolean(isStatement) ? isStatement : true), // default true
origString: '',
cvtString: '',
isReplication: (k2hr3apiutil_1.default.isBoolean(isReplication) ? isReplication : true), // default true
formUnits: [] // empty array[]
};
return areaobj;
};
const replicateK2hr3TemplateStatement = (statementObj) => {
if (!isSafeStatementObject(statementObj, false)) { // not check units
return createEmptyK2hr3TemplateStatement();
}
const areaobj = createEmptyK2hr3TemplateStatement(statementObj.isStatement, true);
if (k2hr3apiutil_1.default.isString2DArray(statementObj.formUnits)) {
areaobj.formUnits = statementObj.formUnits; // reference
}
return areaobj;
};
const createReplicatedK2hr3TemplateStatement = (isStatement, formUnits) => {
const areaobj = createEmptyK2hr3TemplateStatement(isStatement, true);
if (k2hr3apiutil_1.default.isNotEmptyArray(formUnits)) {
areaobj.formUnits = formUnits;
}
return areaobj;
};
const replaceK2hr3TemplateStatementFormUnits = (statementObj, formUnits) => {
// Allowed empty formUnits and not check strict statementObj
if (!isSafeStatementObject(statementObj) || !k2hr3apiutil_1.default.isString2DArray(formUnits)) { // check units
return false;
}
statementObj.formUnits = formUnits;
return true;
};
const compressStatementsArray = (statementsArray) => {
if (!k2hr3apiutil_1.default.isArray(statementsArray)) {
return;
}
for (let cnt1 = 0; cnt1 < statementsArray.length;) {
if (!isSafeStatementObject(statementsArray[cnt1], false)) {
// something is wrong, then remove this statement object
statementsArray.splice(cnt1, 1);
}
else {
for (let cnt2 = 0; cnt2 < statementsArray[cnt1].formUnits.length;) {
if (!k2hr3apiutil_1.default.isNotEmptyArray(statementsArray[cnt1].formUnits[cnt2])) {
// units is empty, then remove this units
statementsArray[cnt1].formUnits.splice(cnt2, 1);
}
else {
for (let cnt3 = 0; cnt3 < statementsArray[cnt1].formUnits[cnt2].length;) {
if (!k2hr3apiutil_1.default.isSafeString(statementsArray[cnt1].formUnits[cnt2][cnt3]) && '' !== statementsArray[cnt1].formUnits[cnt2][cnt3]) {
// one unit is wrong, then remove this unit
statementsArray[cnt1].formUnits[cnt2].splice(cnt3, 1);
}
else {
++cnt3;
}
}
if (!k2hr3apiutil_1.default.isNotEmptyArray(statementsArray[cnt1].formUnits[cnt2])) {
// finally units is empty, then remove this units
statementsArray[cnt1].formUnits.splice(cnt2, 1);
}
else {
++cnt2;
}
}
}
if (!k2hr3apiutil_1.default.isNotEmptyArray(statementsArray[cnt1].formUnits)) {
// finally units is empty, then remove this units
statementsArray.splice(cnt1, 1);
}
else {
++cnt1;
}
}
}
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Rollback Template Statement Objects
//---------------------------------------------------------
//
// rollback(insert) statement object to statements array
//
// is_add_first_pos : if true, insert statement object at first position in statementsArray.
// if false, push bach units array data to statementsArray.
//
// return : returns statementsArray object
// if input statementsArray is wrong, returned statementsArray is created in this function.
// please take care for wrong input.
//
// [NOTE]
// If statementObj is replication object, this rollbacks only formUnits in statementObj.
//
const rollbackStatementObjectToArray = (statementsArray, statementObj, is_add_first_pos) => {
if (!k2hr3apiutil_1.default.isBoolean(is_add_first_pos)) {
is_add_first_pos = true;
}
if (!isSafeStatementObject(statementObj, false)) { // not check units
// statement object is something wrong
// ---> nothing to do
return statementsArray;
}
if (!isSafeStatementsArray(statementsArray, false)) { // not check units
// statementsArray is something wrong
// ---> overwrite it by statement object.
statementsArray = [statementObj];
}
else if (0 === statementsArray.length) {
// statementsArray is empty
// ---> push statement object.
statementsArray.push(statementObj);
}
else {
const pos = (is_add_first_pos ? 0 : (statementsArray.length - 1));
if (!isReplicationStatementObject(statementObj)) {
// statement object is not replication
if (isReplicationStatementObject(statementsArray[pos])) {
// statementsArray[pos] is not replication
if (is_add_first_pos) {
// ---> insert statement object to top of statement array
statementsArray.unshift(statementObj);
}
else {
// ---> push back statement object to last of statement array
statementsArray.push(statementObj);
}
}
else {
// statementsArray[pos] is replication,
if (is_add_first_pos) {
// ---> insert the statement object' formUnits to top of statementsArray[pos]'s one.
// and replace statementsArray[pos] other member with statement object's one.
for (let cnt = 0; cnt < statementsArray[pos].formUnits.length; ++cnt) {
statementObj.formUnits.push(statementsArray[pos].formUnits[cnt]);
}
statementsArray.shift();
statementsArray.unshift(statementObj);
}
else {
// ---> push back the statement object' formUnits to last of statementsArray[pos]'s one.
// and replace statementsArray[pos] other member with statement object's one.
for (let cnt = 0; cnt < statementsArray[pos].formUnits.length; ++cnt) {
statementObj.formUnits.unshift(statementsArray[pos].formUnits[statementsArray[pos].formUnits.length - cnt - 1]);
}
statementsArray.splice(statementsArray.length - 1, 1);
statementsArray.push(statementObj);
}
}
}
else {
// statement object is replication
if (isReplicationStatementObject(statementsArray[pos])) {
// statementsArray[pos] is not replication
if (is_add_first_pos) {
// ---> insert statement object to top of statement array
statementsArray.unshift(statementObj);
}
else {
// ---> push back statement object to last of statement array
statementsArray.push(statementObj);
}
}
else {
// statementsArray[pos] is replication
if (is_add_first_pos) {
// ---> insert the statement object' formUnits to top of statementsArray[pos]'s one.
for (let cnt = 0; cnt < statementObj.formUnits.length; ++cnt) {
statementsArray[pos].formUnits.unshift(statementObj.formUnits[statementObj.formUnits.length - cnt - 1]);
}
}
else {
// ---> push back the statement object' formUnits to last of statementsArray[pos]'s one.
for (let cnt = 0; cnt < statementObj.formUnits.length; ++cnt) {
statementsArray[pos].formUnits.push(statementObj.formUnits[cnt]);
}
}
}
}
}
return statementsArray;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Parse Template Statement Objects
//---------------------------------------------------------
//
// Parse k2hr3 template to statement areas and minimum formula units.
//
// templString : The string is all of template string
// result : Statement object Array
//
const parseK2hr3Template = (templString) => {
// parse template to statement areas
const resobj = parseK2hr3TemplateToStatements(templString);
if (!isSafeStatementsArray(resobj)) {
dbglogging_1.default.dlog('parsed template string result is null.');
return null;
}
const objarr = resobj;
// parse each statement area to formula units
for (let cnt = 0; k2hr3apiutil_1.default.isNotEmptyArray(objarr) && cnt < objarr.length; ++cnt) {
if (!k2hr3apiutil_1.default.isSafeEntity(objarr[cnt])) {
// why?
objarr.splice(cnt, 1);
if (0 === cnt) {
cnt = -1;
}
else {
--cnt;
}
continue;
}
let formUnits;
if (objarr[cnt].isStatement) {
// in statement area
formUnits = parseK2hr3TemplateForStatements(objarr[cnt].cvtString);
if (null === formUnits || !k2hr3apiutil_1.default.isString2DArray(formUnits)) {
// empty sentence, so remove this element.
objarr.splice(cnt, 1);
if (0 === cnt) {
cnt = -1;
}
else {
--cnt;
}
continue;
}
}
else {
// not statement area
formUnits = [[objarr[cnt].cvtString]];
}
objarr[cnt].formUnits = formUnits;
}
if (!k2hr3apiutil_1.default.isNotEmptyArray(objarr)) {
dbglogging_1.default.dlog('parsed template string result is null.');
return null;
}
//r3logger.dlog('parsed template string result is : ' + r3logger.dump(objarr));
return objarr;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Parse Template String to Template Statement Objects
//---------------------------------------------------------
//
// Parse input string which is k2hr3 template to statement areas array.
// Each area is statement or not statement area.
//
// templString : The string is all of template string
// result : Following object array, return empty array when error.
// [
// { : Each template area(statement area / not statement area)
// "isStatement": true/false : This is true when the template area is statement({{...}}).
// "origString": <string> : original string
// "cvtString": <string> : converted string(escaped keyword and trimmed when statement area includes formula)
// },
// ...
// ]
//
const parseK2hr3TemplateToStatements = (templString) => {
if (!k2hr3apiutil_1.default.isSafeString(templString)) {
return null;
}
let inputString = templString;
// parse
const resobj = [];
let tmpl_cvtstr = '';
let tmpl_origin = '';
let keyword = TEMPL_START_KW;
let escword = TEMPL_ESCAPE_START_KW;
let oescword = TEMPL_ESCAPE_END_KW; // not keyword's escape
let templ_area = false;
while (k2hr3apiutil_1.default.isSafeString(inputString) && 0 < inputString.length) {
// each
const key_pos = inputString.indexOf(keyword); // '{{' or '}}'
const esc_pos = inputString.indexOf(escword); // '{{{' or '}}}'
const oesc_pos = inputString.indexOf(oescword); // '}}}' or '{{{'
if (-1 !== oesc_pos && (-1 === key_pos || oesc_pos < key_pos)) {
// found not keyword's escaped words before keyword
tmpl_origin += inputString.substr(0, oesc_pos + 3);
tmpl_cvtstr += inputString.substr(0, oesc_pos + 2); // converts '{{{'('}}}') to '{{'('}}') and appends it to end of tmpl_cvtstr.
inputString = inputString.substr(oesc_pos + 3); // after key words('{{{' or '}}}')
}
else {
if (-1 != esc_pos && esc_pos === key_pos) {
// found escaped key words
tmpl_origin += inputString.substr(0, esc_pos + 3);
tmpl_cvtstr += inputString.substr(0, esc_pos + 2); // converts '{{{'('}}}') to '{{'('}}') and appends it to end of tmpl_cvtstr.
inputString = inputString.substr(esc_pos + 3); // after key words('{{{' or '}}}')
}
else if (-1 != key_pos) {
// found key words
if (templ_area) {
tmpl_origin += inputString.substr(0, key_pos + 2); // original string with '}}'
tmpl_cvtstr += inputString.substr(0, key_pos); // converted string without '}}'
// make object
const oneobj = {
isStatement: true,
origString: tmpl_origin,
cvtString: tmpl_cvtstr.trim(), // trimmed string
isReplication: false,
formUnits: []
};
// add
if (k2hr3apiutil_1.default.isSafeString(oneobj.origString)) {
resobj.push(oneobj);
}
// set next
templ_area = false;
keyword = TEMPL_START_KW;
escword = TEMPL_ESCAPE_START_KW;
oescword = TEMPL_ESCAPE_END_KW;
tmpl_origin = '';
tmpl_cvtstr = '';
inputString = inputString.substr(key_pos + 2); // after key words('{{')
}
else {
tmpl_origin += inputString.substr(0, key_pos); // original string without '{{'
tmpl_cvtstr += inputString.substr(0, key_pos); // converted string without '{{'
// make object
const oneobj = {
isStatement: false,
origString: tmpl_origin,
cvtString: tmpl_cvtstr, // not trimmed string
isReplication: false,
formUnits: []
};
// add
if (k2hr3apiutil_1.default.isSafeString(oneobj.origString)) {
resobj.push(oneobj);
}
// set next
templ_area = true;
keyword = TEMPL_END_KW;
escword = TEMPL_ESCAPE_END_KW;
oescword = TEMPL_ESCAPE_START_KW;
tmpl_origin = TEMPL_START_KW; // start original string with '{{'
tmpl_cvtstr = '';
inputString = inputString.substr(key_pos + 2); // after key words('}}')
}
}
else {
// not found keywords
tmpl_origin += inputString; // add rest string to original string
tmpl_cvtstr += inputString; // add rest string to converted string
const oneobj = {
isStatement: (templ_area ? true : false),
origString: tmpl_origin,
cvtString: (templ_area ? tmpl_cvtstr.trim() : tmpl_cvtstr),
isReplication: false,
formUnits: []
};
// add
if (k2hr3apiutil_1.default.isSafeString(oneobj.origString)) {
resobj.push(oneobj);
}
break;
}
}
}
return resobj;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Parse Template String to Minimum Template Statement Objects
//---------------------------------------------------------
//
// Parse input string which is rough cutting statement area to minimum statement array.
// Each minimum statement has formula units array which elements are minimum formula string.
// Formula unit string is separated by keywords.
//
// target : the string in template area which is from '{{' to '}}'.
// result : The array has formula units array which is separated by ':'.
// The one sentence array member is array which member is
// minimum opcode/operand unit.
// [
// [ : One sentence(separated by ';')
// "unit string", : One unit(separated by keywords...)
// "unit string",
// ...
// ],
// ...
// ]
//
// [NOTE]
// About comment and print statement which are special.
// If target starts comment keyword('{{#'), this returns [ ["#", "...."] ] array.
// If target starts print keyword('{{='), this returns [ ["=", "...."], ... ] array.
//
const parseK2hr3TemplateForStatements = (target, is_print_statement) => {
if (!k2hr3apiutil_1.default.isSafeString(target)) {
return null;
}
const inputTarget = target;
const is_print = (!k2hr3apiutil_1.default.isBoolean(is_print_statement) ? false : is_print_statement);
let mainres = [];
let subres = [];
let one_part = '';
// check comment/print line at first
if (0 === inputTarget.indexOf(TEMPL_COMMENT_KW)) {
// found comment keyword at first character position
one_part = inputTarget.substr(1).trim();
subres.push(TEMPL_COMMENT_KW);
if (k2hr3apiutil_1.default.isSafeString(one_part)) {
subres.push(one_part);
}
mainres.push(subres);
return mainres;
}
else if (!is_print && 0 === inputTarget.indexOf(TEMPL_PRINT_KW)) {
// found print keyword at first character position
one_part = inputTarget.substr(1).trim();
// reentrant for analyzing after statement string
const tmpres = parseK2hr3TemplateForStatements(one_part, true);
if (null === tmpres || !k2hr3apiutil_1.default.isNotEmptyArray(tmpres)) {
// mainres array is empty, then make static for print(maybe this is error at assembling or executing)
subres.push(TEMPL_PRINT_KW);
mainres = [];
mainres.push(subres);
}
else if (!k2hr3apiutil_1.default.isNotEmptyArray(tmpres[0])) {
// first array in mainres is empty, then make static for print(maybe this is error at assembling or executing)
subres.push(TEMPL_PRINT_KW);
mainres[0] = subres;
}
else {
// insert print keyword into first of array
mainres = tmpres;
mainres[0].unshift(TEMPL_PRINT_KW);
}
return mainres;
}
// parse to statement string
let is_squate = false;
let is_dquate = false;
let is_escape = false;
for (let cnt = 0; cnt < inputTarget.length; ++cnt) {
// check ';', '\'', '\"', '\\', '\s'
if (TEMPL_SEMICOLON_KW === inputTarget[cnt]) { // ';'
if (is_escape) {
one_part += TEMPL_ESCAPE_KW;
}
is_squate = false;
is_dquate = false;
is_escape = false;
if (0 < one_part.length) {
subres.push(one_part); // finish one word
one_part = '';
}
if (0 < subres.length) {
mainres.push(subres); // finish statement
subres = [];
}
}
else if (TEMPL_SINGLE_QUOTE_KW === inputTarget[cnt]) { // '\''
if (is_escape) {
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
one_part += inputTarget[cnt];
}
else if (is_squate) {
is_squate = false;
one_part += inputTarget[cnt];
subres.push(one_part); // finish one word
one_part = '';
}
else if (is_dquate) {
// nothing to do...
one_part += inputTarget[cnt];
}
else {
is_squate = true;
if (0 < one_part.length) {
subres.push(one_part); // finish one word
}
one_part = inputTarget[cnt];
}
}
else if (TEMPL_DOUBLE_QUOTE_KW === inputTarget[cnt]) { // '\"'
if (is_escape) {
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
one_part += inputTarget[cnt];
}
else if (is_dquate) {
is_dquate = false;
one_part += inputTarget[cnt];
subres.push(one_part); // finish one word
one_part = '';
}
else if (is_squate) {
// nothing to do...
one_part += inputTarget[cnt];
}
else {
is_dquate = true;
if (0 < one_part.length) {
subres.push(one_part); // finish one word
}
one_part = inputTarget[cnt];
}
}
else if (TEMPL_ESCAPE_KW === inputTarget[cnt]) { // '\\'
if (is_escape) {
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
one_part += inputTarget[cnt];
}
else {
is_escape = true;
}
}
else if (' ' === inputTarget[cnt] || '\t' === inputTarget[cnt] || '\r' === inputTarget[cnt] || '\n' === inputTarget[cnt]) { // === \s
if (is_escape) {
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
subres.push(one_part); // finish one word
one_part = '';
}
else if (is_dquate || is_squate) {
one_part += inputTarget[cnt];
}
else if (0 === one_part.length) {
// nothing to do
}
else {
subres.push(one_part); // finish one word
one_part = '';
}
}
else { // another char
if (is_escape) {
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
}
one_part += inputTarget[cnt];
}
}
// rest
if (is_escape) {
one_part += TEMPL_ESCAPE_KW;
}
if (0 < one_part.length) {
subres.push(one_part); // finish one word
}
if (0 < subres.length) {
mainres.push(subres); // finish statement
}
// next parse units(minimum formula units)
const tmpres = parseK2hr3TemplateStatementToFomulaUnits(mainres);
return tmpres;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Parsing Template Formula String to Minimum Template Statement Units
//---------------------------------------------------------
//
// This parses double array which is parsed by parseK2hr3TemplateForStatements
// to minimum formula units.
// After this parsing, the result double array is separated minimum formula units
// array divided into instruction units.
//
// mainres : input array which elements are each statement area.
// [
// [ : array for statement separated by ';'
// "unit string", : unit statement string separated by ';' or "string"(which is statement area by '\'' or '\"')
// ...
// ]
// ]
//
// result : parse input unit array by keywords
// [
// [ : array for statement separated by ';'
// "unit string", : One unit formula string separated by ';' or "string" or any keywords
// ...
// ]
// ]
//
const parseK2hr3TemplateStatementToFomulaUnits = (mainres) => {
if (!k2hr3apiutil_1.default.isString2DArray(mainres) || !k2hr3apiutil_1.default.isNotEmptyArray(mainres)) {
return mainres;
}
const tmpres = mainres;
for (let cnt = 0; cnt < tmpres.length; ++cnt) {
if (!k2hr3apiutil_1.default.isNotEmptyArray(tmpres[cnt])) {
// why?
tmpres.splice(cnt, 1);
if (0 === cnt) {
cnt = -1;
}
else {
--cnt;
}
continue;
}
// parse subres to some units
const subres = tmpres[cnt];
for (let cnt2 = 0; cnt2 < subres.length; ++cnt2) {
// parse string to minimum unit array
const subres_array = parseK2hr3TemplateStatementToMinimumUnits(subres[cnt2]);
if (!k2hr3apiutil_1.default.isNotEmptyArray(subres_array)) {
// why?
subres.splice(cnt2, 1);
if (0 === cnt2) {
cnt2 = -1;
}
else {
--cnt2;
}
}
else if (1 < subres_array.length) {
// replace pos to array
subres.splice(cnt2, 1);
for (let cnt3 = 0; cnt3 < subres_array.length; ++cnt3) {
subres.splice(cnt2, 0, subres_array[subres_array.length - cnt3 - 1]);
}
cnt2 += subres_array.length - 1;
}
else {
// nothing to do
}
}
// check empty subres
if (!k2hr3apiutil_1.default.isStringArray(subres) || !k2hr3apiutil_1.default.isNotEmptyArray(subres)) {
// tmpres[cnt] has empty subres array, then remove cnt position array.
tmpres.splice(cnt, 1);
if (0 === cnt) {
cnt = -1;
}
else {
--cnt;
}
}
}
// [NOTE]
// if units array(subres) is empty, it is removed from tmpres.
// if there is no units in tmpres, tmpres is empty array.
//
return tmpres;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Parsing Template String Including Some Formula to Minimum Template Statement Units
//---------------------------------------------------------
//
// If it starts '\'' or '\"', it means "string" area which maybe include ';' and '\s'.
// Then this method does not check when the target is "string" and '\' character,
// because it effects only "string".
// The input string must not include basically ';' and '\s'.
//
// result : null or following array
// [
// "unit string", : One unit in formula(separate keywords...)
// ...
// ]
//
const parseK2hr3TemplateStatementToMinimumUnits = (target) => {
if (!k2hr3apiutil_1.default.isSafeString(target)) {
return [];
}
const inputTarget = target;
const resarr = [];
if (TEMPL_SINGLE_QUOTE_KW === inputTarget[0] || TEMPL_DOUBLE_QUOTE_KW === inputTarget[0]) {
// inputTarget is '...' or "..." string, then this can not parse.
resarr.push(inputTarget);
return resarr;
}
let one_part = '';
for (let cnt = 0; cnt < inputTarget.length; ++cnt) {
if (TEMPL_VALUESEP_KW === inputTarget[cnt]) { // '%' (== TEMPL_REM_KW)
// [NOTE]
// Space characters are already parsed before calling this function.
//
if (inputTarget.length <= (cnt + 1)) {
// inputTarget[cnt + 1] === \s or null, then inputTarget[cnt] is TEMPL_REM_KW
if (0 !== one_part.length) {
resarr.push(one_part); // set stocked string before percent
}
one_part = TEMPL_REM_KW;
resarr.push(one_part); // set percent
one_part = '';
}
else {
const end_percent_pos = inputTarget.substr(cnt + 1).indexOf(TEMPL_VALUESEP_KW);
if (-1 === end_percent_pos) {
// not found end(2'nd) percent/or \r(\n) found before percent, then inputTarget[cnt] is TEMPL_REM_KW
if (0 !== one_part.length) {
resarr.push(one_part); // set stocked string before percent
}
one_part = TEMPL_REM_KW;
resarr.push(one_part); // set percent
one_part = '';
}
else {
// found end(2'nd) percent, then these are TEMPL_VALUESEP_KW
if (0 !== one_part.length) {
resarr.push(one_part); // set stocked string before percent
}
one_part = TEMPL_REM_KW;
one_part += inputTarget.substr(cnt + 1).substr(0, end_percent_pos);
one_part += TEMPL_REM_KW;
resarr.push(one_part); // set %...%(TEMPL_VALUESEP_KW area)
one_part = '';
cnt += end_percent_pos + 1; // cnt is set end of TEMPL_VALUESEP_KW
}
}
}
else if (TEMPL_SQUARE_START_KW === inputTarget[cnt]) { // '['
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
resarr.push(TEMPL_SQUARE_START_KW);
}
else if (TEMPL_SQUARE_END_KW === inputTarget[cnt]) { // ']'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
resarr.push(TEMPL_SQUARE_END_KW);
}
else if (TEMPL_CURLY_START_KW === inputTarget[cnt]) { // '{'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
resarr.push(TEMPL_CURLY_START_KW);
}
else if (TEMPL_CURLY_END_KW === inputTarget[cnt]) { // '}'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
resarr.push(TEMPL_CURLY_END_KW);
}
else if (TEMPL_MUL_KW === inputTarget[cnt]) { // '*'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
resarr.push(TEMPL_MUL_KW);
}
else if (TEMPL_DIV_KW === inputTarget[cnt]) { // '/'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
resarr.push(TEMPL_DIV_KW);
}
else if (TEMPL_NOT_KW === inputTarget[cnt]) { // '!'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_SET_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_NOTEQ_KW); // '!='
}
else {
resarr.push(TEMPL_NOT_KW); // '!'
}
}
else if (TEMPL_SET_KW === inputTarget[cnt]) { // '='
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_SET_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_EQUAL_KW); // '=='
}
else {
resarr.push(TEMPL_SET_KW); // '='
}
}
else if (TEMPL_ADD_KW === inputTarget[cnt]) { // '+'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_ADD_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_INC_KW); // '++'
}
else {
resarr.push(TEMPL_ADD_KW); // '+'
}
}
else if (TEMPL_SUB_KW === inputTarget[cnt]) { // '-'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_SUB_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_DEC_KW); // '--'
}
else {
resarr.push(TEMPL_SUB_KW); // '-'
}
}
else if (TEMPL_AMP_KW === inputTarget[cnt]) { // '&'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_AMP_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_AND_KW); // '&&'
}
else {
resarr.push(TEMPL_AMP_KW); // '&'
}
}
else if (TEMPL_VARTBAR_KW === inputTarget[cnt]) { // '|'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_VARTBAR_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_OR_KW); // '||'
}
else {
resarr.push(TEMPL_VARTBAR_KW); // '|'
}
}
else if (TEMPL_LESS_KW === inputTarget[cnt]) { // '<'
if (0 !== one_part.length) {
resarr.push(one_part);
one_part = '';
}
if ((cnt + 1) < inputTarget.length && TEMPL_SET_KW === inputTarget[cnt + 1]) {
++cnt;
resarr.push(TEMPL_LESS