zpt
Version:
Zenon Page Templates - JS (ZPT-JS)
185 lines (145 loc) • 5.64 kB
JavaScript
/*
PathSegmentExpression class
*/
;
var context = require( '../../context.js' );
var ExpressionTokenizer = require( '../expressionTokenizer.js' );
var expressionsUtils = require( '../expressionsUtils.js' );
var ArrayExpression = require( './arrayExpression.js' );
var StringLiteral = require( './literals/stringLiteral.js' );
var NumericLiteral = require( './literals/numericLiteral.js' );
var BooleanLiteral = require( './literals/booleanLiteral.js' );
var ListExpression = require( './listExpression.js' );
var FunctionExpression = require( './functionExpression.js' );
var VariableExpression = require( './variableExpression.js' );
var IndirectionExpression = require( './indirectionExpression.js' );
var MethodExpression = require( './methodExpression.js' );
var PropertyExpression = require( './propertyExpression.js' );
var PathSegmentExpression = function( stringToApply, itemsToApply ) {
var string = stringToApply;
var items = itemsToApply;
var evaluate = function( scope ){
var token = items[ 0 ];
var result = token.evaluate( scope );
for ( var i = 1; i < items.length; i++ ) {
// Only last element can be null
if ( result == null ) {
throw 'Error evaluating "' + string + '": "' + token + '" is null';
}
token = items[ i ];
result = token.evaluate( scope, result );
}
return result;
};
var dependsOn = function( depsDataItem, scope ){
var firstSegmentDependsOn = expressionsUtils.buildDependsOnList( depsDataItem, scope, items[ 0 ] );
if ( firstSegmentDependsOn.length === 0 ){
return [];
} else if ( firstSegmentDependsOn.length > 1 ){
return firstSegmentDependsOn;
}
var temp = firstSegmentDependsOn[ 0 ];
var result = [ temp ];
for ( var i = 1; i < items.length; i++ ) {
var token = items[ i ];
var tokenDependsOn = token.dependsOn( temp );
if ( ! tokenDependsOn ){
break;
//return temp;
}
temp += tokenDependsOn;
result.push( temp );
}
return result;
};
var toString = function(){
return string;
};
return {
evaluate: evaluate,
dependsOn: dependsOn,
toString: toString
};
};
PathSegmentExpression.build = function( string ) {
var items = [];
// Blank expression evaluates to blank string
if ( string.length === 0 ) {
items.push(
StringLiteral.build( '' ) );
return items;
}
// Build first token
var path = new ExpressionTokenizer(
string,
context.getConf().pathSegmentDelimiter,
false );
var token = path.nextToken().trim();
items.push(
PathSegmentExpression.buildFirstPathToken( token ) );
// Traverse the path
while ( path.hasMoreTokens() ) {
token = path.nextToken().trim();
items.push(
PathSegmentExpression.buildNextPathToken( token ) );
}
return new PathSegmentExpression( string, items );
};
PathSegmentExpression.buildFirstPathToken = function( t ){
// Separate identifier from any array accessors
var arrayData = ArrayExpression.buildArrayData( t );
var arrayAccessor = arrayData? arrayData.arrayAccessor: undefined;
var token = arrayData? arrayData.token: t;
// First token must come from dictionary or be a literal
// First see if it's a string literal
var result = StringLiteral.build( token );
// If it's not, try to see if it's a number
if ( result === undefined ) {
result = NumericLiteral.build( token );
// Maybe it's a boolean literal
if ( result === undefined ) {
result = BooleanLiteral.build( token );
// A list?
if ( result === undefined ){
result = ListExpression.build( token );
// A function call?
if ( result === undefined ) {
result = FunctionExpression.build( token );
// Must be an object in scope
if ( result === undefined ) {
result = VariableExpression.build( token );
// Not recognized expression
if ( result === undefined ) {
throw 'Unknown expression: ' + token;
}
}
}
}
}
}
if ( arrayAccessor !== undefined ) {
result = ArrayExpression.build( result, arrayAccessor );
}
return result;
};
PathSegmentExpression.buildNextPathToken = function( t ){
// Separate identifier from any array accessors
var arrayData = ArrayExpression.buildArrayData( t );
var arrayAccessor = arrayData? arrayData.arrayAccessor: undefined;
var token = arrayData? arrayData.token: t;
// Test for indirection
var result = IndirectionExpression.build( token );
// A method call?
if ( result === undefined ) {
result = MethodExpression.build( token );
// A property
if ( result === undefined ) {
result = PropertyExpression.build( token );
}
}
if ( arrayAccessor !== undefined ) {
result = ArrayExpression.build( result, arrayAccessor );
}
return result;
};
module.exports = PathSegmentExpression;