void parseTemplateArgument() { currentTokenKind = TokenKind.VALUE; Token name = tokens[cursor += 1]; if (name.type != TT.IDENTIFIER) { Jolly.unexpected(name); } AST_Template node = new AST_Template(name.location); AST_Node typeFrom = null; if (prevTokenKind == TokenKind.VALUE) { if (defineMode != DefineMode.TEMPLATE) { throw Jolly.unexpected(token); } typeFrom = values.Pop(); Debug.Assert(typeFrom != null); } DefineMode inferrableDefineMode = (DefineMode.TEMPLATE | DefineMode.ARGUMENT) & defineMode; if (canDefine && inferrableDefineMode != 0) { if (scope.template.TryGetValue(name.text, out node.item)) { if ((node.item.canBeInferredBy & defineMode) == DefineMode.TEMPLATE) { throw Jolly.addError(name.location, "Trying to redefine template argument ${0}".fill(name.text)); } node.item.canBeInferredBy |= inferrableDefineMode; } else { scope.template.Add(name.text, node.item = new TemplateItem { canBeInferredBy = inferrableDefineMode, constantValue = typeFrom, location = node.location, defineIndex = defineIndex++, }); } } else { node.name = name.text; } values.Push(node); ast.Add(node); }
AST_Template[] parseTemplate(SymbolTable theScope) { var less = tokens[cursor + 1]; if (less.type != TT.LESS) { return(null); } cursor += 2; var result = new ExpressionParser(parseData, TT.GREATER, theScope, DefineMode.TEMPLATE, end) .parse(false) .getValue(); if (result == null) { return(null); } switch (result.nodeType) { case NT.TUPLE: var tuple = (AST_Tuple)result; var returns = new AST_Template[tuple.values.Count]; tuple.values.forEach((v, i) => { if (v.nodeType != NT.TEMPLATE_NAME) { throw Jolly.unexpected(v); } returns[i] = (AST_Template)v; }); return(returns); case NT.TEMPLATE_NAME: return(new AST_Template[] { (AST_Template)result }); default: throw Jolly.unexpected(result); } }