"use strict"; var Exception = require("../exception")["default"]; function LocationInfo(locInfo) { locInfo = locInfo || {}; this.firstLine = locInfo.first_line; this.firstColumn = locInfo.first_column; this.lastColumn = locInfo.last_column; this.lastLine = locInfo.last_line; } var AST = { ProgramNode: function(statements, strip, locInfo) { LocationInfo.call(this, locInfo); this.type = "program"; this.statements = statements; this.strip = strip; }, MustacheNode: function(rawParams, hash, open, strip, locInfo) { LocationInfo.call(this, locInfo); this.type = "mustache"; this.strip = strip; // Open may be a string parsed from the parser or a passed boolean flag if (open != null && open.charAt) { // Must use charAt to support IE pre-10 var escapeFlag = open.charAt(3) || open.charAt(2); this.escaped = escapeFlag !== '{' && escapeFlag !== '&'; } else { this.escaped = !!open; } if (rawParams instanceof AST.SexprNode) { this.sexpr = rawParams; } else { // Support old AST API this.sexpr = new AST.SexprNode(rawParams, hash); } // Support old AST API that stored this info in MustacheNode this.id = this.sexpr.id; this.params = this.sexpr.params; this.hash = this.sexpr.hash; this.eligibleHelper = this.sexpr.eligibleHelper; this.isHelper = this.sexpr.isHelper; }, SexprNode: function(rawParams, hash, locInfo) { LocationInfo.call(this, locInfo); this.type = "sexpr"; this.hash = hash; var id = this.id = rawParams[0]; var params = this.params = rawParams.slice(1); // a mustache is definitely a helper if: // * it is an eligible helper, and // * it has at least one parameter or hash segment this.isHelper = !!(params.length || hash); // a mustache is an eligible helper if: // * its id is simple (a single part, not `this` or `..`) this.eligibleHelper = this.isHelper || id.isSimple; // if a mustache is an eligible helper but not a definite // helper, it is ambiguous, and will be resolved in a later // pass or at runtime. }, PartialNode: function(partialName, context, hash, strip, locInfo) { LocationInfo.call(this, locInfo); this.type = "partial"; this.partialName = partialName; this.context = context; this.hash = hash; this.strip = strip; this.strip.inlineStandalone = true; }, BlockNode: function(mustache, program, inverse, strip, locInfo) { LocationInfo.call(this, locInfo); this.type = 'block'; this.mustache = mustache; this.program = program; this.inverse = inverse; this.strip = strip; if (inverse && !program) { this.isInverse = true; } }, RawBlockNode: function(mustache, content, close, locInfo) { LocationInfo.call(this, locInfo); if (mustache.sexpr.id.original !== close) { throw new Exception(mustache.sexpr.id.original + " doesn't match " + close, this); } content = new AST.ContentNode(content, locInfo); this.type = 'block'; this.mustache = mustache; this.program = new AST.ProgramNode([content], {}, locInfo); }, ContentNode: function(string, locInfo) { LocationInfo.call(this, locInfo); this.type = "content"; this.original = this.string = string; }, HashNode: function(pairs, locInfo) { LocationInfo.call(this, locInfo); this.type = "hash"; this.pairs = pairs; }, IdNode: function(parts, locInfo) { LocationInfo.call(this, locInfo); this.type = "ID"; var original = "", dig = [], depth = 0, depthString = ''; for(var i=0,l=parts.length; i 0) { throw new Exception("Invalid path: " + original, this); } else if (part === "..") { depth++; depthString += '../'; } else { this.isScoped = true; } } else { dig.push(part); } } this.original = original; this.parts = dig; this.string = dig.join('.'); this.depth = depth; this.idName = depthString + this.string; // an ID is simple if it only has one part, and that part is not // `..` or `this`. this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; this.stringModeValue = this.string; }, PartialNameNode: function(name, locInfo) { LocationInfo.call(this, locInfo); this.type = "PARTIAL_NAME"; this.name = name.original; }, DataNode: function(id, locInfo) { LocationInfo.call(this, locInfo); this.type = "DATA"; this.id = id; this.stringModeValue = id.stringModeValue; this.idName = '@' + id.stringModeValue; }, StringNode: function(string, locInfo) { LocationInfo.call(this, locInfo); this.type = "STRING"; this.original = this.string = this.stringModeValue = string; }, NumberNode: function(number, locInfo) { LocationInfo.call(this, locInfo); this.type = "NUMBER"; this.original = this.number = number; this.stringModeValue = Number(number); }, BooleanNode: function(bool, locInfo) { LocationInfo.call(this, locInfo); this.type = "BOOLEAN"; this.bool = bool; this.stringModeValue = bool === "true"; }, CommentNode: function(comment, locInfo) { LocationInfo.call(this, locInfo); this.type = "comment"; this.comment = comment; this.strip = { inlineStandalone: true }; } }; // Must be exported as an object rather than the root of the module as the jison lexer // most modify the object to operate properly. exports["default"] = AST;