public Node parse(string code, Options options) { // Program program, toString; //toString = String; //if (typeof code !== "string" && !(code instanceof String)) { // code = toString(code); //} source = code; index = 0; lineNumber = (source.Length > 0) ? 1 : 0; lineStart = 0; startIndex = index; startLineNumber = lineNumber; startLineStart = lineStart; length = source.Length; lookahead = null; state = new State() { allowIn = true, allowYield = true, labelSet = new List<string>(), inFunctionBody = false, inIteration = false, inSwitch = false, lastCommentStart = -1, curlyStack = new Stack<string>(), sourceType = "script" }; strict = false; extra = new Extra(); if (options != null) { extra.range = options.range; extra.loc = options.loc; extra.attachComment = options.attachComment; //if (extra.loc && options.source != null && options.source != undefined) { // extra.source = toString(options.source); //} if (options.tokens) { extra.tokens = new List<Token>(); } if (options.comment) { extra.comments = new List<Comment>(); } if (options.tolerant) { extra.errors = new List<Error>(); } if (extra.attachComment) { extra.range = true; extra.comments = new List<Comment>(); extra.bottomRightStack = new List<Token>(); extra.trailingComments = new List<Comment>(); extra.leadingComments = new List<Comment>(); } if (options.sourceType == "module") { // very restrictive condition for now state.sourceType = options.sourceType; strict = true; } } //try //{ var program = parseProgram(); //if (typeof extra.comments !== "undefined") { // program.comments = extra.comments; //} //if (typeof extra.tokens !== "undefined") { // filterTokenLocation(); // program.tokens = extra.tokens; //} //if (typeof extra.errors !== "undefined") { // program.errors = extra.errors; //} //} //catch (Exception e) //{ // throw e; //} //finally //{ // extra = new Extra(); //} return program; }
public Options parseParams(Token firstRestricted = null) { Options options; options = new Options { @params = new List<Node>(), defaultCount = 0, defaults = new List<Node>(), firstRestricted = firstRestricted }; expect("("); if (!match(")")) { //options.paramSet = //{ //} //; while (startIndex < length) { if (!parseParam(options)) { break; } expect(","); } } expect(")"); if (options.defaultCount == 0) { options.defaults = new List<Node>(); } return new Options() { @params = options.@params, defaults = options.defaults, stricted = options.stricted, firstRestricted = options.firstRestricted, message = options.message }; }
public List<Token> tokenize(string code, Options options) { //var toString; List<Token> tokens; //toString = String; //if (typeof code !== "string" && !(code instanceof String)) { // code = toString(code); //} source = code; index = 0; lineNumber = (source.Length > 0) ? 1 : 0; lineStart = 0; startIndex = index; startLineNumber = lineNumber; startLineStart = lineStart; length = source.Length; lookahead = null; state = new State() { allowIn = true, allowYield = true, labelSet = new List<string>(), inFunctionBody = false, inIteration = false, inSwitch = false, lastCommentStart = -1, curlyStack = new Stack<string>() }; extra = new Extra(); // Options matching. options = options ?? new Options(); // Of course we collect tokens here. options.tokens = true; extra.tokens = new List<Token>(); extra.tokenize = true; // The following two fields are necessary to compute the Regex tokens. extra.openParenToken = -1; extra.openCurlyToken = -1; extra.range = options.range; extra.loc = options.loc; if (options.comment) { extra.comments = new List<Comment>(); } if (options.tolerant) { extra.errors = new List<Error>(); } //try //{ peek(); if (lookahead.type == TokenType.EOF) { return extra.tokens; } lex(); while (lookahead.type != TokenType.EOF) { try { lex(); } catch (Error lexError) { if (extra.errors != null) { recordError(lexError); // We have to break on the first error // to avoid infinite loops. break; } else { throw lexError; } } } filterTokenLocation(); tokens = extra.tokens; //tokens.comments = extra.comments; //tokens.errors = extra.errors; //} //catch (Exception e) //{ // throw e; //} //finally //{ // extra = new Extra(); //} return tokens; }
public void validateParam(Options options, Node param, string name) { //var key = "$" + name; //if (strict) //{ // if (isRestrictedWord(name)) // { // options.stricted = param; // options.message = Messages.StrictParamName; // } // //if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { // // options.stricted = param; // // options.message = Messages.StrictParamDupe; // //} //} //else if (!options.firstRestricted) //{ // if (isRestrictedWord(name)) // { // options.firstRestricted = param; // options.message = Messages.StrictParamName; // } // else if (isStrictModeReservedWord(name)) // { // options.firstRestricted = param; // options.message = Messages.StrictReservedWord; // } // //} else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { // // options.stricted = param; // // options.message = Messages.StrictParamDupe; // //} //} //options.paramSet[key] = true; }
public bool parseParam(Options options) { Token token; Node param; List<Token> @params = new List<Token>(); int i; Node def = null; token = lookahead; if (token.value == "...") { param = parseRestElement(@params); validateParam(options, param.argument, param.argument.name); [email protected](param); options.defaults.Add(null); return false; } param = parsePatternWithDefault(@params, ""); for (i = 0; i < @params.Count; i++) { //validateParam(options, @params[i], "");//, @params[i].value); } if (param.type == Syntax.AssignmentPattern) { def = param.right; param = param.left; ++options.defaultCount; } [email protected](param); options.defaults.Add(def); return !match(")"); }
public List<Node> parseBindingList(string kind, Options options) { List<Node> list = new List<Node>(); do { list.Add(parseLexicalBinding(kind, options)); if (!match(",")) { break; } lex(); } while (startIndex < length); return list; }
public Node parseLexicalDeclaration(Options options) { string kind; List<Node> declarations; Node node = new Node(); kind = lex().value; assert(kind == "let" || kind == "const", "Lexical declaration must be either let or const"); declarations = parseBindingList(kind, options); consumeSemicolon(); return node.finishLexicalDeclaration(declarations, kind); }
public List<Node> parseVariableDeclarationList(Options options) { List<Node> list = new List<Node>(); do { list.Add(parseVariableDeclaration(new Options() { inFor = options.inFor })); if (!match(",")) { break; } lex(); } while (startIndex < length); return list; }
// ECMA-262 13.3.1 Let and Const Declarations public Node parseLexicalBinding(string kind, Options options) { Node init = null; Node id; Node node = new Node(); List<Token> @params = new List<Token>(); id = parsePattern(@params, kind); // ECMA-262 12.2.1 if (strict && id.type == Syntax.Identifier && isRestrictedWord(id.name)) { tolerateError(Messages.StrictVarName); } if (kind == "const") { if (!matchKeyword("in") && !matchContextualKeyword("of")) { expect("="); init = isolateCoverGrammar(parseAssignmentExpression); } } else if ((!options.inFor && id.type != Syntax.Identifier) || match("=")) { expect("="); init = isolateCoverGrammar(parseAssignmentExpression); } return node.finishVariableDeclarator(id, init); }
public Node parseArrowFunctionExpression(Options options, Node node) { bool previousStrict; bool previousAllowYield; List<Node> body; if (hasLineTerminator) { tolerateUnexpectedToken(lookahead); } expect("=>"); previousStrict = strict; previousAllowYield = state.allowYield; state.allowYield = true; body = new List<Node>() { parseConciseBody() }; if (strict && options.firstRestricted != null) { throwUnexpectedToken(options.firstRestricted, options.message); } if (strict && options.stricted != null) { tolerateUnexpectedToken(options.stricted, options.message); } strict = previousStrict; state.allowYield = previousAllowYield; return node.finishArrowFunctionExpression(options.@params, options.defaults, body, null); //body.type != Syntax.BlockStatement); }
public Node parseVariableDeclaration(Options options) { Node init = null; Node id, node = new Node(); List<Token> @params = new List<Token>(); id = parsePattern(@params, "var"); // ECMA-262 12.2.1 if (strict && isRestrictedWord(id.name)) { tolerateError(Messages.StrictVarName); } if (match("=")) { lex(); init = isolateCoverGrammar(parseAssignmentExpression); } else if (id.type != Syntax.Identifier && !options.inFor) { expect("="); } return node.finishVariableDeclarator(id, init); }
public Options reinterpretAsCoverFormalsList(Node expr) { int i, len; Node param; List<Node> @params; List<Node> defaults; int defaultCount; Options options; Token token; defaults = new List<Node>(); defaultCount = 0; @params = new List<Node>() { expr }; switch (expr.type) { case Syntax.Identifier: break; case PlaceHolders.ArrowParameterPlaceHolder: @params = expr.@params; break; default: return null; } options = new Options() { // paramSet= {} }; for (i = 0, len = @params.Count; i < len; i += 1) { param = @params[i]; switch (param.type) { case Syntax.AssignmentPattern: @params[i] = param.left; if (param.right.type == Syntax.YieldExpression) { if (param.right.argument != null) { throwUnexpectedToken(lookahead); } param.right.type = Syntax.Identifier; param.right.name = "yield"; param.right.argument = null; param.right.@delegate = null; } defaults.Add(param.right); ++defaultCount; checkPatternParam(options, param.left); break; default: checkPatternParam(options, param); @params[i] = param; defaults.Add(null); break; } } if (strict || !state.allowYield) { for (i = 0, len = @params.Count; i < len; i += 1) { param = @params[i]; if (param.type == Syntax.YieldExpression) { throwUnexpectedToken(lookahead); } } } if (options.message == Messages.StrictParamDupe) { token = strict ? options.stricted : options.firstRestricted; throwUnexpectedToken(token, options.message); } if (defaultCount == 0) { defaults = new List<Node>(); } return new Options() { @params = @params, defaults = defaults, stricted = options.stricted, firstRestricted = options.firstRestricted, message = options.message }; }
public void checkPatternParam(Options options, Node @param) { int i; switch (@param.type) { case Syntax.Identifier: validateParam(options, @param, @param.name); break; case Syntax.RestElement: checkPatternParam(options, @param.argument); break; case Syntax.AssignmentPattern: checkPatternParam(options, @param.left); break; case Syntax.ArrayPattern: for (i = 0; i < @param.elements.Count; i++) { if (@param.elements[i] != null) { checkPatternParam(options, param.elements[i]); } } break; case Syntax.YieldExpression: break; default: assert(param.type == Syntax.ObjectPattern, "Invalid type"); for (i = 0; i < param.properties.Count; i++) { checkPatternParam(options, param.properties[i].value); } break; } }
// ECMA-262 12.2.9 Template Literals public Node parseTemplateElement(Options option) { Node node; Token token; if (lookahead.type != TokenType.Template || (option.head && !lookahead.head)) { throwUnexpectedToken(); } node = new Node(); token = lex(); return node.finishTemplateElement(new Node() { raw = token.value }, token.tail); //.raw, cooked= token.value.cooked } }
// This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals, // it might be called at a position where there is in fact a short hand identifier pattern or a data property. // This can only be determined after we consumed up to the left parentheses. // // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller // is responsible to visit other options. public Node tryParseMethodDefinition(Token token, Node key, bool computed, Node node) { Node value; Options options; Node methodNode; Options @params; bool previousAllowYield = state.allowYield; if (token.type == TokenType.Identifier) { // check for `get` and `set`; if (token.value == "get" && lookaheadPropertyName()) { computed = match("["); key = parseObjectPropertyKey(); methodNode = new Node(); expect("("); expect(")"); state.allowYield = false; value = parsePropertyFunction(methodNode, new Options() { @params = new List<Node>(), defaults = new List<Node>(), stricted = null, firstRestricted = null, message = null }, false); state.allowYield = previousAllowYield; return node.finishProperty("get", key, computed, value, false, false); } else if (token.value == "set" && lookaheadPropertyName()) { computed = match("["); key = parseObjectPropertyKey(); methodNode = new Node(); expect("("); options = new Options() { @params = new List<Node>(), defaultCount = 0, defaults = new List<Node>(), firstRestricted = null, // paramSet = {} }; if (match(")")) { tolerateUnexpectedToken(lookahead); } else { state.allowYield = false; parseParam(options); state.allowYield = previousAllowYield; if (options.defaultCount == 0) { options.defaults = new List<Node>(); } } expect(")"); state.allowYield = false; value = parsePropertyFunction(methodNode, options, false); state.allowYield = previousAllowYield; return node.finishProperty("set", key, computed, value, false, false); } } else if (token.type == TokenType.Punctuator && token.value == "*" && lookaheadPropertyName()) { computed = match("["); key = parseObjectPropertyKey(); methodNode = new Node(); state.allowYield = true; @params = parseParams(); state.allowYield = previousAllowYield; state.allowYield = false; value = parsePropertyFunction(methodNode, @params, true); state.allowYield = previousAllowYield; return node.finishProperty("init", key, computed, value, true, false); } if (key != null && match("(")) { value = parsePropertyMethodFunction(); return node.finishProperty("init", key, computed, value, true, false); } // Not a MethodDefinition. return null; }
// ECMA-262 12.2.6 Object Initializer public Node parsePropertyFunction(Node node, Options paramInfo, bool isGenerator) { bool previousStrict; List<Node> body; isAssignmentTarget = isBindingElement = false; previousStrict = strict; body = new List<Node>() { isolateCoverGrammar(parseFunctionSourceElements) }; if (strict && paramInfo.firstRestricted != null) { tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message); } if (strict && paramInfo.stricted != null) { tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message); } strict = previousStrict; return node.finishFunctionExpression(null, paramInfo.@params, paramInfo.defaults, body, isGenerator); }