k2hr3-api
Version:
K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules
1,568 lines (1,462 loc) • 243 kB
JavaScript
/*
* 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:
*
*/
'use strict';
var apiutil = require('./k2hr3apiutil');
// Debug logging objects
var r3logger = 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
//---------------------------------------------------------
// Template Statement Objects for K2HR3 Template Engine
//---------------------------------------------------------
// Statement object Array is an array that decomposes the k2hr3 template and holds its contents.
// It is indicated as follows:
// [
// { : 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)
// "isReplication": true/false : true means the statement object is replicated
// "formUnits": [ : formula units array for each statement area, if the statement does not have any template object, this is [[cvtString]].
// [ : One formula(separate ';')
// "unit string", : One unit in formula(separate keywords...)
// "unit string",
// ...
// ],
// ...
// ]
// },
// ...
// ]
//
// [NOTE]
// If the statement is comment, it's statement area(object) is following as example:
// { "isStatement": true,
// "origString": "{{#.....}}",
// "cvtString": "#....",
// "formUnits": [ [
// "#",
// "....."
// ] ]
// }
//
// If the statement is print, it's statement area(object) is following as example:
// { "isStatement": true,
// "origString": "{{=AAAA; BBBB}}",
// "cvtString": "=AAAA; BBBB",
// "formUnits": [ [
// "=",
// "AAAA"
// ],
// [
// "BBBB"
// ]
// ]
// }
//
//---------------------------------------------------------
// 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.
//
var createK2hr3TemplateObject = function(statementsArray, parentObject)
{
var resobj = {'result': false, 'message': null, 'templObj': null};
if(isEmptyStatementsArray(statementsArray)){
resobj.result = true;
resobj.templObj = null;
r3logger.elog('templateArray is empty or wrong : ' + JSON.stringify(statementsArray));
return resobj;
}
if(null !== parentObject && !(parentObject instanceof BaseTemplateObject)){
resobj.result = false;
resobj.message = 'parentObject is not BaseTemplateObject class or subclass : ' + JSON.stringify(parentObject);
r3logger.elog(resobj.message);
return resobj;
}
var lastErrorString = '';
for(var cnt = 0; cnt < k2hr3StatementObjectList.length; ++cnt){
// create object
var assembleObject = new k2hr3StatementObjectList[cnt]();
// test assembling
if(assembleObject.testAssemble(statementsArray)){
// try assemble
if(null !== assembleObject.assemble(statementsArray, parentObject)){
for(var 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(apiutil.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;
r3logger.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);
var isRequireLeftTemplate = function(statementsArray, type)
{
if(!apiutil.isSafeEntity(type) || isNaN(type)){
r3logger.elog('type parameter is wrong : ' + JSON.stringify(type));
return false;
}
if(isEmptyStatementsArray(statementsArray)){
// empty
return false;
}
// first unit(string)
var unit = statementsArray[0].formUnits[0][0];
var 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 !== (type & unit_type));
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility : Others
//---------------------------------------------------------
var isEmptyStatementsArray = function(statementsArray)
{
if(!isSafeStatementsArray(statementsArray, true) || apiutil.isEmptyArray(statementsArray) || apiutil.isEmptyArray(statementsArray[0].formUnits)){
return true;
}
return false;
};
var isSafeStatementsArray = function(statementsArray, is_check_units)
{
if(!apiutil.isArray(statementsArray)){
return false;
}
for(var cnt = 0; cnt < statementsArray.length; ++cnt){
if(!isSafeStatementObject(statementsArray[cnt], is_check_units)){
return false;
}
}
return true;
};
var isSafeStatementObject = function(statementObj, is_check_units)
{
if(!apiutil.isSafeEntity(is_check_units) || 'boolean' !== typeof is_check_units){
is_check_units = true; // default check units
}
if( !apiutil.isSafeEntity(statementObj) ||
!apiutil.isSafeEntity(statementObj.isStatement) || // check statement object
'boolean' !== typeof statementObj.isStatement || //
(!apiutil.isSafeString(statementObj.origString) && '' !== statementObj.origString) || //
(!apiutil.isSafeString(statementObj.cvtString) && '' !== statementObj.cvtString) || //
!apiutil.isSafeEntity(statementObj.isReplication) || //
'boolean' !== typeof statementObj.isReplication || //
!apiutil.isArray(statementObj.formUnits) || //
(is_check_units && !isSafeFormulaUnits(statementObj.formUnits)) ) // check units array
{
return false;
}
return true;
};
var isReplicationStatementObject = function(statementObj)
{
if( !apiutil.isSafeEntity(statementObj) ||
!apiutil.isSafeEntity(statementObj.isReplication) ||
'boolean' !== typeof statementObj.isReplication ||
!statementObj.isReplication )
{
return false;
}
return true;
};
var isSafeFormulaUnits = function(unitsObj)
{
if(!apiutil.isArray(unitsObj)){
return false;
}
for(var cnt = 0; cnt < unitsObj.length; ++cnt){
if(!isSafeFormulaUnitsArray(unitsObj[cnt]) || apiutil.isEmptyArray(unitsObj[cnt])){
return false;
}
}
return true;
};
var isSafeFormulaUnitsArray = function(unitsArray)
{
if(!apiutil.isArray(unitsArray)){
return false;
}
for(var cnt = 0; cnt < unitsArray.length; ++cnt){
if(!apiutil.isSafeString(unitsArray[cnt]) && '' !== unitsArray[cnt]){
return false;
}
}
return true;
};
//---------------------------------------------------------
// K2HR3 Template Engine Utility
// : Create/Modify Template Statement Objects
//---------------------------------------------------------
var createEmptyK2hr3TemplateStatement = function(isStatement, isReplication)
{
var areaobj = {};
areaobj.isStatement = ('boolean' === typeof isStatement ? isStatement : true); // default true
areaobj.origString = '';
areaobj.cvtString = '';
areaobj.isReplication = ('boolean' === typeof isReplication ? isReplication : true); // default true
areaobj.formUnits = []; // empty array[]
return areaobj;
};
var replicateK2hr3TemplateStatement = function(statementObj)
{
if(!isSafeStatementObject(statementObj, false)){ // not check units
return createEmptyK2hr3TemplateStatement();
}
var areaobj = createEmptyK2hr3TemplateStatement(statementObj.isStatement, true);
if(isSafeFormulaUnits(statementObj.formUnits)){
areaobj.formUnits = statementObj.formUnits; // reference
}
return areaobj;
};
var createReplicatedK2hr3TemplateStatement = function(isStatement, formUnits)
{
var areaobj = createEmptyK2hr3TemplateStatement(isStatement, true);
if(!apiutil.isEmptyArray(formUnits)){
areaobj.formUnits = formUnits;
}
return areaobj;
};
var replaceK2hr3TemplateStatementFormUnits = function(statementObj, formUnits)
{
// Allowed empty formUnits and not check strict statementObj
if( !apiutil.isSafeEntity(statementObj) ||
!apiutil.isArray(formUnits) )
{
return false;
}
statementObj.formUnits = formUnits;
return true;
};
var compressStatementsArray = function(statementsArray)
{
if(!apiutil.isArray(statementsArray)){
return;
}
for(var cnt1 = 0; cnt1 < statementsArray.length; ){
if(!isSafeStatementObject(statementsArray[cnt1], false)){
// something is wrong, then remove this statement object
statementsArray.splice(cnt1, 1);
}else{
for(var cnt2 = 0; cnt2 < statementsArray[cnt1].formUnits.length; ){
if(apiutil.isEmptyArray(statementsArray[cnt1].formUnits[cnt2])){
// units is empty, then remove this units
statementsArray[cnt1].formUnits.splice(cnt2, 1);
}else{
for(var cnt3 = 0; cnt3 < statementsArray[cnt1].formUnits[cnt2].length; ){
if(!apiutil.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(apiutil.isEmptyArray(statementsArray[cnt1].formUnits[cnt2])){
// finally units is empty, then remove this units
statementsArray[cnt1].formUnits.splice(cnt2, 1);
}else{
++cnt2;
}
}
}
if(apiutil.isEmptyArray(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.
//
var rollbackStatementObjectToArray = function(statementsArray, statementObj, is_add_first_pos)
{
if('boolean' !== typeof 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(apiutil.isEmptyArray(statementsArray)){
// statementsArray is empty
// ---> push statement object.
statementsArray.push(statementObj);
}else{
var pos = (is_add_first_pos ? 0 : (statementsArray.length - 1));
var cnt;
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(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(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(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(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
//
var parseK2hr3Template = function(templString)
{
// parse template to statement areas
var resobj = parseK2hr3TemplateToStatements(templString);
if(apiutil.isEmptyArray(resobj)){
r3logger.dlog('parsed template string result is null.');
return null;
}
// parse each statement area to formula units
var formUnits;
for(var cnt = 0; !apiutil.isEmptyArray(resobj) && cnt < resobj.length; ++cnt){
if(!apiutil.isSafeEntity(resobj[cnt])){
// why?
resobj.splice(cnt, 1);
if(0 === cnt){
cnt = -1;
}else{
--cnt;
}
continue;
}
if(resobj[cnt].isStatement){
// in statement area
formUnits = parseK2hr3TemplateForStatements(resobj[cnt].cvtString);
if(!isSafeFormulaUnits(formUnits)){
// empty sentence, so remove this element.
resobj.splice(cnt, 1);
if(0 === cnt){
cnt = -1;
}else{
--cnt;
}
continue;
}
}else{
// not statement area
formUnits = [[resobj[cnt].cvtString]];
}
resobj[cnt].formUnits = formUnits;
}
if(apiutil.isEmptyArray(resobj)){
r3logger.dlog('parsed template string result is null.');
return null;
}
//r3logger.dlog('parsed template string result is : ' + r3logger.dump(resobj));
return resobj;
};
//---------------------------------------------------------
// 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)
// },
// ...
// ]
//
var parseK2hr3TemplateToStatements = function(templString)
{
var resobj = new Array(0);
var oneobj = {};
if(!apiutil.isSafeString(templString)){
return null;
}
// parse
var tmpl_cvtstr = '';
var tmpl_origin = '';
var keyword = TEMPL_START_KW;
var escword = TEMPL_ESCAPE_START_KW;
var oescword = TEMPL_ESCAPE_END_KW; // not keyword's escape
var templ_area = false;
while(apiutil.isSafeString(templString) && 0 < templString.length){
// each
var key_pos = templString.indexOf(keyword); // '{{' or '}}'
var esc_pos = templString.indexOf(escword); // '{{{' or '}}}'
var oesc_pos = templString.indexOf(oescword); // '}}}' or '{{{'
if(-1 !== oesc_pos && (-1 === key_pos || oesc_pos < key_pos)){
// found not keyword's escaped words before keyword
tmpl_origin += templString.substr(0, oesc_pos + 3);
tmpl_cvtstr += templString.substr(0, oesc_pos + 2); // converts '{{{'('}}}') to '{{'('}}') and appends it to end of tmpl_cvtstr.
templString = templString.substr(oesc_pos + 3); // after key words('{{{' or '}}}')
}else{
if(-1 != esc_pos && esc_pos === key_pos){
// found escaped key words
tmpl_origin += templString.substr(0, esc_pos + 3);
tmpl_cvtstr += templString.substr(0, esc_pos + 2); // converts '{{{'('}}}') to '{{'('}}') and appends it to end of tmpl_cvtstr.
templString = templString.substr(esc_pos + 3); // after key words('{{{' or '}}}')
}else if(-1 != key_pos){
// found key words
oneobj = {};
if(templ_area){
tmpl_origin += templString.substr(0, key_pos + 2); // original string with '}}'
tmpl_cvtstr += templString.substr(0, key_pos); // converted string without '}}'
// make object
oneobj.isStatement = true;
oneobj.origString = tmpl_origin;
oneobj.cvtString = tmpl_cvtstr.trim(); // trimmed string
oneobj.isReplication= false;
// set next
templ_area = false;
keyword = TEMPL_START_KW;
escword = TEMPL_ESCAPE_START_KW;
oescword = TEMPL_ESCAPE_END_KW;
tmpl_origin = '';
tmpl_cvtstr = '';
templString = templString.substr(key_pos + 2); // after key words('{{')
}else{
tmpl_origin += templString.substr(0, key_pos); // original string without '{{'
tmpl_cvtstr += templString.substr(0, key_pos); // converted string without '{{'
// make object
oneobj.isStatement = false;
oneobj.origString = tmpl_origin;
oneobj.cvtString = tmpl_cvtstr; // not trimmed string
oneobj.isReplication= false;
// 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 = '';
templString = templString.substr(key_pos + 2); // after key words('}}')
}
// add
if(apiutil.isSafeString(oneobj.origString)){
resobj.push(oneobj);
}
}else{
// not found keywords
oneobj = {};
tmpl_origin += templString; // add rest string to original string
tmpl_cvtstr += templString; // add rest string to converted string
// only make object
if(templ_area){
oneobj.isStatement = true;
oneobj.origString = tmpl_origin;
oneobj.cvtString = tmpl_cvtstr.trim(); // trimmed string
}else{
oneobj.isStatement = false;
oneobj.origString = tmpl_origin;
oneobj.cvtString = tmpl_cvtstr; // not trimmed string
}
oneobj.isReplication = false;
// add
if(apiutil.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.
//
var parseK2hr3TemplateForStatements = function(target, is_print_statement)
{
if(!apiutil.isSafeString(target)){
return null;
}
if('boolean' !== typeof is_print_statement){
is_print_statement = false;
}
var mainres = new Array(0);
var subres = new Array(0);
var one_part = '';
// check comment/print line at first
if(0 === target.indexOf(TEMPL_COMMENT_KW)){
// found comment keyword at first character position
one_part = target.substr(1).trim();
subres.push(TEMPL_COMMENT_KW);
if(apiutil.isSafeString(one_part)){
subres.push(one_part);
}
mainres.push(subres);
return mainres;
}else if(!is_print_statement && 0 === target.indexOf(TEMPL_PRINT_KW)){
// found print keyword at first character position
one_part = target.substr(1).trim();
// reentrant for analyzing after statement string
mainres = parseK2hr3TemplateForStatements(one_part, true);
if(apiutil.isEmptyArray(mainres)){
// mainres array is empty, then make static for print(maybe this is error at assembling or executing)
subres.push(TEMPL_PRINT_KW);
mainres = new Array(0);
mainres.push(subres);
}else if(apiutil.isEmptyArray(mainres[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[0].unshift(TEMPL_PRINT_KW);
}
return mainres;
}
// parse to statement string
var is_squate = false;
var is_dquate = false;
var is_escape = false;
for(var cnt = 0; cnt < target.length; ++cnt){
// check ';', '\'', '\"', '\\', '\s'
if(TEMPL_SEMICOLON_KW === target[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 = new Array(0);
}
}else if(TEMPL_SINGLE_QUOTE_KW === target[cnt]){ // '\''
if(is_escape){
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
one_part += target[cnt];
}else if(is_squate){
is_squate = false;
one_part += target[cnt];
subres.push(one_part); // finish one word
one_part = '';
}else if(is_dquate){
// nothing to do...
one_part += target[cnt];
}else{
is_squate = true;
if(0 < one_part.length){
subres.push(one_part); // finish one word
}
one_part = target[cnt];
}
}else if(TEMPL_DOUBLE_QUOTE_KW === target[cnt]){ // '\"'
if(is_escape){
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
one_part += target[cnt];
}else if(is_dquate){
is_dquate = false;
one_part += target[cnt];
subres.push(one_part); // finish one word
one_part = '';
}else if(is_squate){
// nothing to do...
one_part += target[cnt];
}else{
is_dquate = true;
if(0 < one_part.length){
subres.push(one_part); // finish one word
}
one_part = target[cnt];
}
}else if(TEMPL_ESCAPE_KW === target[cnt]){ // '\\'
if(is_escape){
is_escape = false;
one_part += TEMPL_ESCAPE_KW;
one_part += target[cnt];
}else{
is_escape = true;
}
}else if(' ' === target[cnt] || '\t' === target[cnt] || '\r' === target[cnt] || '\n' === target[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 += target[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 += target[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)
mainres = parseK2hr3TemplateStatementToFomulaUnits(mainres);
return mainres;
};
//---------------------------------------------------------
// 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
// ...
// ]
// ]
//
var parseK2hr3TemplateStatementToFomulaUnits = function(mainres)
{
if(apiutil.isEmptyArray(mainres)){
return mainres;
}
for(var cnt = 0; cnt < mainres.length; ++cnt){
if(apiutil.isEmptyArray(mainres[cnt])){
// why?
mainres.splice(cnt, 1);
if(0 === cnt){
cnt = -1;
}else{
--cnt;
}
continue;
}
// parse subres to some units
var subres = mainres[cnt];
for(var cnt2 = 0; cnt2 < subres.length; ++cnt2){
// parse string to minimum unit array
var subres_array = parseK2hr3TemplateStatementToMinimumUnits(subres[cnt2]);
if(apiutil.isEmptyArray(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(var 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(!isSafeFormulaUnitsArray(subres) || apiutil.isEmptyArray(subres)){
// mainres[cnt] has empty subres array, then remove cnt position array.
mainres.splice(cnt, 1);
if(0 === cnt){
cnt = -1;
}else{
--cnt;
}
}
}
// [NOTE]
// if units array(subres) is empty, it is removed from mainres.
// if there is no units in mainres, mainres is empty array.
//
return mainres;
};
//---------------------------------------------------------
// 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...)
// ...
// ]
//
var parseK2hr3TemplateStatementToMinimumUnits = function(target)
{
if(!apiutil.isSafeString(target)){
return null;
}
var resarr = new Array(0);
if(TEMPL_SINGLE_QUOTE_KW === target[0] || TEMPL_DOUBLE_QUOTE_KW === target[0]){
// target is '...' or "..." string, then this can not parse.
resarr.push(target);
return resarr;
}
var one_part = '';
for(var cnt = 0; cnt < target.length; ++cnt){
if(TEMPL_VALUESEP_KW === target[cnt]){ // '%' (== TEMPL_REM_KW)
// [NOTE]
// Space characters are already parsed before calling this function.
//
if(target.length <= (cnt + 1)){
// target[cnt + 1] === \s or null, then target[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{
var end_percent_pos = target.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 target[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 += target.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 === target[cnt]){ // '['
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
resarr.push(TEMPL_SQUARE_START_KW);
}else if(TEMPL_SQUARE_END_KW === target[cnt]){ // ']'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
resarr.push(TEMPL_SQUARE_END_KW);
}else if(TEMPL_CURLY_START_KW === target[cnt]){ // '{'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
resarr.push(TEMPL_CURLY_START_KW);
}else if(TEMPL_CURLY_END_KW === target[cnt]){ // '}'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
resarr.push(TEMPL_CURLY_END_KW);
}else if(TEMPL_MUL_KW === target[cnt]){ // '*'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
resarr.push(TEMPL_MUL_KW);
}else if(TEMPL_DIV_KW === target[cnt]){ // '/'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
resarr.push(TEMPL_DIV_KW);
}else if(TEMPL_NOT_KW === target[cnt]){ // '!'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_SET_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_NOTEQ_KW); // '!='
}else{
resarr.push(TEMPL_NOT_KW); // '!'
}
}else if(TEMPL_SET_KW === target[cnt]){ // '='
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_SET_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_EQUAL_KW); // '=='
}else{
resarr.push(TEMPL_SET_KW); // '='
}
}else if(TEMPL_ADD_KW === target[cnt]){ // '+'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_ADD_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_INC_KW); // '++'
}else{
resarr.push(TEMPL_ADD_KW); // '+'
}
}else if(TEMPL_SUB_KW === target[cnt]){ // '-'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_SUB_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_DEC_KW); // '--'
}else{
resarr.push(TEMPL_SUB_KW); // '-'
}
}else if(TEMPL_AMP_KW === target[cnt]){ // '&'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_AMP_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_AND_KW); // '&&'
}else{
resarr.push(TEMPL_AMP_KW); // '&'
}
}else if(TEMPL_VARTBAR_KW === target[cnt]){ // '|'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_VARTBAR_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_OR_KW); // '||'
}else{
resarr.push(TEMPL_VARTBAR_KW); // '|'
}
}else if(TEMPL_LESS_KW === target[cnt]){ // '<'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_SET_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_LESSEQ_KW); // '<='
}else if((cnt + 1) < target.length && TEMPL_LESS_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_LSHIFT_KW); // '<<'
}else{
resarr.push(TEMPL_LESS_KW); // '<'
}
}else if(TEMPL_GREAT_KW === target[cnt]){ // '>'
if(0 !== one_part.length){
resarr.push(one_part);
one_part= '';
}
if((cnt + 1) < target.length && TEMPL_SET_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_GREATEQ_KW); // '>='
}else if((cnt + 1) < target.length && TEMPL_GREAT_KW === target[cnt + 1]){
++cnt;
resarr.push(TEMPL_RSHIFT_KW); // '>>'
}else{
resarr.push(TEMPL_GREAT_KW); // '>'
}
}else{
one_part += target[cnt];
}
}
// rest
if(0 !== one_part.length){
resarr.push(one_part);
}
return resarr;
};
//---------------------------------------------------------
// Execute Result Class for K2HR3 Template Class
//---------------------------------------------------------
var K2hr3TemplateResult = (function()
{
var K2hr3TemplateResult = function(result)
{
if(!(this instanceof K2hr3TemplateResult)){
return new K2hr3TemplateResult(result);
}
// private variables(do not use directly)
this._result = ('boolean' === typeof result) ? result : false; // result of all
this._templString = ''; // result string value
this._cond = false; // result boolean value
this._lastvalue = null; // last value object which is any type value
this._isbreak = false; // if break is called, true
this._iscontinue = false; // if continue is called, true
this._varNameArray = null; // variable name array
};
var proto = K2hr3TemplateResult.prototype;
// access
proto.result = function()
{
return this._result;
};
proto.isSuccess = function()
{
return this._result;
};
proto.isFailure = function()
{
return !this._result;
};
proto.getString = function()
{
return this._templString;
};
proto.getCondition = function()
{
return this._cond;
};
proto.getLastValue = function()
{
return this._lastvalue;
};
proto.getVariableNames = function()
{
return this._varNameArray;
};
proto.isLoopControlFlags = function()
{
return (this._isbreak || this._iscontinue);
};
proto.isBreak = function()
{
return this._isbreak;
};
proto.isContinue = function()
{
return this._iscontinue;
};
// set
proto.init = function(result)
{
this._result = ('boolean' === typeof result) ? result : false; // result of all
this._templString = ''; // result string value
this._cond = false; // result boolean value
this._lastvalue = null; // result value object which is any type value
this._isbreak = false; // if break is called, true
this._iscontinue = false; // if continue is called, true
this._varNameArray = null; // variable name array
};
proto.setError = function(errstr)
{
this._result = false; // result is false
this._templString += ' --> ' + apiutil.getSafeString(errstr);
this._cond = false;
this._lastvalue = apiutil.getSafeString(errstr);
};
proto.addTemplString = function(str)
{
this._templString += apiutil.getSafeString(str);
this.setLastString(str);
};
proto.mergeTemplString = function(other)
{
if(!(other instanceof K2hr3TemplateResult)){
return;
}
this.addTemplString(other._templString);
this.setLastString(other._templString);
};
proto.setLastString = function(str)
{
this._cond = apiutil.isSafeString(str);
this._lastvalue = apiutil.getSafeString(str);
};
proto.setLastValue = function(value)
{
// check value type
if(null === value){ // null ---> condition = false
this._cond = false;
this._lastvalue = null;
}else if('boolean' === typeof value){ // boolean ---> condition = true/false
this._cond = value;
this._lastvalue = value;
}else if(apiutil.isSafeString(value) || '' === value){ // string ---> condition = true/false
this._cond = apiutil.isSafeString(value);
this.setLastString(value);
}else if(!isNaN(value)){ // number ---> condition = true/false
this._cond = (0 !== parseInt(value));
this._lastvalue = value;
}else{ // unknown ---> condition = false
if(value){
this._cond = true;
}else{
this._cond = false;
}
this._lastvalue = value; // unknown value
}
};
proto.setVariableNames = function()
{
var args = Array.prototype.slice.call(arguments, 0);
if(apiutil.isEmptyArray(args)){
this._varNameArray = null;
return;
}
for(var cnt = 0; cnt < args.length; ){
if(null === args[cnt] || ('boolean' === typeof args[cnt]) || (isNaN(args[cnt]) && !apiutil.isSafeString(args[cnt]))){
// cut not string member
args.splice(cnt, 1);
}else{
++cnt;
}
}
if(apiutil.isEmptyArray(args)){
this._varNameArray = null;
}else{
this._varNameArray = args;
}
};
proto.setBreak = function()
{
this._isbreak = true;
};
proto.clearBreak = function()
{
this._isbreak = false;
};
proto.setContinue = function()
{
this._iscontinue = true;
};
proto.clearContinue = function()
{
this._iscontinue = false;
};
proto.clearLoopControlFlags = function()
{
this.clearBreak();
this.clearContinue();
};
proto.merge = function(other)
{
if(!(other instanceof K2hr3TemplateResult)){
return;
}
this._result = (this._result && other.result()); // and
this._templString += other.getString(); // adding other
this._cond = other.getCondition(); // other
this._lastvalue = other.getLastValue(); // other
this._isbreak = (this._isbreak || other.isBreak()); // or
this._iscontinue = (this._iscontinue || other.isContinue()); // or
this._varNameArray = other._varNameArray; // other
};
proto.mergeStop = function(other)
{
if(!(other instanceof K2hr3TemplateResult)){
return;
}
this._result = (this._result && other.result()); // and
this._isbreak = (this._isbreak || other.isBreak()); // or
this._iscontinue = (this._iscontinue || other.isContinue()); // or
};
proto.insert = function(other)
{
if(!(other instanceof K2hr3TemplateResult)){
return;
}
this._result = (this._result && other.result()); // and
this._templString = other.getString() + this._templString; // inserting other
this._cond = other.getCondition(); // other
this._lastvalue = other.getLastValue(); // other
this._isbreak = (this._isbreak || other.isBreak()); // or
this._iscontinue = (this._iscontinue || other.isContinue()); // or
this._varNameArray = other._varNameArray; // other
};
proto.insertPrint = function(other)
{
if(!(other instanceof K2hr3TemplateResult)){
return;
}
this._result = (this._result && other.result()); // and
this._templString = (undefined === other.getLastValue() || null === other.getLastValue() ? '' : other.getLastValue().toString()) + this._templString; // inserting other last value
this._cond = other.getCondition(); // other
this._lastvalue = other.getLastValue(); // other
this._isbreak = (this._isbreak || other.isBreak()); // or
this._iscontinue = (this._iscontinue || other.isContinue()); // or
this._varNameArray = other._varNameArray; // other
};
return K2hr3TemplateResult;
})();
//---------------------------------------------------------
// K2HR3 Template Class : Common Variables
//---------------------------------------------------------
//
// Static Variables
//
const K2HR3TEMPL_ERROR_MSG_MAXLENGTH = (128 - 3); // 3 is margin "..."
//
// Class type string
//
const TEMPLATECLASS_TYPE_BASE = 'template:base';
const STATEMENTCLASS_TYPE_BASE = 'statement:base';
const STATEMENTCLASS_TYPE_STATIC = 'statement:static';
const STATEMENTCLASS_TYPE_COMMENT = 'statement:comment';
const STATEMENTCLASS_TYPE_PRINT = 'statement:print';
const FORMULACLASS_TYPE_BASE = 'formula:base';
const FORMULACLASS_TYPE_VARIABLE = 'formula:variable';
const FORMULACLASS_TYPE_CALCULATE = 'formula:calculate';
const FORMULACLASS_TYPE_CONDITION = 'formula:condition';
const FORMULACLASS_TYPE_SYNTAX = 'formula:syntax';
//
// These type is used by isPossibleResultType method parameter.
//
// [NOTE]
// If you get true from isPossibleResultType method with one of following
// symbol, but it is only possibility and you get another type result from
// execute method at runtime.
//
const TEMPLATE_RESULT_TYPE_NULL = 0;
const TEMPLATE_RESULT_TYPE_BOOLEAN = 1;
const TEMPLATE_RESULT_TYPE_NUMBER = 2;
const TEMPLATE_RESULT_TYPE_VARIABLE = 3;
const TEMPLATE_RESULT_TYPE_STRING = 4;
const TEMPLATE_RESULT_TYPE_STRICT_STRING = 5;
const TEMPLATE_RESULT_TYPE_NOSTATIC = 6;
const TEMPLATE_RESULT_TYPE_ANYVALUE = 7;
//---------------------------------------------------------
// K2HR3 Template Class : Common utility - class Inherits
//---------------------------------------------------------
var inherits = function(childClass, parentClass)
{
Object.setPrototypeOf(childClass.prototype, parentClass.prototype);
};
//---------------------------------------------------------
// K2HR3 Template Class : Base Class
//---------------------------------------------------------
//
// Constructor
//
var BaseTemplateObject = function(type)
{
if(!(this instanceof BaseTemplateObject)){
return new BaseTemplateObject(type);
}
this._type = apiutil.isSafeString(type) ? type : TEMPLATECLASS_TYPE_BASE; // type of class
this._error = null; // last error string when initializing/assembling
this._parentTempl = null; // if not null, this object is included from another object
this._nextTempl = null; // if not null, next object after this object is existed, it means the input statement has many statement.
this._resobj = new K2hr3TemplateResult(true); // result object for executing
};
//
// Methods
//
BaseTemplateObject.prototype.clear = function()
{
this._error = null;
this.clear