diff --git a/javascript/extractor/src/com/semmle/js/ast/SourceLocation.java b/javascript/extractor/src/com/semmle/js/ast/SourceLocation.java index 2ef727051f5..3a8475c3a5e 100644 --- a/javascript/extractor/src/com/semmle/js/ast/SourceLocation.java +++ b/javascript/extractor/src/com/semmle/js/ast/SourceLocation.java @@ -21,6 +21,10 @@ public class SourceLocation { this(source, start, null); } + public SourceLocation(SourceLocation that) { + this(that.source, that.start, that.end); + } + /** * The source code contained in this location. */ diff --git a/javascript/extractor/src/com/semmle/js/ast/regexp/Error.java b/javascript/extractor/src/com/semmle/js/ast/regexp/Error.java index b5f56e3d4f6..66977309781 100644 --- a/javascript/extractor/src/com/semmle/js/ast/regexp/Error.java +++ b/javascript/extractor/src/com/semmle/js/ast/regexp/Error.java @@ -7,6 +7,20 @@ import com.semmle.js.ast.SourceLocation; * An error encountered while parsing a regular expression. */ public class Error extends SourceElement { + public static final int UNEXPECTED_EOS = 0; + public static final int UNEXPECTED_CHARACTER = 1; + public static final int EXPECTED_DIGIT = 2; + public static final int EXPECTED_HEX_DIGIT = 3; + public static final int EXPECTED_CONTROL_LETTER = 4; + public static final int EXPECTED_CLOSING_PAREN = 5; + public static final int EXPECTED_CLOSING_BRACE = 6; + public static final int EXPECTED_EOS = 7; + public static final int OCTAL_ESCAPE = 8; + public static final int INVALID_BACKREF = 9; + public static final int EXPECTED_RBRACKET = 10; + public static final int EXPECTED_IDENTIFIER = 11; + public static final int EXPECTED_CLOSING_ANGLE = 12; + private final int code; public Error(SourceLocation loc, Number code) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 9116a71dc0a..bca6014f66c 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -39,7 +39,7 @@ public class Main { * such a way that it may produce different tuples for the same file under the same * {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2018-10-16"; + public static final String EXTRACTOR_VERSION = "2018-11-12"; public static final Pattern NEWLINE = Pattern.compile("\n"); diff --git a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java index a4fcd786758..da5c351d23c 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java @@ -3,12 +3,10 @@ package com.semmle.js.parser; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; - -import org.mozilla.javascript.NativeArray; -import org.mozilla.javascript.NativeObject; -import org.mozilla.javascript.Undefined; +import java.util.Set; import com.semmle.js.ast.Comment; import com.semmle.js.ast.Position; @@ -33,71 +31,38 @@ import com.semmle.js.ast.jsdoc.TypeApplication; import com.semmle.js.ast.jsdoc.UndefinedLiteral; import com.semmle.js.ast.jsdoc.UnionType; import com.semmle.js.ast.jsdoc.VoidLiteral; +import com.semmle.util.data.Pair; import com.semmle.util.exception.Exceptions; /** - * A wrapper for invoking doctrine through Rhino. + * A Java port of doctrine. */ -public class JSDocParser extends ScriptLoader { - public JSDocParser() { - super("/doctrine.js"); - } +public class JSDocParser { + private String source; /** * Parse the given string as a JSDoc comment. */ public JSDocComment parse(Comment comment) { - NativeObject doctrine = (NativeObject)readGlobal("doctrine"); - NativeObject opts = mkObject("unwrap", true, "recoverable", true, - "sloppy", true, "lineNumbers", true); - NativeObject res = (NativeObject)callMethod(doctrine, "parse", comment.getText().substring(1), opts); - return decodeJSDocComment(res, comment); - } + source = comment.getText().substring(1); + JSDocTagParser p = new JSDocTagParser(); + Pair> r = p.new TagParser(null).parse(source); + List tags = new ArrayList<>(); + for (JSDocTagParser.Tag tag : r.snd()) { + String title = tag.title; + String description = tag.description; + String name = tag.name; + int startLine = tag.startLine; + int startColumn = tag.startColumn; - private JSDocComment decodeJSDocComment(NativeObject obj, Comment comment) { - String description = (String)readProperty(obj, "description"); - NativeArray tags = (NativeArray)readProperty(obj, "tags"); - return new JSDocComment(comment, description, decodeJSDocTags(tags, comment)); - } - - private List decodeJSDocTags(NativeArray tags, Comment comment) { - String src = comment.getText().substring(1); - List result = new ArrayList(tags.size()); - for (Object tag : tags) { - String title = readStringProperty(tag, "title"); - String description = readStringProperty(tag, "description"); - String name = readStringProperty(tag, "name"); - int startLine = readIntProperty(tag, "startLine"); - int startColumn = readIntProperty(tag, "startColumn"); - - Object type = readProperty(tag, "type"); - JSDocTypeExpression jsdocType; - if (type == null || type == Undefined.instance) { - jsdocType = null; - } else { - JSObjectDecoder typeDecoder = new JSObjectDecoder(src, this, "com.semmle.js.ast.jsdoc", spec); - try { - jsdocType = typeDecoder.decodeObject((NativeObject)type); - } catch (ParseError e) { - Exceptions.ignore(e, "Exceptions in JSDoc should always be ignored."); - jsdocType = null; - } - } - - NativeArray err = (NativeArray)readProperty(tag, "errors"); - List errors = new ArrayList(); - if (err != null) { - for (Object msg : err) { - errors.add(String.valueOf(msg)); - } - } + JSDocTypeExpression jsdocType = tag.type; int realStartLine = comment.getLoc().getStart().getLine() + startLine; int realStartColumn = (startLine == 0 ? comment.getLoc().getStart().getColumn() + 3 : 0) + startColumn; - SourceLocation loc = new SourceLocation(src, new Position(realStartLine, realStartColumn, -1), new Position(realStartLine, realStartColumn + 1 + title.length(), -1)); - result.add(new JSDocTag(loc, title, description, name, jsdocType, errors)); + SourceLocation loc = new SourceLocation(source, new Position(realStartLine, realStartColumn, -1), new Position(realStartLine, realStartColumn + 1 + title.length(), -1)); + tags.add(new JSDocTag(loc, title, description, name, jsdocType, tag.errors)); } - return result; + return new JSDocComment(comment, r.fst(), tags); } /** @@ -123,4 +88,1705 @@ public class JSDocParser extends ScriptLoader { spec.put(UnionType.class, Arrays.asList("elements")); spec.put(VoidLiteral.class, Arrays.asList()); } + + private static String sliceSource(String source, int index, int last) { + if (index >= source.length()) + return ""; + if (last > source.length()) + last = source.length(); + return source.substring(index, last); + } + + private static boolean isLineTerminator(int ch) { + return ch == '\n' || ch == '\r' || ch == '\u2028' || ch == '\u2029'; + } + + private static boolean isWhiteSpace(char ch) { + return Character.isWhitespace(ch) && !isLineTerminator(ch) || + ch == '\u00a0'; + } + + private static boolean isDecimalDigit(char ch) { + return "0123456789".indexOf(ch) >= 0; + } + + private static boolean isHexDigit(char ch) { + return "0123456789abcdefABCDEF".indexOf(ch) >= 0; + } + + private static boolean isOctalDigit(char ch) { + return "01234567".indexOf(ch) >= 0; + } + + private static boolean isASCIIAlphanumeric(char ch) { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'); + } + + private static boolean isIdentifierStart(char ch) { + return (ch == '\\') || Character.isJavaIdentifierStart(ch); + } + + private static boolean isIdentifierPart(char ch) { + return (ch == '\\') || Character.isJavaIdentifierPart(ch); + } + + private static boolean isTypeName(char ch) { + return "><(){}[],:*|?!=".indexOf(ch) == -1 && !isWhiteSpace(ch) && !isLineTerminator(ch); + } + + private static boolean isParamTitle(String title) { + return title.equals("param") || title.equals("argument") || title.equals("arg"); + } + + private static boolean isProperty(String title) { + return title.equals("property") || title.equals("prop"); + } + + private static boolean isNameParameterRequired(String title) { + return isParamTitle(title) || isProperty(title) || + title.equals("alias") || title.equals("this") || title.equals("mixes") || title.equals("requires"); + } + + private static boolean isAllowedName(String title) { + return isNameParameterRequired(title) || title.equals("const") || title.equals("constant"); + } + + private static boolean isAllowedNested(String title) { + return isProperty(title) || isParamTitle(title); + } + + private static boolean isTypeParameterRequired(String title) { + return isParamTitle(title) || title.equals("define") || title.equals("enum") || + title.equals("implements") || title.equals("return") || + title.equals("this") || title.equals("type") || title.equals("typedef") || + title.equals("returns") || isProperty(title); + } + + // Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required + // This would require changes to 'parseType' + private static boolean isAllowedType(String title) { + return isTypeParameterRequired(title) || title.equals("throws") || title.equals("const") || title.equals("constant") || + title.equals("namespace") || title.equals("member") || title.equals("var") || title.equals("module") || + title.equals("constructor") || title.equals("class") || title.equals("extends") || title.equals("augments") || + title.equals("public") || title.equals("private") || title.equals("protected"); + } + + private static T throwError(String message) throws ParseError { + throw new ParseError(message, null); + } + + private static class TypeExpressionParser { + private enum Token { + ILLEGAL, // ILLEGAL + DOT, // . + DOT_LT, // .< + REST, // ... + LT, // < + GT, // > + LPAREN, // ( + RPAREN, // ) + LBRACE, // { + RBRACE, // } + LBRACK, // [ + RBRACK, // ] + COMMA, // , + COLON, // : + STAR, // * + PIPE, // | + QUESTION, // ? + BANG, // ! + EQUAL, // = + NAME, // name token + STRING, // string + NUMBER, // number + EOF + }; + + String source; + int length; + int previous, index; + Token token; + Object value; + + private class Context { + int _previous, _index; + Token _token; + Object _value; + + Context(int previous, int index, Token token, Object value) { + this._previous = previous; + this._index = index; + this._token = token; + this._value = value; + } + + void restore() { + previous = this._previous; + index = this._index; + token = this._token; + value = this._value; + } + } + + Context save() { + return new Context(previous, index, token, value); + } + + private SourceLocation loc() { + return new SourceLocation(pos()); + } + + private Position pos() { + return new Position(1, index+1, index); + } + + private T finishNode(T node) { + SourceLocation loc = node.getLoc(); + Position end = pos(); + loc.setSource(inputSubstring(loc.getStart().getOffset(), end.getOffset())); + loc.setEnd(end); + return node; + } + + private String inputSubstring(int start, int end) { + if (start >= source.length()) + return ""; + if (end > source.length()) + end = source.length(); + return source.substring(start, end); + } + + private int advance() { + if (index >= source.length()) + return -1; + return source.charAt(index++); + } + + private String scanHexEscape(char prefix) { + int i, len, ch, code = 0; + + len = (prefix == 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source.charAt(index))) { + ch = advance(); + code = code * 16 + "0123456789abcdef".indexOf(Character.toLowerCase(ch)); + } else { + return ""; + } + } + return new String(Character.toChars(code)); + } + + private Token scanString() throws ParseError { + StringBuilder str = new StringBuilder(); + int quote, ch, code, restore; //TODO review removal octal = false + String unescaped; + quote = source.charAt(index); + ++index; + + while (index < length) { + ch = advance(); + + if (ch == quote) { + quote = -1; + break; + } else if (ch == '\\') { + ch = advance(); + if (!isLineTerminator(ch)) { + switch (ch) { + case 'n': + str.append('\n'); + break; + case 'r': + str.append('\r'); + break; + case 't': + str.append('\t'); + break; + case 'u': + case 'x': + restore = index; + unescaped = scanHexEscape((char) ch); + if (!unescaped.isEmpty()) { + str.append(unescaped); + } else { + index = restore; + str.append((char) ch); + } + break; + case 'b': + str.append('\b'); + break; + case 'f': + str.append('\f'); + break; + case 'v': + str.append('\u000b'); + break; + + default: + if (isOctalDigit((char) ch)) { + code = "01234567".indexOf(ch); + + // \0 is not octal escape sequence + // Deprecating unused code. TODO review removal + //if (code != 0) { + // octal = true; + //} + + if (index < length && isOctalDigit(source.charAt(index))) { + //TODO Review Removal octal = true; + code = code * 8 + "01234567".indexOf(advance()); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ("0123".indexOf(ch) >= 0 && + index < length && + isOctalDigit(source.charAt(index))) { + code = code * 8 + "01234567".indexOf(advance()); + } + } + str.append(Character.toChars(code)); + } else { + str.append((char) ch); + } + break; + } + } else { + if (ch == '\r' && index < length && source.charAt(index) == '\n') { + ++index; + } + } + } else if (isLineTerminator(ch)) { + break; + } else { + str.append((char) ch); + } + } + + if (quote != -1) { + throwError("unexpected quote"); + } + + value = str.toString(); + return Token.STRING; + } + + private Token scanNumber() throws ParseError { + StringBuilder number = new StringBuilder(); + boolean isFloat = false; + char ch = '\0'; + + if (ch != '.') { + int next = advance(); + number.append((char)next); + ch = index < length ? source.charAt(index) : '\0'; + + if (next == '0') { + if (ch == 'x' || ch == 'X') { + number.append((char)advance()); + while (index < length) { + ch = source.charAt(index); + if (!isHexDigit(ch)) { + break; + } + number.append((char)advance()); + } + + if (number.length() <= 2) { + // only 0x + throwError("unexpected token"); + } + + if (index < length) { + ch = source.charAt(index); + if (isIdentifierStart(ch)) { + throwError("unexpected token"); + } + } + try { + value = Integer.parseInt(number.toString(), 16); + } catch (NumberFormatException nfe) { + Exceptions.ignore(nfe, "Precise exception content is unimportant"); + throwError("Invalid hexadecimal constant " + number); + } + return Token.NUMBER; + } + + if (isOctalDigit(ch)) { + number.append((char)advance()); + while (index < length) { + ch = source.charAt(index); + if (!isOctalDigit(ch)) { + break; + } + number.append((char)advance()); + } + + if (index < length) { + ch = source.charAt(index); + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError("unexpected token"); + } + } + try { + value = Integer.parseInt(number.toString(), 8); + } catch (NumberFormatException nfe) { + Exceptions.ignore(nfe, "Precise exception content is unimportant"); + throwError("Invalid octal constant " + number); + } + return Token.NUMBER; + } + + if (isDecimalDigit(ch)) { + throwError("unexpected token"); + } + } + + while (index < length) { + ch = source.charAt(index); + if (!isDecimalDigit(ch)) { + break; + } + number.append((char)advance()); + } + } + + if (ch == '.') { + isFloat = true; + number.append((char)advance()); + while (index < length) { + ch = source.charAt(index); + if (!isDecimalDigit(ch)) { + break; + } + number.append((char)advance()); + } + } + + if (ch == 'e' || ch == 'E') { + isFloat = true; + number.append((char)advance()); + + ch = index < length ? source.charAt(index) : '\0'; + if (ch == '+' || ch == '-') { + number.append((char)advance()); + } + + ch = index < length ? source.charAt(index) : '\0'; + if (isDecimalDigit(ch)) { + number.append((char)advance()); + while (index < length) { + ch = source.charAt(index); + if (!isDecimalDigit(ch)) { + break; + } + number.append((char)advance()); + } + } else { + throwError("unexpected token"); + } + } + + if (index < length) { + ch = source.charAt(index); + if (isIdentifierStart(ch)) { + throwError("unexpected token"); + } + } + + String num = number.toString(); + try { + if (isFloat) + value = Double.parseDouble(num); + else + value = Integer.parseInt(num); + } catch (NumberFormatException nfe) { + Exceptions.ignore(nfe, "Precise exception content is unimportant"); + throwError("Invalid numeric literal " + num); + } + return Token.NUMBER; + } + + private Token scanTypeName() { + char ch, ch2; + + value = new String(Character.toChars(advance())); + while (index < length && isTypeName(source.charAt(index))) { + ch = source.charAt(index); + if (ch == '.') { + if ((index + 1) < length) { + ch2 = source.charAt(index + 1); + if (ch2 == '<') { + break; + } + } + } + value += new String(Character.toChars(advance())); + } + return Token.NAME; + } + + private Token next() throws ParseError { + char ch; + + previous = index; + + while (index < length && isWhiteSpace(source.charAt(index))) { + advance(); + } + if (index >= length) { + token = Token.EOF; + return token; + } + + ch = source.charAt(index); + switch (ch) { + case '"': + token = scanString(); + return token; + + case ':': + advance(); + token = Token.COLON; + return token; + + case ',': + advance(); + token = Token.COMMA; + return token; + + case '(': + advance(); + token = Token.LPAREN; + return token; + + case ')': + advance(); + token = Token.RPAREN; + return token; + + case '[': + advance(); + token = Token.LBRACK; + return token; + + case ']': + advance(); + token = Token.RBRACK; + return token; + + case '{': + advance(); + token = Token.LBRACE; + return token; + + case '}': + advance(); + token = Token.RBRACE; + return token; + + case '.': + advance(); + if (index < length) { + ch = source.charAt(index); + if (ch == '<') { + advance(); + token = Token.DOT_LT; + return token; + } + + if (ch == '.' && index + 1 < length && source.charAt(index + 1) == '.') { + advance(); + advance(); + token = Token.REST; + return token; + } + + if (isDecimalDigit(ch)) { + token = scanNumber(); + return token; + } + } + token = Token.DOT; + return token; + + case '<': + advance(); + token = Token.LT; + return token; + + case '>': + advance(); + token = Token.GT; + return token; + + case '*': + advance(); + token = Token.STAR; + return token; + + case '|': + advance(); + token = Token.PIPE; + return token; + + case '?': + advance(); + token = Token.QUESTION; + return token; + + case '!': + advance(); + token = Token.BANG; + return token; + + case '=': + advance(); + token = Token.EQUAL; + return token; + + default: + if (isDecimalDigit(ch)) { + token = scanNumber(); + return token; + } + + // type string permits following case, + // + // namespace.module.MyClass + // + // this reduced 1 token TK_NAME + if (isTypeName(ch)) { + token = scanTypeName(); + return token; + } + + token = Token.ILLEGAL; + return token; + } + } + + private void consume(Token target, String text) throws ParseError { + if (token != target) + throwError(text == null ? "consumed token not matched" : text); + next(); + } + + private void consume(Token target) throws ParseError { + consume(target, null); + } + + private void expect(Token target) throws ParseError { + if (token != target) { + throwError("unexpected token"); + } + next(); + } + + // UnionType := '(' TypeUnionList ')' + // + // TypeUnionList := + // <> + // | NonemptyTypeUnionList + // + // NonemptyTypeUnionList := + // TypeExpression + // | TypeExpression '|' NonemptyTypeUnionList + private JSDocTypeExpression parseUnionType() throws ParseError { + SourceLocation loc = loc(); + List elements = new ArrayList<>(); + consume(Token.LPAREN, "UnionType should start with ("); + if (token != Token.RPAREN) { + while (true) { + elements.add(parseTypeExpression()); + if (token == Token.RPAREN) { + break; + } + expect(Token.PIPE); + } + } + consume(Token.RPAREN, "UnionType should end with )"); + return finishNode(new UnionType(loc, elements)); + } + + // ArrayType := '[' ElementTypeList ']' + // + // ElementTypeList := + // <> + // | TypeExpression + // | '...' TypeExpression + // | TypeExpression ',' ElementTypeList + private JSDocTypeExpression parseArrayType() throws ParseError { + SourceLocation loc = loc(); + List elements = new ArrayList<>(); + consume(Token.LBRACK, "ArrayType should start with ["); + while (token != Token.RBRACK) { + loc = loc(); + if (token == Token.REST) { + consume(Token.REST); + elements.add(finishNode(new RestType(loc, parseTypeExpression()))); + break; + } else { + elements.add(parseTypeExpression()); + } + if (token != Token.RBRACK) { + expect(Token.COMMA); + } + } + expect(Token.RBRACK); + return finishNode(new ArrayType(loc, elements)); + } + + private String parseFieldName() throws ParseError { + Object v = value; + if (token == Token.NAME || token == Token.STRING) { + next(); + return v.toString(); + } + + if (token == Token.NUMBER) { + consume(Token.NUMBER); + return v.toString(); + } + + return throwError("unexpected token"); + } + + // FieldType := + // FieldName + // | FieldName ':' TypeExpression + // + // FieldName := + // NameExpression + // | StringLiteral + // | NumberLiteral + // | ReservedIdentifier + private FieldType parseFieldType() throws ParseError { + String key; + SourceLocation loc = loc(); + key = parseFieldName(); + if (token == Token.COLON) { + consume(Token.COLON); + return finishNode(new FieldType(loc, key, parseTypeExpression())); + } + return finishNode(new FieldType(loc, key, null)); + } + + // RecordType := '{' FieldTypeList '}' + // + // FieldTypeList := + // <> + // | FieldType + // | FieldType ',' FieldTypeList + private JSDocTypeExpression parseRecordType() throws ParseError { + List fields = new ArrayList<>(); + SourceLocation loc = loc(); + consume(Token.LBRACE, "RecordType should start with {"); + if (token == Token.COMMA) { + consume(Token.COMMA); + } else { + while (token != Token.RBRACE) { + fields.add(parseFieldType()); + if (token != Token.RBRACE) { + expect(Token.COMMA); + } + } + } + expect(Token.RBRACE); + return finishNode(new RecordType(loc, fields)); + } + + private JSDocTypeExpression parseNameExpression() throws ParseError { + Object name = value; + SourceLocation loc = loc(); + expect(Token.NAME); + return finishNode(new NameExpression(loc, name.toString())); + } + + // TypeExpressionList := + // TopLevelTypeExpression + // | TopLevelTypeExpression ',' TypeExpressionList + private List parseTypeExpressionList() throws ParseError { + List elements = new ArrayList<>(); + + elements.add(parseTop()); + while (token == Token.COMMA) { + consume(Token.COMMA); + elements.add(parseTop()); + } + return elements; + } + + // TypeName := + // NameExpression + // | NameExpression TypeApplication + // + // TypeApplication := + // '.<' TypeExpressionList '>' + // | '<' TypeExpressionList '>' // this is extension of doctrine + private JSDocTypeExpression parseTypeName() throws ParseError { + JSDocTypeExpression expr; + List applications; + SourceLocation loc = loc(); + expr = parseNameExpression(); + if (token == Token.DOT_LT || token == Token.LT) { + next(); + applications = parseTypeExpressionList(); + expect(Token.GT); + return finishNode(new TypeApplication(loc, expr, applications)); + } + return expr; + } + + // ResultType := + // <> + // | ':' void + // | ':' TypeExpression + // + // BNF is above + // but, we remove <> pattern, so token is always TypeToken::COLON + private JSDocTypeExpression parseResultType() throws ParseError { + consume(Token.COLON, "ResultType should start with :"); + SourceLocation loc = loc(); + if (token == Token.NAME && value.equals("void")) { + consume(Token.NAME); + return finishNode(new VoidLiteral(loc)); + } + return parseTypeExpression(); + } + + // ParametersType := + // RestParameterType + // | NonRestParametersType + // | NonRestParametersType ',' RestParameterType + // + // RestParameterType := + // '...' + // '...' Identifier + // + // NonRestParametersType := + // ParameterType ',' NonRestParametersType + // | ParameterType + // | OptionalParametersType + // + // OptionalParametersType := + // OptionalParameterType + // | OptionalParameterType, OptionalParametersType + // + // OptionalParameterType := ParameterType= + // + // ParameterType := TypeExpression | Identifier ':' TypeExpression + // + // Identifier is "new" or "this" + private List parseParametersType() throws ParseError { + List params = new ArrayList<>(); + boolean normal = true; + JSDocTypeExpression expr; + boolean rest = false; + + while (token != Token.RPAREN) { + if (token == Token.REST) { + // RestParameterType + consume(Token.REST); + rest = true; + } + + SourceLocation loc = loc(); + expr = parseTypeExpression(); + if (expr instanceof NameExpression && token == Token.COLON) { + // Identifier ':' TypeExpression + consume(Token.COLON); + expr = finishNode(new ParameterType(loc, ((NameExpression) expr).getName(), parseTypeExpression())); + } + if (token == Token.EQUAL) { + consume(Token.EQUAL); + expr = finishNode(new OptionalType(loc, expr)); + normal = false; + } else { + if (!normal) { + throwError("unexpected token"); + } + } + if (rest) { + expr = finishNode(new RestType(new SourceLocation(loc), expr)); + } + params.add(expr); + if (token != Token.RPAREN) { + expect(Token.COMMA); + } + } + return params; + } + + // FunctionType := 'function' FunctionSignatureType + // + // FunctionSignatureType := + // | TypeParameters '(' ')' ResultType + // | TypeParameters '(' ParametersType ')' ResultType + // | TypeParameters '(' 'this' ':' TypeName ')' ResultType + // | TypeParameters '(' 'this' ':' TypeName ',' ParametersType ')' ResultType + private JSDocTypeExpression parseFunctionType() throws ParseError { + SourceLocation loc = loc(); + boolean isNew; + JSDocTypeExpression thisBinding; + List params; + JSDocTypeExpression result; + consume(Token.NAME); + + // Google Closure Compiler is not implementing TypeParameters. + // So we do not. if we don't get '(', we see it as error. + expect(Token.LPAREN); + + isNew = false; + params = new ArrayList(); + thisBinding = null; + if (token != Token.RPAREN) { + // ParametersType or 'this' + if (token == Token.NAME && + (value.equals("this") || value.equals("new"))) { + // 'this' or 'new' + // 'new' is Closure Compiler extension + isNew = value.equals("new"); + consume(Token.NAME); + expect(Token.COLON); + thisBinding = parseTypeName(); + if (token == Token.COMMA) { + consume(Token.COMMA); + params = parseParametersType(); + } + } else { + params = parseParametersType(); + } + } + + expect(Token.RPAREN); + + result = null; + if (token == Token.COLON) { + result = parseResultType(); + } + + return finishNode(new FunctionType(loc, thisBinding, isNew, params, result)); + } + + // BasicTypeExpression := + // '*' + // | 'null' + // | 'undefined' + // | TypeName + // | FunctionType + // | UnionType + // | RecordType + // | ArrayType + private JSDocTypeExpression parseBasicTypeExpression() throws ParseError { + Context context; + SourceLocation loc; + switch (token) { + case STAR: + loc = loc(); + consume(Token.STAR); + return new AllLiteral(loc); + + case LPAREN: + return parseUnionType(); + + case LBRACK: + return parseArrayType(); + + case LBRACE: + return parseRecordType(); + + case NAME: + if (value.equals("null")) { + loc = loc(); + consume(Token.NAME); + return new NullLiteral(loc); + } + + if (value.equals("undefined")) { + loc = loc(); + consume(Token.NAME); + return new UndefinedLiteral(loc); + } + + context = save(); + if (value.equals("function")) { + try { + return parseFunctionType(); + } catch (ParseError e) { + context.restore(); + } + } + + return parseTypeName(); + + default: + return throwError("unexpected token"); + } + } + + // TypeExpression := + // BasicTypeExpression + // | '?' BasicTypeExpression + // | '!' BasicTypeExpression + // | BasicTypeExpression '?' + // | BasicTypeExpression '!' + // | '?' + // | BasicTypeExpression '[]' + private JSDocTypeExpression parseTypeExpression() throws ParseError { + JSDocTypeExpression expr; + SourceLocation loc = loc(); + + if (token == Token.QUESTION) { + consume(Token.QUESTION); + if (token == Token.COMMA || token == Token.EQUAL || token == Token.RBRACE || + token == Token.RPAREN || token == Token.PIPE || token == Token.EOF || + token == Token.RBRACK) { + return finishNode(new NullableLiteral(loc)); + } + return finishNode(new NullableType(loc, parseBasicTypeExpression(), true)); + } + + if (token == Token.BANG) { + consume(Token.BANG); + return finishNode(new NonNullableType(loc, parseBasicTypeExpression(), true)); + } + + expr = parseBasicTypeExpression(); + if (token == Token.BANG) { + consume(Token.BANG); + return finishNode(new NonNullableType(loc, expr, false)); + } + + if (token == Token.QUESTION) { + consume(Token.QUESTION); + return finishNode(new NullableType(loc, expr, false)); + } + + if (token == Token.LBRACK) { + consume(Token.LBRACK); + consume(Token.RBRACK, "expected an array-style type declaration (' + value + '[])"); + List expressions = new ArrayList<>(); + expressions.add(expr); + return finishNode(new TypeApplication(loc, new NameExpression(loc, "Array"), expressions)); + } + + return expr; + } + + // TopLevelTypeExpression := + // TypeExpression + // | TypeUnionList + // + // This rule is Google Closure Compiler extension, not ES4 + // like, + // { number | string } + // If strict to ES4, we should write it as + // { (number|string) } + private JSDocTypeExpression parseTop() throws ParseError { + JSDocTypeExpression expr; + List elements = new ArrayList(); + SourceLocation loc = loc(); + + expr = parseTypeExpression(); + if (token != Token.PIPE) { + return expr; + } + + elements.add(expr); + consume(Token.PIPE); + while (true) { + elements.add(parseTypeExpression()); + if (token != Token.PIPE) { + break; + } + consume(Token.PIPE); + } + + return finishNode(new UnionType(loc, elements)); + } + + private JSDocTypeExpression parseTopParamType() throws ParseError { + JSDocTypeExpression expr; + SourceLocation loc = loc(); + + if (token == Token.REST) { + consume(Token.REST); + return finishNode(new RestType(loc, parseTop())); + } + + expr = parseTop(); + if (token == Token.EQUAL) { + consume(Token.EQUAL); + return finishNode(new OptionalType(loc, expr)); + } + + return expr; + } + + private JSDocTypeExpression parseType(String src) throws ParseError { + JSDocTypeExpression expr; + + source = src; + length = source.length(); + index = 0; + previous = 0; + + next(); + expr = parseTop(); + + if (token != Token.EOF) { + throwError("not reach to EOF"); + } + + return expr; + } + + private JSDocTypeExpression parseParamType(String src) throws ParseError { + JSDocTypeExpression expr; + + source = src; + length = source.length(); + index = 0; + previous = 0; + + next(); + expr = parseTopParamType(); + + if (token != Token.EOF) { + throwError("not reach to EOF"); + } + + return expr; + } + } + private static TypeExpressionParser typed = new TypeExpressionParser(); + + private static class JSDocTagParser { + int index, lineNumber, lineStart, length; + String source; + boolean recoverable = true, sloppy = false; + + private int skipStars(int index) { + while (index < length && isWhiteSpace(source.charAt(index)) && !isLineTerminator(source.charAt(index))) { + index += 1; + } + while (index < length && source.charAt(index) == '*') { + index += 1; + } + while (index < length && isWhiteSpace(source.charAt(index)) && !isLineTerminator(source.charAt(index))) { + index += 1; + } + return index; + } + + private char advance() { + char ch = source.charAt(index); + index += 1; + if (isLineTerminator(ch) && + !(ch == '\r' && index < length && source.charAt(index) == '\n')) { + lineNumber += 1; + lineStart = index; + index = skipStars(index); + } + return ch; + } + + private String scanTitle() { + StringBuilder title = new StringBuilder(); + // waste '@' + advance(); + + while (index < length && isASCIIAlphanumeric(source.charAt(index))) { + title.append(advance()); + } + + return title.toString(); + } + + private int seekContent() { + char ch; + boolean waiting = false; + int last = index; + + while (last < length) { + ch = source.charAt(last); + if (isLineTerminator(ch) && + !(ch == '\r' && last + 1 < length && source.charAt(last + 1) == '\n')) { + lineNumber += 1; + lineStart = last + 1; + last = skipStars(last + 1) - 1; + waiting = true; + } else if (waiting) { + if (ch == '@') { + break; + } + if (!isWhiteSpace(ch)) { + waiting = false; + } + } + last += 1; + } + return last; + } + + // type expression may have nest brace, such as, + // { { ok: string } } + // + // therefore, scanning type expression with balancing braces. + private JSDocTypeExpression parseType(String title, int last) throws ParseError { + char ch; + int brace; + StringBuilder type; + boolean direct = false; + + // search '{' + while (index < last) { + ch = source.charAt(index); + if (isWhiteSpace(ch)) { + advance(); + } else if (ch == '{') { + advance(); + break; + } else { + // this is direct pattern + direct = true; + break; + } + } + + if (!direct) { + // type expression { is found + brace = 1; + type = new StringBuilder(); + while (index < last) { + ch = source.charAt(index); + if (isLineTerminator(ch)) { + advance(); + } else { + if (ch == '}') { + brace -= 1; + if (brace == 0) { + advance(); + break; + } + } else if (ch == '{') { + brace += 1; + } + type.append(advance()); + } + } + + if (brace != 0) { + // braces is not balanced + return throwError("Braces are not balanced"); + } + + try { + if (isParamTitle(title)) { + return typed.parseParamType(type.toString()); + } + return typed.parseType(type.toString()); + } catch (ParseError e) { + // parse failed + return null; + } + } else { + return null; + } + } + + private String scanIdentifier(int last) { + StringBuilder identifier = new StringBuilder(); + if (!(index < length && isIdentifierStart(source.charAt(index)))) { + return null; + } + identifier.append(advance()); + while (index < last && isIdentifierPart(source.charAt(index))) { + identifier.append(advance()); + } + return identifier.toString(); + } + + private void skipWhiteSpace(int last) { + while (index < last && (isWhiteSpace(source.charAt(index)) || isLineTerminator(source.charAt(index)))) { + advance(); + } + } + + private String parseName(int last, boolean allowBrackets, boolean allowNestedParams) { + StringBuilder name = new StringBuilder(); + boolean useBrackets = false; + + skipWhiteSpace(last); + + if (index >= last) { + return null; + } + + if (allowBrackets && source.charAt(index) == '[') { + useBrackets = true; + name.append(advance()); + } + + if (!isIdentifierStart(source.charAt(index))) { + return null; + } + + name.append(scanIdentifier(last)); + + if (allowNestedParams) { + while (index < last && + (source.charAt(index) == '.' || source.charAt(index) == '#' || source.charAt(index) == '~')) { + name.append(source.charAt(index)); + index += 1; + name.append(scanIdentifier(last)); + } + } + + if (useBrackets) { + // do we have a default value for this? + if (index < last && source.charAt(index) == '=') { + + // consume the '='' symbol + name.append(advance()); + // scan in the default value + while (index < last && source.charAt(index) != ']') { + name .append(advance()); + } + } + + if (index >= last || source.charAt(index) != ']') { + // we never found a closing ']' + return null; + } + + // collect the last ']' + name .append(advance()); + } + + return name.toString(); + } + + boolean skipToTag() { + while (index < length && source.charAt(index) != '@') { + advance(); + } + if (index >= length) { + return false; + } + return true; + } + + private class Tag { + public String description; + public String title; + List errors = new ArrayList<>(); + JSDocTypeExpression type; + String name; + public int startLine; + public int startColumn; + } + + private class TagParser { + String _title; + Tag _tag; + int _last; + String _extra_name; + + TagParser(String title) { + this._title = title; + this._tag = new Tag(); + this._tag.description = null; + this._tag.title = title; + this._last = 0; + // space to save special information for title parsers. + this._extra_name = null; + } + + // addError(err, ...) + public boolean addError(String errorText, Object... args) { + this._tag.errors.add(String.format(errorText, args)); + return recoverable; + } + + public boolean parseType() { + // type required titles + if (isTypeParameterRequired(this._title)) { + try { + this._tag.type = JSDocTagParser.this.parseType(this._title, this._last); + if (this._tag.type == null) { + if (!isParamTitle(this._title)) { + if (!this.addError("Missing or invalid tag type")) { + return false; + } + } + } + } catch (ParseError error) { + this._tag.type = null; + if (!this.addError(error.getMessage())) { + return false; + } + } + } else if (isAllowedType(this._title)) { + // optional types + try { + this._tag.type = JSDocTagParser.this.parseType(this._title, this._last); + } catch (ParseError e) { + //For optional types, lets drop the thrown error when we hit the end of the file + } + } + return true; + } + + private boolean _parseNamePath(boolean optional) { + String name = JSDocTagParser.this.parseName(this._last, sloppy && isParamTitle(this._title), true); + if (name == null) { + if (!optional) { + if (!this.addError("Missing or invalid tag name")) { + return false; + } + } + } + this._tag.name = name; + return true; + } + + public boolean parseNamePath() { + return _parseNamePath(false); + } + + public boolean parseNamePathOptional() { + return this._parseNamePath(true); + } + + public boolean parseName() { + String[] assign; + String name; + + // param, property requires name + if (isAllowedName(this._title)) { + this._tag.name = JSDocTagParser.this.parseName(this._last, sloppy && isParamTitle(this._title), isAllowedNested(this._title)); + if (this._tag.name == null) { + if (!isNameParameterRequired(this._title)) { + return true; + } + + // it's possible the name has already been parsed but interpreted as a type + // it's also possible this is a sloppy declaration, in which case it will be + // fixed at the end + if (isParamTitle(this._title) && this._tag.type != null && this._tag.type instanceof NameExpression) { + this._extra_name = ((NameExpression) this._tag.type).getName(); + this._tag.name = ((NameExpression) this._tag.type).getName(); + this._tag.type = null; + } else { + if (!this.addError("Missing or invalid tag name")) { + return false; + } + } + } else { + name = this._tag.name; + if (name.charAt(0) == '[' && name.charAt(name.length() - 1) == ']') { + // extract the default value if there is one + // example: @param {string} [somebody=John Doe] description + assign = name.substring(1, name.length() - 1).split("="); + this._tag.name = assign[0]; + + // convert to an optional type + if (this._tag.type != null && !(this._tag.type instanceof OptionalType)) { + Position start = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn); + Position end = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn); + SourceLocation loc = new SourceLocation(_extra_name, start, end); + this._tag.type = new OptionalType(loc, this._tag.type); + } + } + } + } + + return true; + } + + private boolean parseDescription() { + String description = sliceSource(source, index, this._last).trim(); + if (!description.isEmpty()) { + if (description.matches("(?s)^-\\s+.*")) { + description = description.substring(2); + } + description = description.replaceAll("(?m)^\\s*\\*+\\s*", ""); + this._tag.description = description; + } + return true; + } + + private final Set kinds = new LinkedHashSet<>(); + { + kinds.add("class"); + kinds.add("constant"); + kinds.add("event"); + kinds.add("external"); + kinds.add("file"); + kinds.add("function"); + kinds.add("member"); + kinds.add("mixin"); + kinds.add("module"); + kinds.add("namespace"); + kinds.add("typedef"); + } + + private boolean parseKind() { + String kind = sliceSource(source, index, this._last).trim(); + if (!kinds.contains(kind)) { + if (!this.addError("Invalid kind name \'%s\'", kind)) { + return false; + } + } + return true; + } + + private boolean parseAccess() { + String access = sliceSource(source, index, this._last).trim(); + if (!access.equals("private") && !access.equals("protected") && !access.equals("public")) { + if (!this.addError("Invalid access name \'%s\'", access)) { + return false; + } + } + return true; + } + + private boolean parseVariation() { + double variation; + String text = sliceSource(source, index, this._last).trim(); + try { + variation = Double.parseDouble(text); + } catch (NumberFormatException nfe) { + variation = Double.NaN; + } + if (Double.isNaN(variation)) { + if (!this.addError("Invalid variation \'%s\'", text)) { + return false; + } + } + return true; + } + + private boolean ensureEnd() { + String shouldBeEmpty = sliceSource(source, index, this._last).trim(); + if (!shouldBeEmpty.matches("^[\\s*]*$")) { + if (!this.addError("Unknown content \'%s\'", shouldBeEmpty)) { + return false; + } + } + return true; + } + + private boolean epilogue() { + String description; + + description = this._tag.description; + // un-fix potentially sloppy declaration + if (isParamTitle(this._title) && this._tag.type == null && description != null + && description.startsWith("[")) { + if (_extra_name != null) { + Position start = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn); + Position end = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn); + SourceLocation loc = new SourceLocation(_extra_name, start, end); + this._tag.type = new NameExpression(loc, _extra_name); + } + this._tag.name = null; + + if (!sloppy) { + if (!this.addError("Missing or invalid tag name")) { + return false; + } + } + } + + return true; + } + + private Tag parse() { + int oldLineNumber, oldLineStart, newLineNumber, newLineStart; + + // empty title + if (this._title == null || this._title.isEmpty()) { + if (!this.addError("Missing or invalid title")) { + return null; + } + } + + // Seek to content last index. + oldLineNumber = lineNumber; + oldLineStart = lineStart; + this._last = seekContent(); + newLineNumber = lineNumber; + newLineStart = lineStart; + lineNumber = oldLineNumber; + lineStart = oldLineStart; + + switch (this._title) { + // http://usejsdoc.org/tags-access.html + case "access": if (!parseAccess()) return null; break; + // http://usejsdoc.org/tags-alias.html + case "alias": if (!parseNamePath() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-augments.html + case "augments": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-constructor.html + case "constructor": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // Synonym: http://usejsdoc.org/tags-constructor.html + case "class": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // Synonym: http://usejsdoc.org/tags-extends.html + case "extends": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-deprecated.html + case "deprecated": if (!parseDescription()) return null; break; + // http://usejsdoc.org/tags-global.html + case "global": if (!ensureEnd()) return null; break; + // http://usejsdoc.org/tags-inner.html + case "inner": if (!ensureEnd()) return null; break; + // http://usejsdoc.org/tags-instance.html + case "instance": if (!ensureEnd()) return null; break; + // http://usejsdoc.org/tags-kind.html + case "kind": if (!parseKind()) return null; break; + // http://usejsdoc.org/tags-mixes.html + case "mixes": if (!parseNamePath() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-mixin.html + case "mixin": if (!parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-member.html + case "member": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-method.html + case "method": if (!parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-module.html + case "module": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // Synonym: http://usejsdoc.org/tags-method.html + case "func": if (!parseNamePathOptional() || !ensureEnd()) return null; break; + // Synonym: http://usejsdoc.org/tags-method.html + case "function": if (!parseNamePathOptional() || !ensureEnd()) return null; break; + // Synonym: http://usejsdoc.org/tags-member.html + case "var": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-name.html + case "name": if (!parseNamePath() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-namespace.html + case "namespace": if (!parseType() || !parseNamePathOptional() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-private.html + case "private": if (!parseType() || !parseDescription()) return null; break; + // http://usejsdoc.org/tags-protected.html + case "protected": if (!parseType() || !parseDescription()) return null; break; + // http://usejsdoc.org/tags-public.html + case "public": if (!parseType() || !parseDescription()) return null; break; + // http://usejsdoc.org/tags-readonly.html + case "readonly": if (!ensureEnd()) return null; break; + // http://usejsdoc.org/tags-requires.html + case "requires": if (!parseNamePath() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-since.html + case "since": if (!parseDescription()) return null; break; + // http://usejsdoc.org/tags-static.html + case "static": if (!ensureEnd()) return null; break; + // http://usejsdoc.org/tags-summary.html + case "summary": if (!parseDescription()) return null; break; + // http://usejsdoc.org/tags-this.html + case "this": if (!parseNamePath() || !ensureEnd()) return null; break; + // http://usejsdoc.org/tags-todo.html + case "todo": if (!parseDescription()) return null; break; + // http://usejsdoc.org/tags-variation.html + case "variation": if (!parseVariation()) return null; break; + // http://usejsdoc.org/tags-version.html + case "version": if (!parseDescription()) return null; break; + // default sequences + default: if (!parseType() || !parseName() || !parseDescription() || !epilogue()) return null; break; + } + + // Seek global index to end of this tag. + index = this._last; + lineNumber = newLineNumber; + lineStart = newLineStart; + return this._tag; + } + + private Tag parseTag() { + String title; + Tag res; + TagParser parser; + int startColumn; + int startLine; + + // skip to tag + if (!skipToTag()) { + return null; + } + + startLine = lineNumber; + startColumn = index - lineStart; + + // scan title + title = scanTitle(); + + // construct tag parser + parser = new TagParser(title); + res = parser.parse(); + + if (res != null) { + res.startLine = startLine; + res.startColumn = startColumn; + } + + return res; + } + + // + // Parse JSDoc + // + + String scanJSDocDescription() { + StringBuilder description = new StringBuilder(); + char ch; + boolean atAllowed; + + atAllowed = true; + while (index < length) { + ch = source.charAt(index); + + if (atAllowed && ch == '@') { + break; + } + + if (isLineTerminator(ch)) { + atAllowed = true; + } else if (atAllowed && !isWhiteSpace(ch)) { + atAllowed = false; + } + + description.append(advance()); + } + return description.toString().trim(); + } + + + public Pair> parse(String comment) { + List tags = new ArrayList<>(); + Tag tag; + String description; + + source = comment.replaceAll("^/?\\*+", "").replaceAll("\\*+/?\\z", ""); + + length = source.length(); + index = 0; + lineNumber = 0; + lineStart = 0; + recoverable = true; + sloppy = true; + + description = scanJSDocDescription(); + + while (true) { + tag = parseTag(); + if (tag == null) { + break; + } + tags.add(tag); + } + + return Pair.make(description, tags); + } + } + } } diff --git a/javascript/extractor/src/com/semmle/js/parser/RegExpParser.java b/javascript/extractor/src/com/semmle/js/parser/RegExpParser.java index 2099edcbd91..bfa4919cde6 100644 --- a/javascript/extractor/src/com/semmle/js/parser/RegExpParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/RegExpParser.java @@ -1,17 +1,9 @@ package com.semmle.js.parser; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; - -import org.mozilla.javascript.Function; -import org.mozilla.javascript.NativeArray; -import org.mozilla.javascript.NativeObject; -import org.mozilla.javascript.ScriptableObject; +import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.regexp.BackReference; import com.semmle.js.ast.regexp.Caret; @@ -47,54 +39,9 @@ import com.semmle.js.ast.regexp.ZeroWidthPositiveLookahead; import com.semmle.js.ast.regexp.ZeroWidthPositiveLookbehind; /** - * Wrapper for invoking esregex through Rhino. + * A parser for ECMAScript 2018 regular expressions. */ -public class RegExpParser extends ScriptLoader { - /** - * Specification for esregex AST types. - */ - private static final Map, List> spec = new LinkedHashMap, List>(); - static { - spec.put(BackReference.class, Arrays.asList("value", "raw")); - spec.put(Caret.class, Collections.emptyList()); - spec.put(CharacterClass.class, Arrays.asList("elements", "inverted")); - spec.put(CharacterClassEscape.class, Arrays.asList("class", "raw")); - spec.put(CharacterClassRange.class, Arrays.asList("left", "right")); - spec.put(Constant.class, Arrays.asList("value")); - spec.put(ControlEscape.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(ControlLetter.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(DecimalEscape.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(Disjunction.class, Arrays.asList("disjuncts")); - spec.put(Dollar.class, Collections.emptyList()); - spec.put(Dot.class, Collections.emptyList()); - spec.put(Group.class, Arrays.asList("capture", "number", "name", "operand")); - spec.put(HexEscapeSequence.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(IdentityEscape.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(NamedBackReference.class, Arrays.asList("name", "raw")); - spec.put(NonWordBoundary.class, Collections.emptyList()); - spec.put(OctalEscape.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(Opt.class, Arrays.asList("operand", "greedy")); - spec.put(Plus.class, Arrays.asList("operand", "greedy")); - spec.put(Range.class, Arrays.asList("operand", "greedy", "lo", "hi")); - spec.put(Sequence.class, Arrays.asList("elements")); - spec.put(Star.class, Arrays.asList("operand", "greedy")); - spec.put(UnicodeEscapeSequence.class, Arrays.asList("value", "codepoint", "raw")); - spec.put(WordBoundary.class, Collections.emptyList()); - spec.put(ZeroWidthNegativeLookahead.class, Arrays.asList("operand")); - spec.put(ZeroWidthPositiveLookahead.class, Arrays.asList("operand")); - spec.put(ZeroWidthNegativeLookbehind.class, Arrays.asList("operand")); - spec.put(ZeroWidthPositiveLookbehind.class, Arrays.asList("operand")); - spec.put(UnicodePropertyEscape.class, Arrays.asList("name", "value", "raw")); - } - - /** - * Specification for esregex parse errors. - */ - private static final Map, List> errspec = new LinkedHashMap, List>(); - static { - errspec.put(Error.class, Arrays.asList("code")); - } - +public class RegExpParser { /** * The result of a parse. */ @@ -102,12 +49,12 @@ public class RegExpParser extends ScriptLoader { /** * The root of the parsed AST. */ - private final RegExpTerm ast; + public final RegExpTerm ast; /** * A list of errors encountered during parsing. */ - private final List errors; + public final List errors; public Result(RegExpTerm ast, List errors) { this.ast = ast; @@ -123,28 +70,450 @@ public class RegExpParser extends ScriptLoader { } } - public RegExpParser() { - super("/regexparser.js"); - } + private String src; + private int pos; + private List errors; + private List backrefs; + private int maxbackref; /** * Parse the given string as a regular expression. */ public Result parse(String src) { - Function ctor = (Function)readGlobal("RegExpParser"); - ScriptableObject parser = construct(ctor, src); - NativeObject ast = (NativeObject)callMethod(parser, "Pattern"); - NativeArray errors = (NativeArray)readProperty(parser, "errors"); - JSObjectDecoder decoder = new JSObjectDecoder(src, this, "com.semmle.js.ast.regexp", spec); - List errs = null; - RegExpTerm term = null; - try { - term = decoder.decodeObject(ast); - errs = new JSObjectDecoder(src, this, "com.semmle.js.ast.regexp", errspec).decodeObjects(errors); - } catch (ParseError e) { - errs = new ArrayList(); - errs.add(new Error(new SourceLocation("", e.getPosition(), e.getPosition()), 1)); + this.src = src; + this.pos = 0; + this.errors = new ArrayList<>(); + this.backrefs = new ArrayList<>(); + this.maxbackref = 0; + RegExpTerm root = parsePattern(); + for (BackReference backref : backrefs) + if (backref.getValue() > maxbackref) + errors.add(new Error(backref.getLoc(), Error.INVALID_BACKREF)); + return new Result(root, errors); + } + + private static String fromCodePoint(int codepoint) { + if (Character.isValidCodePoint(codepoint)) + return new String(Character.toChars(codepoint)); + // replacement character + return "\ufffd"; + } + + private Position pos() { + return new Position(1, pos, pos); + } + + private void error(int code, int start, int end) { + Position startPos, endPos; + startPos = new Position(1, start, start); + endPos = new Position(1, end, end); + this.errors.add(new Error(new SourceLocation(inputSubstring(start, end), startPos, endPos), code)); + } + + private void error(int code, int start) { + error(code, start, start+1); + } + + private void error(int code) { + error(code, this.pos); + } + + private boolean atEOS() { + return pos >= src.length(); + } + + private char peekChar(boolean opt) { + if (this.atEOS()) { + if (!opt) + this.error(Error.UNEXPECTED_EOS); + return '\0'; + } else { + return this.src.charAt(this.pos); } - return new Result(term, errs); + } + + private char nextChar() { + char c = peekChar(false); + if (this.pos < src.length()) + ++this.pos; + return c; + } + + private String readHexDigit() { + char c = this.peekChar(false); + if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') { + ++this.pos; + return String.valueOf(c); + } + if (c != '\0') + this.error(Error.EXPECTED_HEX_DIGIT, this.pos); + return ""; + } + + private String readHexDigits(int n) { + StringBuilder res = new StringBuilder(); + while (n-->0) { + res.append(readHexDigit()); + } + if (res.length() == 0) + return "0"; + return res.toString(); + } + + private String readDigits(boolean opt) { + StringBuilder res = new StringBuilder(); + for (char c=peekChar(true); c >= '0' && c <= '9'; nextChar(), c=peekChar(true)) + res.append(c); + if (res.length() == 0 && !opt) + this.error(Error.EXPECTED_DIGIT); + return res.toString(); + } + + private Double toNumber(String s) { + if (s.isEmpty()) + return 0.0; + return Double.valueOf(s); + } + + private String readIdentifier() { + StringBuilder res = new StringBuilder(); + for (char c=peekChar(true); + c != '\0' && Character.isJavaIdentifierPart(c); + nextChar(), c=peekChar(true)) + res.append(c); + if (res.length() == 0) + this.error(Error.EXPECTED_IDENTIFIER); + return res.toString(); + } + + private void expectRParen() { + if (!this.match(")")) + this.error(Error.EXPECTED_CLOSING_PAREN, this.pos-1); + } + + private void expectRBrace() { + if (!this.match("}")) + this.error(Error.EXPECTED_CLOSING_BRACE, this.pos-1); + } + + private void expectRAngle() { + if (!this.match(">")) + this.error(Error.EXPECTED_CLOSING_ANGLE, this.pos-1); + } + + private boolean lookahead(String... arguments) { + for (String prefix : arguments) { + if (prefix == null) { + if (atEOS()) + return true; + } else if (inputSubstring(pos, pos+prefix.length()).equals(prefix)) { + return true; + } + } + return false; + } + + private boolean match(String... arguments) { + for (String prefix : arguments) { + if (this.lookahead(prefix)) { + if (prefix == null) + prefix = ""; + this.pos += prefix.length(); + return true; + } + } + return false; + } + + private RegExpTerm parsePattern() { + RegExpTerm res = parseDisjunction(); + if (!this.atEOS()) + this.error(Error.EXPECTED_EOS); + return res; + } + + protected String inputSubstring(int start, int end) { + if (start >= src.length()) + return ""; + if (end > src.length()) + end = src.length(); + return src.substring(start, end); + } + + private T finishTerm(T term) { + SourceLocation loc = term.getLoc(); + Position end = pos(); + loc.setSource(inputSubstring(loc.getStart().getOffset(), end.getOffset())); + loc.setEnd(end); + return term; + } + + private RegExpTerm parseDisjunction() { + SourceLocation loc = new SourceLocation(pos()); + List disjuncts = new ArrayList<>(); + disjuncts.add(this.parseAlternative()); + while (this.match("|")) + disjuncts.add(this.parseAlternative()); + if (disjuncts.size() == 1) + return disjuncts.get(0); + return this.finishTerm(new Disjunction(loc, disjuncts)); + } + + private RegExpTerm parseAlternative() { + SourceLocation loc = new SourceLocation(pos()); + List elements = new ArrayList<>(); + while (!this.lookahead(null, "|", ")")) + elements.add(this.parseTerm()); + if (elements.size() == 1) + return elements.get(0); + return this.finishTerm(new Sequence(loc, elements)); + } + + private RegExpTerm parseTerm() { + SourceLocation loc = new SourceLocation(pos()); + + if (this.match("^")) + return this.finishTerm(new Caret(loc)); + + if (this.match("$")) + return this.finishTerm(new Dollar(loc)); + + if (this.match("\\b")) + return this.finishTerm(new WordBoundary(loc)); + + if (this.match("\\B")) + return this.finishTerm(new NonWordBoundary(loc)); + + if (this.match("(?=")) { + RegExpTerm dis = this.parseDisjunction(); + this.expectRParen(); + return this.finishTerm(new ZeroWidthPositiveLookahead(loc, dis)); + } + + if (this.match("(?!")) { + RegExpTerm dis = this.parseDisjunction(); + this.expectRParen(); + return this.finishTerm(new ZeroWidthNegativeLookahead(loc, dis)); + } + + if (this.match("(?<=")) { + RegExpTerm dis = this.parseDisjunction(); + this.expectRParen(); + return this.finishTerm(new ZeroWidthPositiveLookbehind(loc, dis)); + } + + if (this.match("(?")); + } + + if (this.match("p{", "P{")) { + String name = this.readIdentifier(); + if (this.match("=")) { + value = this.readIdentifier(); + raw = "\\p{" + name + "=" + value + "}"; + } else { + value = null; + raw = "\\p{" + name + "}"; + } + this.expectRBrace(); + return this.finishTerm(new UnicodePropertyEscape(loc, name, value, raw)); + } + + int startpos = this.pos-1; + char c = this.nextChar(); + + if (c >= '0' && c <= '9') { + raw = c + this.readDigits(true); + if (c == '0' || inCharClass) { + int base = c == '0' && raw.length() > 1 ? 8 : 10; + try { + codepoint = Long.parseLong(raw, base); + value = fromCodePoint((int) codepoint); + } catch (NumberFormatException nfe) { + codepoint = 0; + value = "\0"; + } + if (base == 8) { + this.error(Error.OCTAL_ESCAPE, startpos, this.pos); + return this.finishTerm(new OctalEscape(loc, value, (double)codepoint, "\\" + raw)); + } else { + return this.finishTerm(new DecimalEscape(loc, value, (double)codepoint, "\\" + raw)); + } + } else { + try { + codepoint = Long.parseLong(raw, 10); + } catch (NumberFormatException nfe) { + codepoint = 0; + } + BackReference br = this.finishTerm(new BackReference(loc, (double)codepoint, "\\" + raw)); + this.backrefs.add(br); + return br; + } + } + + String ctrltab = "f\fn\nr\rt\tv\u000b"; + int idx; + if ((idx=ctrltab.indexOf(c)) % 2 == 0) { + codepoint = ctrltab.charAt(idx+1); + value = String.valueOf((char)codepoint); + return this.finishTerm(new ControlEscape(loc, value, codepoint, "\\" + c)); + } + + if (c == 'c') { + c = this.nextChar(); + if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) + this.error(Error.EXPECTED_CONTROL_LETTER, this.pos-1); + codepoint = c % 32; + value = String.valueOf((char)codepoint); + return this.finishTerm(new ControlLetter(loc, value, codepoint, "\\c" + c)); + } + + if ("dDsSwW".indexOf(c) >= 0) { + return this.finishTerm(new CharacterClassEscape(loc, String.valueOf(c), "\\" + c)); + } + + codepoint = c; + value = String.valueOf((char)codepoint); + return this.finishTerm(new IdentityEscape(loc, value, codepoint, "\\" + c)); + } + + private RegExpTerm parseCharacterClass() { + SourceLocation loc = new SourceLocation(pos()); + List elements = new ArrayList<>(); + + this.match("["); + boolean inverted = this.match("^"); + while (!this.match("]")) { + if (this.atEOS()) { + this.error(Error.EXPECTED_RBRACKET); + break; + } + elements.add(this.parseCharacterClassElement()); + } + return this.finishTerm(new CharacterClass(loc, elements, inverted)); + } + + private RegExpTerm parseCharacterClassElement() { + SourceLocation loc = new SourceLocation(pos()); + RegExpTerm atom = this.parseCharacterClassAtom(); + if (!this.lookahead("-]") && this.match("-")) + return this.finishTerm(new CharacterClassRange(loc, atom, this.parseCharacterClassAtom())); + return atom; + } + + private RegExpTerm parseCharacterClassAtom() { + SourceLocation loc = new SourceLocation(pos()); + char c = this.nextChar(); + if (c == '\\') { + if (this.match("b")) + return this.finishTerm(new ControlEscape(loc, "\b", 8, "\\b")); + return this.finishTerm(this.parseAtomEscape(loc, true)); + } + return this.finishTerm(new Constant(loc, String.valueOf(c))); } } diff --git a/javascript/extractor/tests/comments/input/jsdoc.js b/javascript/extractor/tests/comments/input/jsdoc.js index e8b4b59c3bf..5f22f8bd78d 100644 --- a/javascript/extractor/tests/comments/input/jsdoc.js +++ b/javascript/extractor/tests/comments/input/jsdoc.js @@ -15,3 +15,28 @@ * @param {Function(DOMNode)} * @param {Function(DOMNode)} x */ + +/** + * @{link a} + */ + +/** + * @typedef + * {a} + */ + +/** + * [resize description] + * @param {[type]} w [description] + * @param { } h [description] + * @return {[type]} [description] + */ + +/** +* @exports R +* +*/ + +/** + * @typedef {{0: number}} + */ diff --git a/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap b/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap index 5c0c6c543b0..7d0e6318fee 100644 --- a/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap +++ b/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap @@ -10,8 +10,8 @@ hasLocation(#10000,#10002) scopes(#20000,0) #20001=@"script;{#10000},1,1" toplevels(#20001,0) -#20002=@"loc,{#10000},1,1,18,0" -locations_default(#20002,#10000,1,1,18,0) +#20002=@"loc,{#10000},1,1,43,0" +locations_default(#20002,#10000,1,1,43,0) hasLocation(#20001,#20002) #20003=* comments(#20003,2,#20001," @@ -51,253 +51,537 @@ comments(#20011,2,#20001," locations_default(#20012,#10000,14,1,17,3) hasLocation(#20011,#20012) #20013=* -lines(#20013,#20001,"/**"," -") -#20014=@"loc,{#10000},1,1,1,3" -locations_default(#20014,#10000,1,1,1,3) +comments(#20013,2,#20001," + * @{link a} + ","/**\n * @{link a}\n */") +#20014=@"loc,{#10000},19,1,21,3" +locations_default(#20014,#10000,19,1,21,3) hasLocation(#20013,#20014) #20015=* -lines(#20015,#20001," * This is a constant."," -") -#20016=@"loc,{#10000},2,1,2,22" -locations_default(#20016,#10000,2,1,2,22) +comments(#20015,2,#20001," + * @typedef + * {a} + ","/**\n * ... {a}\n */") +#20016=@"loc,{#10000},23,1,26,3" +locations_default(#20016,#10000,23,1,26,3) hasLocation(#20015,#20016) -indentation(#10000,2," ",1) #20017=* -lines(#20017,#20001," * "," -") -#20018=@"loc,{#10000},3,1,3,3" -locations_default(#20018,#10000,3,1,3,3) +comments(#20017,2,#20001," + * [resize description] + * @param {[type]} w [description] + * @param { } h [description] + * @return {[type]} [description] + ","/**\n * ... on]\n */") +#20018=@"loc,{#10000},28,1,33,3" +locations_default(#20018,#10000,28,1,33,3) hasLocation(#20017,#20018) -indentation(#10000,3," ",1) #20019=* -lines(#20019,#20001," * @const x"," -") -#20020=@"loc,{#10000},4,1,4,11" -locations_default(#20020,#10000,4,1,4,11) +comments(#20019,2,#20001," +* @exports R +* +","/**\n* @ ... R\n*\n*/") +#20020=@"loc,{#10000},35,1,38,2" +locations_default(#20020,#10000,35,1,38,2) hasLocation(#20019,#20020) -indentation(#10000,4," ",1) #20021=* -lines(#20021,#20001," */"," -") -#20022=@"loc,{#10000},5,1,5,3" -locations_default(#20022,#10000,5,1,5,3) +comments(#20021,2,#20001," + * @typedef {{0: number}} + ","/**\n * ... r}}\n */") +#20022=@"loc,{#10000},40,1,42,3" +locations_default(#20022,#10000,40,1,42,3) hasLocation(#20021,#20022) -indentation(#10000,5," ",1) #20023=* -lines(#20023,#20001,"/** @class {Object} klass */"," +lines(#20023,#20001,"/**"," ") -hasLocation(#20023,#20006) -#20024=* -lines(#20024,#20001,"/** @deprecated */"," -") -hasLocation(#20024,#20008) +#20024=@"loc,{#10000},1,1,1,3" +locations_default(#20024,#10000,1,1,1,3) +hasLocation(#20023,#20024) #20025=* -lines(#20025,#20001,"/** @param {(int|bool)} x"," +lines(#20025,#20001," * This is a constant."," ") -#20026=@"loc,{#10000},8,1,8,25" -locations_default(#20026,#10000,8,1,8,25) +#20026=@"loc,{#10000},2,1,2,22" +locations_default(#20026,#10000,2,1,2,22) hasLocation(#20025,#20026) +indentation(#10000,2," ",1) #20027=* -lines(#20027,#20001," * @param {Array.} ys"," +lines(#20027,#20001," * "," ") -#20028=@"loc,{#10000},9,1,9,38" -locations_default(#20028,#10000,9,1,9,38) +#20028=@"loc,{#10000},3,1,3,3" +locations_default(#20028,#10000,3,1,3,3) hasLocation(#20027,#20028) -indentation(#10000,9," ",1) +indentation(#10000,3," ",1) #20029=* -lines(#20029,#20001," * @param {String[]} zs"," +lines(#20029,#20001," * @const x"," ") -#20030=@"loc,{#10000},10,1,10,24" -locations_default(#20030,#10000,10,1,10,24) +#20030=@"loc,{#10000},4,1,4,11" +locations_default(#20030,#10000,4,1,4,11) hasLocation(#20029,#20030) -indentation(#10000,10," ",1) +indentation(#10000,4," ",1) #20031=* -lines(#20031,#20001," * @param {function(new:goog.ui.Menu, ?string=, number=): void} f"," +lines(#20031,#20001," */"," ") -#20032=@"loc,{#10000},11,1,11,66" -locations_default(#20032,#10000,11,1,11,66) +#20032=@"loc,{#10000},5,1,5,3" +locations_default(#20032,#10000,5,1,5,3) hasLocation(#20031,#20032) -indentation(#10000,11," ",1) +indentation(#10000,5," ",1) #20033=* -lines(#20033,#20001," * @param {...number} var_args"," +lines(#20033,#20001,"/** @class {Object} klass */"," ") -#20034=@"loc,{#10000},12,1,12,31" -locations_default(#20034,#10000,12,1,12,31) -hasLocation(#20033,#20034) -indentation(#10000,12," ",1) +hasLocation(#20033,#20006) +#20034=* +lines(#20034,#20001,"/** @deprecated */"," +") +hasLocation(#20034,#20008) #20035=* -lines(#20035,#20001," */"," +lines(#20035,#20001,"/** @param {(int|bool)} x"," ") -#20036=@"loc,{#10000},13,1,13,3" -locations_default(#20036,#10000,13,1,13,3) +#20036=@"loc,{#10000},8,1,8,25" +locations_default(#20036,#10000,8,1,8,25) hasLocation(#20035,#20036) -indentation(#10000,13," ",1) #20037=* -lines(#20037,#20001,"/**"," +lines(#20037,#20001," * @param {Array.} ys"," ") -#20038=@"loc,{#10000},14,1,14,3" -locations_default(#20038,#10000,14,1,14,3) +#20038=@"loc,{#10000},9,1,9,38" +locations_default(#20038,#10000,9,1,9,38) hasLocation(#20037,#20038) +indentation(#10000,9," ",1) #20039=* -lines(#20039,#20001," * @param {Function(DOMNode)}"," +lines(#20039,#20001," * @param {String[]} zs"," ") -#20040=@"loc,{#10000},15,1,15,29" -locations_default(#20040,#10000,15,1,15,29) +#20040=@"loc,{#10000},10,1,10,24" +locations_default(#20040,#10000,10,1,10,24) hasLocation(#20039,#20040) -indentation(#10000,15," ",1) +indentation(#10000,10," ",1) #20041=* -lines(#20041,#20001," * @param {Function(DOMNode)} x"," +lines(#20041,#20001," * @param {function(new:goog.ui.Menu, ?string=, number=): void} f"," ") -#20042=@"loc,{#10000},16,1,16,31" -locations_default(#20042,#10000,16,1,16,31) +#20042=@"loc,{#10000},11,1,11,66" +locations_default(#20042,#10000,11,1,11,66) hasLocation(#20041,#20042) -indentation(#10000,16," ",1) +indentation(#10000,11," ",1) #20043=* -lines(#20043,#20001," */"," +lines(#20043,#20001," * @param {...number} var_args"," ") -#20044=@"loc,{#10000},17,1,17,3" -locations_default(#20044,#10000,17,1,17,3) +#20044=@"loc,{#10000},12,1,12,31" +locations_default(#20044,#10000,12,1,12,31) hasLocation(#20043,#20044) -indentation(#10000,17," ",1) -numlines(#20001,17,0,17) +indentation(#10000,12," ",1) #20045=* -tokeninfo(#20045,0,#20001,0,"") -#20046=@"loc,{#10000},18,1,18,0" -locations_default(#20046,#10000,18,1,18,0) +lines(#20045,#20001," */"," +") +#20046=@"loc,{#10000},13,1,13,3" +locations_default(#20046,#10000,13,1,13,3) hasLocation(#20045,#20046) -next_token(#20003,#20045) -next_token(#20005,#20045) -next_token(#20007,#20045) -next_token(#20009,#20045) -next_token(#20011,#20045) +indentation(#10000,13," ",1) #20047=* -entry_cfg_node(#20047,#20001) -#20048=@"loc,{#10000},1,1,1,0" -locations_default(#20048,#10000,1,1,1,0) +lines(#20047,#20001,"/**"," +") +#20048=@"loc,{#10000},14,1,14,3" +locations_default(#20048,#10000,14,1,14,3) hasLocation(#20047,#20048) #20049=* -exit_cfg_node(#20049,#20001) -hasLocation(#20049,#20046) -successor(#20047,#20049) -#20050=* -jsdoc(#20050,"This is a constant.",#20003) -hasLocation(#20050,#20004) +lines(#20049,#20001," * @param {Function(DOMNode)}"," +") +#20050=@"loc,{#10000},15,1,15,29" +locations_default(#20050,#10000,15,1,15,29) +hasLocation(#20049,#20050) +indentation(#10000,15," ",1) #20051=* -jsdoc_tags(#20051,"const",#20050,0,"@const") -#20052=@"loc,{#10000},4,4,4,9" -locations_default(#20052,#10000,4,4,4,9) +lines(#20051,#20001," * @param {Function(DOMNode)} x"," +") +#20052=@"loc,{#10000},16,1,16,31" +locations_default(#20052,#10000,16,1,16,31) hasLocation(#20051,#20052) -jsdoc_tag_names(#20051,"x") +indentation(#10000,16," ",1) #20053=* -jsdoc(#20053,"",#20005) -hasLocation(#20053,#20006) -#20054=* -jsdoc_tags(#20054,"class",#20053,0,"@class") -#20055=@"loc,{#10000},6,5,6,10" -locations_default(#20055,#10000,6,5,6,10) -hasLocation(#20054,#20055) -jsdoc_tag_names(#20054,"klass") -#20056=* -jsdoc_type_exprs(#20056,5,#20054,0,"Object") +lines(#20053,#20001," */"," +") +#20054=@"loc,{#10000},17,1,17,3" +locations_default(#20054,#10000,17,1,17,3) +hasLocation(#20053,#20054) +indentation(#10000,17," ",1) +#20055=* +lines(#20055,#20001,""," +") +#20056=@"loc,{#10000},18,1,18,0" +locations_default(#20056,#10000,18,1,18,0) +hasLocation(#20055,#20056) #20057=* -jsdoc(#20057,"",#20007) -hasLocation(#20057,#20008) -#20058=* -jsdoc_tags(#20058,"deprecated",#20057,0,"@deprecated") -#20059=@"loc,{#10000},7,5,7,15" -locations_default(#20059,#10000,7,5,7,15) -hasLocation(#20058,#20059) -#20060=* -jsdoc(#20060,"",#20009) -hasLocation(#20060,#20010) +lines(#20057,#20001,"/**"," +") +#20058=@"loc,{#10000},19,1,19,3" +locations_default(#20058,#10000,19,1,19,3) +hasLocation(#20057,#20058) +#20059=* +lines(#20059,#20001," * @{link a}"," +") +#20060=@"loc,{#10000},20,1,20,12" +locations_default(#20060,#10000,20,1,20,12) +hasLocation(#20059,#20060) +indentation(#10000,20," ",1) #20061=* -jsdoc_tags(#20061,"param",#20060,0,"@param") -#20062=@"loc,{#10000},8,5,8,10" -locations_default(#20062,#10000,8,5,8,10) +lines(#20061,#20001," */"," +") +#20062=@"loc,{#10000},21,1,21,3" +locations_default(#20062,#10000,21,1,21,3) hasLocation(#20061,#20062) -jsdoc_tag_names(#20061,"x") +indentation(#10000,21," ",1) #20063=* -jsdoc_type_exprs(#20063,11,#20061,0,"(int|bool)") -#20064=* -jsdoc_type_exprs(#20064,5,#20063,0,"int") +lines(#20063,#20001,""," +") +#20064=@"loc,{#10000},22,1,22,0" +locations_default(#20064,#10000,22,1,22,0) +hasLocation(#20063,#20064) #20065=* -jsdoc_type_exprs(#20065,5,#20063,1,"bool") -#20066=* -jsdoc_tags(#20066,"param",#20060,1,"@param") -#20067=@"loc,{#10000},9,5,9,10" -locations_default(#20067,#10000,9,5,9,10) -hasLocation(#20066,#20067) -jsdoc_tag_names(#20066,"ys") -#20068=* -jsdoc_type_exprs(#20068,6,#20066,0,"Array.") +lines(#20065,#20001,"/**"," +") +#20066=@"loc,{#10000},23,1,23,3" +locations_default(#20066,#10000,23,1,23,3) +hasLocation(#20065,#20066) +#20067=* +lines(#20067,#20001," * @typedef"," +") +#20068=@"loc,{#10000},24,1,24,11" +locations_default(#20068,#10000,24,1,24,11) +hasLocation(#20067,#20068) +indentation(#10000,24," ",1) #20069=* -jsdoc_type_exprs(#20069,5,#20068,-1,"Array") -#20070=* -jsdoc_type_exprs(#20070,5,#20068,0,"String") +lines(#20069,#20001," * {a}"," +") +#20070=@"loc,{#10000},25,1,25,6" +locations_default(#20070,#10000,25,1,25,6) +hasLocation(#20069,#20070) +indentation(#10000,25," ",1) #20071=* -jsdoc_type_exprs(#20071,5,#20068,1,"Number") -#20072=* -jsdoc_tags(#20072,"param",#20060,2,"@param") -#20073=@"loc,{#10000},10,5,10,10" -locations_default(#20073,#10000,10,5,10,10) -hasLocation(#20072,#20073) -jsdoc_tag_names(#20072,"zs") -#20074=* -jsdoc_type_exprs(#20074,6,#20072,0,"Array.") +lines(#20071,#20001," */"," +") +#20072=@"loc,{#10000},26,1,26,3" +locations_default(#20072,#10000,26,1,26,3) +hasLocation(#20071,#20072) +indentation(#10000,26," ",1) +#20073=* +lines(#20073,#20001,""," +") +#20074=@"loc,{#10000},27,1,27,0" +locations_default(#20074,#10000,27,1,27,0) +hasLocation(#20073,#20074) #20075=* -jsdoc_type_exprs(#20075,5,#20074,-1,"Array") -#20076=* -jsdoc_type_exprs(#20076,5,#20074,0,"String") +lines(#20075,#20001,"/**"," +") +#20076=@"loc,{#10000},28,1,28,3" +locations_default(#20076,#10000,28,1,28,3) +hasLocation(#20075,#20076) #20077=* -jsdoc_tags(#20077,"param",#20060,3,"@param") -#20078=@"loc,{#10000},11,5,11,10" -locations_default(#20078,#10000,11,5,11,10) +lines(#20077,#20001," * [resize description]"," +") +#20078=@"loc,{#10000},29,1,29,23" +locations_default(#20078,#10000,29,1,29,23) hasLocation(#20077,#20078) -jsdoc_tag_names(#20077,"f") +indentation(#10000,29," ",1) #20079=* -jsdoc_type_exprs(#20079,12,#20077,0,"function (new: goog.ui.Menu, ?string=, number=): void") -#20080=* -jsdoc_type_exprs(#20080,13,#20079,0,"?string=") +lines(#20079,#20001," * @param {[type]} w [description]"," +") +#20080=@"loc,{#10000},30,1,30,35" +locations_default(#20080,#10000,30,1,30,35) +hasLocation(#20079,#20080) +indentation(#10000,30," ",1) #20081=* -jsdoc_type_exprs(#20081,7,#20080,0,"?string") -#20082=* -jsdoc_type_exprs(#20082,5,#20081,0,"string") -jsdoc_prefix_qualifier(#20081) +lines(#20081,#20001," * @param { } h [description]"," +") +#20082=@"loc,{#10000},31,1,31,31" +locations_default(#20082,#10000,31,1,31,31) +hasLocation(#20081,#20082) +indentation(#10000,31," ",1) #20083=* -jsdoc_type_exprs(#20083,13,#20079,1,"number=") -#20084=* -jsdoc_type_exprs(#20084,5,#20083,0,"number") +lines(#20083,#20001," * @return {[type]} [description]"," +") +#20084=@"loc,{#10000},32,1,32,35" +locations_default(#20084,#10000,32,1,32,35) +hasLocation(#20083,#20084) +indentation(#10000,32," ",1) #20085=* -jsdoc_type_exprs(#20085,4,#20079,-1,"void") -#20086=* -jsdoc_type_exprs(#20086,5,#20079,-2,"goog.ui.Menu") -jsdoc_has_new_parameter(#20079) +lines(#20085,#20001," */"," +") +#20086=@"loc,{#10000},33,1,33,3" +locations_default(#20086,#10000,33,1,33,3) +hasLocation(#20085,#20086) +indentation(#10000,33," ",1) #20087=* -jsdoc_tags(#20087,"param",#20060,4,"@param") -#20088=@"loc,{#10000},12,5,12,10" -locations_default(#20088,#10000,12,5,12,10) +lines(#20087,#20001,""," +") +#20088=@"loc,{#10000},34,1,34,0" +locations_default(#20088,#10000,34,1,34,0) hasLocation(#20087,#20088) -jsdoc_tag_names(#20087,"var_args") #20089=* -jsdoc_type_exprs(#20089,14,#20087,0,"...number") -#20090=* -jsdoc_type_exprs(#20090,5,#20089,0,"number") +lines(#20089,#20001,"/**"," +") +#20090=@"loc,{#10000},35,1,35,3" +locations_default(#20090,#10000,35,1,35,3) +hasLocation(#20089,#20090) #20091=* -jsdoc(#20091,"",#20011) -hasLocation(#20091,#20012) -#20092=* -jsdoc_tags(#20092,"param",#20091,0,"@param") -#20093=@"loc,{#10000},15,4,15,9" -locations_default(#20093,#10000,15,4,15,9) -hasLocation(#20092,#20093) -#20094=* -jsdoc_errors(#20094,#20092,"Missing or invalid tag name","Missing ... ag name") +lines(#20091,#20001,"* @exports R"," +") +#20092=@"loc,{#10000},36,1,36,12" +locations_default(#20092,#10000,36,1,36,12) +hasLocation(#20091,#20092) +#20093=* +lines(#20093,#20001,"*"," +") +#20094=@"loc,{#10000},37,1,37,1" +locations_default(#20094,#10000,37,1,37,1) +hasLocation(#20093,#20094) #20095=* -jsdoc_tags(#20095,"param",#20091,1,"@param") -#20096=@"loc,{#10000},16,4,16,9" -locations_default(#20096,#10000,16,4,16,9) +lines(#20095,#20001,"*/"," +") +#20096=@"loc,{#10000},38,1,38,2" +locations_default(#20096,#10000,38,1,38,2) hasLocation(#20095,#20096) -jsdoc_tag_names(#20095,"x") -numlines(#10000,17,0,17) +#20097=* +lines(#20097,#20001,""," +") +#20098=@"loc,{#10000},39,1,39,0" +locations_default(#20098,#10000,39,1,39,0) +hasLocation(#20097,#20098) +#20099=* +lines(#20099,#20001,"/**"," +") +#20100=@"loc,{#10000},40,1,40,3" +locations_default(#20100,#10000,40,1,40,3) +hasLocation(#20099,#20100) +#20101=* +lines(#20101,#20001," * @typedef {{0: number}}"," +") +#20102=@"loc,{#10000},41,1,41,25" +locations_default(#20102,#10000,41,1,41,25) +hasLocation(#20101,#20102) +indentation(#10000,41," ",1) +#20103=* +lines(#20103,#20001," */"," +") +#20104=@"loc,{#10000},42,1,42,3" +locations_default(#20104,#10000,42,1,42,3) +hasLocation(#20103,#20104) +indentation(#10000,42," ",1) +numlines(#20001,42,0,37) +#20105=* +tokeninfo(#20105,0,#20001,0,"") +#20106=@"loc,{#10000},43,1,43,0" +locations_default(#20106,#10000,43,1,43,0) +hasLocation(#20105,#20106) +next_token(#20003,#20105) +next_token(#20005,#20105) +next_token(#20007,#20105) +next_token(#20009,#20105) +next_token(#20011,#20105) +next_token(#20013,#20105) +next_token(#20015,#20105) +next_token(#20017,#20105) +next_token(#20019,#20105) +next_token(#20021,#20105) +#20107=* +entry_cfg_node(#20107,#20001) +#20108=@"loc,{#10000},1,1,1,0" +locations_default(#20108,#10000,1,1,1,0) +hasLocation(#20107,#20108) +#20109=* +exit_cfg_node(#20109,#20001) +hasLocation(#20109,#20106) +successor(#20107,#20109) +#20110=* +jsdoc(#20110,"This is a constant.",#20003) +hasLocation(#20110,#20004) +#20111=* +jsdoc_tags(#20111,"const",#20110,0,"@const") +#20112=@"loc,{#10000},4,4,4,9" +locations_default(#20112,#10000,4,4,4,9) +hasLocation(#20111,#20112) +jsdoc_tag_names(#20111,"x") +#20113=* +jsdoc(#20113,"",#20005) +hasLocation(#20113,#20006) +#20114=* +jsdoc_tags(#20114,"class",#20113,0,"@class") +#20115=@"loc,{#10000},6,5,6,10" +locations_default(#20115,#10000,6,5,6,10) +hasLocation(#20114,#20115) +jsdoc_tag_names(#20114,"klass") +#20116=* +jsdoc_type_exprs(#20116,5,#20114,0,"Object") +#20117=* +jsdoc(#20117,"",#20007) +hasLocation(#20117,#20008) +#20118=* +jsdoc_tags(#20118,"deprecated",#20117,0,"@deprecated") +#20119=@"loc,{#10000},7,5,7,15" +locations_default(#20119,#10000,7,5,7,15) +hasLocation(#20118,#20119) +#20120=* +jsdoc(#20120,"",#20009) +hasLocation(#20120,#20010) +#20121=* +jsdoc_tags(#20121,"param",#20120,0,"@param") +#20122=@"loc,{#10000},8,5,8,10" +locations_default(#20122,#10000,8,5,8,10) +hasLocation(#20121,#20122) +jsdoc_tag_names(#20121,"x") +#20123=* +jsdoc_type_exprs(#20123,11,#20121,0,"(int|bool)") +#20124=* +jsdoc_type_exprs(#20124,5,#20123,0,"int") +#20125=* +jsdoc_type_exprs(#20125,5,#20123,1,"bool") +#20126=* +jsdoc_tags(#20126,"param",#20120,1,"@param") +#20127=@"loc,{#10000},9,5,9,10" +locations_default(#20127,#10000,9,5,9,10) +hasLocation(#20126,#20127) +jsdoc_tag_names(#20126,"ys") +#20128=* +jsdoc_type_exprs(#20128,6,#20126,0,"Array.") +#20129=* +jsdoc_type_exprs(#20129,5,#20128,-1,"Array") +#20130=* +jsdoc_type_exprs(#20130,5,#20128,0,"String") +#20131=* +jsdoc_type_exprs(#20131,5,#20128,1,"Number") +#20132=* +jsdoc_tags(#20132,"param",#20120,2,"@param") +#20133=@"loc,{#10000},10,5,10,10" +locations_default(#20133,#10000,10,5,10,10) +hasLocation(#20132,#20133) +jsdoc_tag_names(#20132,"zs") +#20134=* +jsdoc_type_exprs(#20134,6,#20132,0,"Array.") +#20135=* +jsdoc_type_exprs(#20135,5,#20134,-1,"Array") +#20136=* +jsdoc_type_exprs(#20136,5,#20134,0,"String") +#20137=* +jsdoc_tags(#20137,"param",#20120,3,"@param") +#20138=@"loc,{#10000},11,5,11,10" +locations_default(#20138,#10000,11,5,11,10) +hasLocation(#20137,#20138) +jsdoc_tag_names(#20137,"f") +#20139=* +jsdoc_type_exprs(#20139,12,#20137,0,"function (new: goog.ui.Menu, ?string=, number=): void") +#20140=* +jsdoc_type_exprs(#20140,13,#20139,0,"?string=") +#20141=* +jsdoc_type_exprs(#20141,7,#20140,0,"?string") +#20142=* +jsdoc_type_exprs(#20142,5,#20141,0,"string") +jsdoc_prefix_qualifier(#20141) +#20143=* +jsdoc_type_exprs(#20143,13,#20139,1,"number=") +#20144=* +jsdoc_type_exprs(#20144,5,#20143,0,"number") +#20145=* +jsdoc_type_exprs(#20145,4,#20139,-1,"void") +#20146=* +jsdoc_type_exprs(#20146,5,#20139,-2,"goog.ui.Menu") +jsdoc_has_new_parameter(#20139) +#20147=* +jsdoc_tags(#20147,"param",#20120,4,"@param") +#20148=@"loc,{#10000},12,5,12,10" +locations_default(#20148,#10000,12,5,12,10) +hasLocation(#20147,#20148) +jsdoc_tag_names(#20147,"var_args") +#20149=* +jsdoc_type_exprs(#20149,14,#20147,0,"...number") +#20150=* +jsdoc_type_exprs(#20150,5,#20149,0,"number") +#20151=* +jsdoc(#20151,"",#20011) +hasLocation(#20151,#20012) +#20152=* +jsdoc_tags(#20152,"param",#20151,0,"@param") +#20153=@"loc,{#10000},15,4,15,9" +locations_default(#20153,#10000,15,4,15,9) +hasLocation(#20152,#20153) +#20154=* +jsdoc_errors(#20154,#20152,"Missing or invalid tag name","Missing ... ag name") +#20155=* +jsdoc_tags(#20155,"param",#20151,1,"@param") +#20156=@"loc,{#10000},16,4,16,9" +locations_default(#20156,#10000,16,4,16,9) +hasLocation(#20155,#20156) +jsdoc_tag_names(#20155,"x") +#20157=* +jsdoc(#20157,"",#20013) +hasLocation(#20157,#20014) +#20158=* +jsdoc_tags(#20158,"",#20157,0,"@") +#20159=@"loc,{#10000},20,4,20,4" +locations_default(#20159,#10000,20,4,20,4) +hasLocation(#20158,#20159) +jsdoc_tag_descriptions(#20158,"{link a}") +#20160=* +jsdoc_errors(#20160,#20158,"Missing or invalid title","Missing ... d title") +#20161=* +jsdoc(#20161,"",#20015) +hasLocation(#20161,#20016) +#20162=* +jsdoc_tags(#20162,"typedef",#20161,0,"@typedef") +#20163=@"loc,{#10000},24,4,24,11" +locations_default(#20163,#10000,24,4,24,11) +hasLocation(#20162,#20163) +jsdoc_tag_descriptions(#20162,"{a}") +#20164=* +jsdoc_errors(#20164,#20162,"Missing or invalid tag type","Missing ... ag type") +#20165=* +jsdoc(#20165,"[resize description]",#20017) +hasLocation(#20165,#20018) +#20166=* +jsdoc_tags(#20166,"param",#20165,0,"@param") +#20167=@"loc,{#10000},30,4,30,9" +locations_default(#20167,#10000,30,4,30,9) +hasLocation(#20166,#20167) +jsdoc_tag_descriptions(#20166,"[description] +") +jsdoc_tag_names(#20166,"w") +#20168=* +jsdoc_type_exprs(#20168,10,#20166,0,"[type]") +#20169=* +jsdoc_type_exprs(#20169,5,#20168,0,"type") +#20170=* +jsdoc_tags(#20170,"param",#20165,1,"@param") +#20171=@"loc,{#10000},31,4,31,9" +locations_default(#20171,#10000,31,4,31,9) +hasLocation(#20170,#20171) +jsdoc_tag_descriptions(#20170,"[description] +") +#20172=* +jsdoc_tags(#20172,"return",#20165,2,"@return") +#20173=@"loc,{#10000},32,4,32,10" +locations_default(#20173,#10000,32,4,32,10) +hasLocation(#20172,#20173) +jsdoc_tag_descriptions(#20172,"[description]") +#20174=* +jsdoc_type_exprs(#20174,10,#20172,0,"[type]") +#20175=* +jsdoc_type_exprs(#20175,5,#20174,0,"type") +#20176=* +jsdoc(#20176,"",#20019) +hasLocation(#20176,#20020) +#20177=* +jsdoc_tags(#20177,"exports",#20176,0,"@exports") +#20178=@"loc,{#10000},36,3,36,10" +locations_default(#20178,#10000,36,3,36,10) +hasLocation(#20177,#20178) +jsdoc_tag_descriptions(#20177,"R +") +#20179=* +jsdoc(#20179,"",#20021) +hasLocation(#20179,#20022) +#20180=* +jsdoc_tags(#20180,"typedef",#20179,0,"@typedef") +#20181=@"loc,{#10000},41,4,41,11" +locations_default(#20181,#10000,41,4,41,11) +hasLocation(#20180,#20181) +#20182=* +jsdoc_type_exprs(#20182,9,#20180,0,"{0: number}") +jsdoc_record_field_name(#20182,0,"0") +#20183=* +jsdoc_type_exprs(#20183,5,#20182,0,"number") +numlines(#10000,42,0,37) filetype(#10000,"javascript") diff --git a/javascript/extractor/tests/exprs/output/trap/regexp.js.trap b/javascript/extractor/tests/exprs/output/trap/regexp.js.trap index 9a3eb7e3595..b255ddbb8a3 100644 --- a/javascript/extractor/tests/exprs/output/trap/regexp.js.trap +++ b/javascript/extractor/tests/exprs/output/trap/regexp.js.trap @@ -792,1409 +792,1412 @@ locations_default(#20250,#10000,26,2,26,4) hasLocation(#20249,#20250) backref(#20249,10) #20251=* -stmts(#20251,2,#20001,26,"/\t\n\r\f\v/;") -#20252=@"loc,{#10000},27,1,27,13" -locations_default(#20252,#10000,27,1,27,13) -hasLocation(#20251,#20252) -stmtContainers(#20251,#20001) -#20253=* -exprs(#20253,5,#20251,0,"/\t\n\r\f\v/") -#20254=@"loc,{#10000},27,1,27,12" -locations_default(#20254,#10000,27,1,27,12) -hasLocation(#20253,#20254) -enclosingStmt(#20253,#20251) -exprContainers(#20253,#20001) -literals("/\t\n\r\f\v/","/\t\n\r\f\v/",#20253) -#20255=* -regexpterm(#20255,1,#20253,0,"\t\n\r\f\v") -#20256=@"loc,{#10000},27,2,27,11" -locations_default(#20256,#10000,27,2,27,11) -hasLocation(#20255,#20256) -#20257=* -regexpterm(#20257,19,#20255,0,"\t") -#20258=@"loc,{#10000},27,2,27,3" -locations_default(#20258,#10000,27,2,27,3) -hasLocation(#20257,#20258) -regexpConstValue(#20257," ") -#20259=* -regexpterm(#20259,19,#20255,1,"\n") -#20260=@"loc,{#10000},27,4,27,5" -locations_default(#20260,#10000,27,4,27,5) -hasLocation(#20259,#20260) -regexpConstValue(#20259," +regexpParseErrors(#20251,#20249,"invalid back reference") +hasLocation(#20251,#20250) +#20252=* +stmts(#20252,2,#20001,26,"/\t\n\r\f\v/;") +#20253=@"loc,{#10000},27,1,27,13" +locations_default(#20253,#10000,27,1,27,13) +hasLocation(#20252,#20253) +stmtContainers(#20252,#20001) +#20254=* +exprs(#20254,5,#20252,0,"/\t\n\r\f\v/") +#20255=@"loc,{#10000},27,1,27,12" +locations_default(#20255,#10000,27,1,27,12) +hasLocation(#20254,#20255) +enclosingStmt(#20254,#20252) +exprContainers(#20254,#20001) +literals("/\t\n\r\f\v/","/\t\n\r\f\v/",#20254) +#20256=* +regexpterm(#20256,1,#20254,0,"\t\n\r\f\v") +#20257=@"loc,{#10000},27,2,27,11" +locations_default(#20257,#10000,27,2,27,11) +hasLocation(#20256,#20257) +#20258=* +regexpterm(#20258,19,#20256,0,"\t") +#20259=@"loc,{#10000},27,2,27,3" +locations_default(#20259,#10000,27,2,27,3) +hasLocation(#20258,#20259) +regexpConstValue(#20258," ") +#20260=* +regexpterm(#20260,19,#20256,1,"\n") +#20261=@"loc,{#10000},27,4,27,5" +locations_default(#20261,#10000,27,4,27,5) +hasLocation(#20260,#20261) +regexpConstValue(#20260," ") -#20261=* -regexpterm(#20261,19,#20255,2,"\r") -#20262=@"loc,{#10000},27,6,27,7" -locations_default(#20262,#10000,27,6,27,7) -hasLocation(#20261,#20262) -regexpConstValue(#20261," ") -#20263=* -regexpterm(#20263,19,#20255,3,"\f") -#20264=@"loc,{#10000},27,8,27,9" -locations_default(#20264,#10000,27,8,27,9) -hasLocation(#20263,#20264) -regexpConstValue(#20263," ") -#20265=* -regexpterm(#20265,19,#20255,4,"\v") -#20266=@"loc,{#10000},27,10,27,11" -locations_default(#20266,#10000,27,10,27,11) -hasLocation(#20265,#20266) -regexpConstValue(#20265," ") -#20267=* -stmts(#20267,2,#20001,27,"/\ca\cN/;") -#20268=@"loc,{#10000},28,1,28,9" -locations_default(#20268,#10000,28,1,28,9) -hasLocation(#20267,#20268) -stmtContainers(#20267,#20001) -#20269=* -exprs(#20269,5,#20267,0,"/\ca\cN/") -#20270=@"loc,{#10000},28,1,28,8" -locations_default(#20270,#10000,28,1,28,8) -hasLocation(#20269,#20270) -enclosingStmt(#20269,#20267) -exprContainers(#20269,#20001) -literals("/\ca\cN/","/\ca\cN/",#20269) -#20271=* -regexpterm(#20271,1,#20269,0,"\ca\cN") -#20272=@"loc,{#10000},28,2,28,7" -locations_default(#20272,#10000,28,2,28,7) -hasLocation(#20271,#20272) -#20273=* -regexpterm(#20273,19,#20271,0,"\ca") -#20274=@"loc,{#10000},28,2,28,4" -locations_default(#20274,#10000,28,2,28,4) -hasLocation(#20273,#20274) -regexpConstValue(#20273,"") -#20275=* -regexpterm(#20275,19,#20271,1,"\cN") -#20276=@"loc,{#10000},28,5,28,7" -locations_default(#20276,#10000,28,5,28,7) -hasLocation(#20275,#20276) -regexpConstValue(#20275,"") -#20277=* -stmts(#20277,2,#20001,28,"/\w\S/;") -#20278=@"loc,{#10000},29,1,29,7" -locations_default(#20278,#10000,29,1,29,7) -hasLocation(#20277,#20278) -stmtContainers(#20277,#20001) -#20279=* -exprs(#20279,5,#20277,0,"/\w\S/") -#20280=@"loc,{#10000},29,1,29,6" -locations_default(#20280,#10000,29,1,29,6) -hasLocation(#20279,#20280) -enclosingStmt(#20279,#20277) -exprContainers(#20279,#20001) -literals("/\w\S/","/\w\S/",#20279) -#20281=* -regexpterm(#20281,1,#20279,0,"\w\S") -#20282=@"loc,{#10000},29,2,29,5" -locations_default(#20282,#10000,29,2,29,5) -hasLocation(#20281,#20282) -#20283=* -regexpterm(#20283,20,#20281,0,"\w") -#20284=@"loc,{#10000},29,2,29,3" -locations_default(#20284,#10000,29,2,29,3) -hasLocation(#20283,#20284) -charClassEscape(#20283,"w") -#20285=* -regexpterm(#20285,20,#20281,1,"\S") -#20286=@"loc,{#10000},29,4,29,5" -locations_default(#20286,#10000,29,4,29,5) -hasLocation(#20285,#20286) -charClassEscape(#20285,"S") -#20287=* -stmts(#20287,2,#20001,29,"/\\/;") -#20288=@"loc,{#10000},30,1,30,5" -locations_default(#20288,#10000,30,1,30,5) -hasLocation(#20287,#20288) -stmtContainers(#20287,#20001) -#20289=* -exprs(#20289,5,#20287,0,"/\\/") -#20290=@"loc,{#10000},30,1,30,4" -locations_default(#20290,#10000,30,1,30,4) -hasLocation(#20289,#20290) -enclosingStmt(#20289,#20287) -exprContainers(#20289,#20001) -literals("/\\/","/\\/",#20289) -#20291=* -regexpterm(#20291,21,#20289,0,"\\") -#20292=@"loc,{#10000},30,2,30,3" -locations_default(#20292,#10000,30,2,30,3) -hasLocation(#20291,#20292) -regexpConstValue(#20291,"\") -#20293=* -stmts(#20293,2,#20001,30,"/[abc]/;") -#20294=@"loc,{#10000},31,1,31,8" -locations_default(#20294,#10000,31,1,31,8) -hasLocation(#20293,#20294) -stmtContainers(#20293,#20001) -#20295=* -exprs(#20295,5,#20293,0,"/[abc]/") -#20296=@"loc,{#10000},31,1,31,7" -locations_default(#20296,#10000,31,1,31,7) -hasLocation(#20295,#20296) -enclosingStmt(#20295,#20293) -exprContainers(#20295,#20001) -literals("/[abc]/","/[abc]/",#20295) -#20297=* -regexpterm(#20297,23,#20295,0,"[abc]") -#20298=@"loc,{#10000},31,2,31,6" -locations_default(#20298,#10000,31,2,31,6) -hasLocation(#20297,#20298) -#20299=* -regexpterm(#20299,14,#20297,0,"a") -#20300=@"loc,{#10000},31,3,31,3" -locations_default(#20300,#10000,31,3,31,3) -hasLocation(#20299,#20300) -regexpConstValue(#20299,"a") -#20301=* -regexpterm(#20301,14,#20297,1,"b") -#20302=@"loc,{#10000},31,4,31,4" -locations_default(#20302,#10000,31,4,31,4) -hasLocation(#20301,#20302) -regexpConstValue(#20301,"b") -#20303=* -regexpterm(#20303,14,#20297,2,"c") -#20304=@"loc,{#10000},31,5,31,5" -locations_default(#20304,#10000,31,5,31,5) -hasLocation(#20303,#20304) -regexpConstValue(#20303,"c") -#20305=* -stmts(#20305,2,#20001,31,"/[a-z]/;") -#20306=@"loc,{#10000},32,1,32,8" -locations_default(#20306,#10000,32,1,32,8) -hasLocation(#20305,#20306) -stmtContainers(#20305,#20001) -#20307=* -exprs(#20307,5,#20305,0,"/[a-z]/") -#20308=@"loc,{#10000},32,1,32,7" -locations_default(#20308,#10000,32,1,32,7) -hasLocation(#20307,#20308) -enclosingStmt(#20307,#20305) -exprContainers(#20307,#20001) -literals("/[a-z]/","/[a-z]/",#20307) -#20309=* -regexpterm(#20309,23,#20307,0,"[a-z]") -#20310=@"loc,{#10000},32,2,32,6" -locations_default(#20310,#10000,32,2,32,6) -hasLocation(#20309,#20310) -#20311=* -regexpterm(#20311,24,#20309,0,"a-z") -#20312=@"loc,{#10000},32,3,32,5" -locations_default(#20312,#10000,32,3,32,5) -hasLocation(#20311,#20312) -#20313=* -regexpterm(#20313,14,#20311,0,"a") -#20314=@"loc,{#10000},32,3,32,3" -locations_default(#20314,#10000,32,3,32,3) -hasLocation(#20313,#20314) -regexpConstValue(#20313,"a") -#20315=* -regexpterm(#20315,14,#20311,1,"z") -#20316=@"loc,{#10000},32,5,32,5" -locations_default(#20316,#10000,32,5,32,5) -hasLocation(#20315,#20316) -regexpConstValue(#20315,"z") -#20317=* -stmts(#20317,2,#20001,32,"/[a-zA-Z]/;") -#20318=@"loc,{#10000},33,1,33,11" -locations_default(#20318,#10000,33,1,33,11) -hasLocation(#20317,#20318) -stmtContainers(#20317,#20001) -#20319=* -exprs(#20319,5,#20317,0,"/[a-zA-Z]/") -#20320=@"loc,{#10000},33,1,33,10" -locations_default(#20320,#10000,33,1,33,10) -hasLocation(#20319,#20320) -enclosingStmt(#20319,#20317) -exprContainers(#20319,#20001) -literals("/[a-zA-Z]/","/[a-zA-Z]/",#20319) -#20321=* -regexpterm(#20321,23,#20319,0,"[a-zA-Z]") -#20322=@"loc,{#10000},33,2,33,9" -locations_default(#20322,#10000,33,2,33,9) -hasLocation(#20321,#20322) -#20323=* -regexpterm(#20323,24,#20321,0,"a-z") -#20324=@"loc,{#10000},33,3,33,5" -locations_default(#20324,#10000,33,3,33,5) -hasLocation(#20323,#20324) -#20325=* -regexpterm(#20325,14,#20323,0,"a") -#20326=@"loc,{#10000},33,3,33,3" -locations_default(#20326,#10000,33,3,33,3) -hasLocation(#20325,#20326) -regexpConstValue(#20325,"a") -#20327=* -regexpterm(#20327,14,#20323,1,"z") -#20328=@"loc,{#10000},33,5,33,5" -locations_default(#20328,#10000,33,5,33,5) -hasLocation(#20327,#20328) -regexpConstValue(#20327,"z") -#20329=* -regexpterm(#20329,24,#20321,1,"A-Z") -#20330=@"loc,{#10000},33,6,33,8" -locations_default(#20330,#10000,33,6,33,8) -hasLocation(#20329,#20330) -#20331=* -regexpterm(#20331,14,#20329,0,"A") -#20332=@"loc,{#10000},33,6,33,6" -locations_default(#20332,#10000,33,6,33,6) -hasLocation(#20331,#20332) -regexpConstValue(#20331,"A") -#20333=* -regexpterm(#20333,14,#20329,1,"Z") -#20334=@"loc,{#10000},33,8,33,8" -locations_default(#20334,#10000,33,8,33,8) -hasLocation(#20333,#20334) -regexpConstValue(#20333,"Z") -#20335=* -stmts(#20335,2,#20001,33,"/[-a-z]/;") -#20336=@"loc,{#10000},34,1,34,9" -locations_default(#20336,#10000,34,1,34,9) -hasLocation(#20335,#20336) -stmtContainers(#20335,#20001) -#20337=* -exprs(#20337,5,#20335,0,"/[-a-z]/") -#20338=@"loc,{#10000},34,1,34,8" -locations_default(#20338,#10000,34,1,34,8) -hasLocation(#20337,#20338) -enclosingStmt(#20337,#20335) -exprContainers(#20337,#20001) -literals("/[-a-z]/","/[-a-z]/",#20337) -#20339=* -regexpterm(#20339,23,#20337,0,"[-a-z]") -#20340=@"loc,{#10000},34,2,34,7" -locations_default(#20340,#10000,34,2,34,7) -hasLocation(#20339,#20340) -#20341=* -regexpterm(#20341,14,#20339,0,"-") -#20342=@"loc,{#10000},34,3,34,3" -locations_default(#20342,#10000,34,3,34,3) -hasLocation(#20341,#20342) -regexpConstValue(#20341,"-") -#20343=* -regexpterm(#20343,24,#20339,1,"a-z") -#20344=@"loc,{#10000},34,4,34,6" -locations_default(#20344,#10000,34,4,34,6) -hasLocation(#20343,#20344) -#20345=* -regexpterm(#20345,14,#20343,0,"a") -#20346=@"loc,{#10000},34,4,34,4" -locations_default(#20346,#10000,34,4,34,4) -hasLocation(#20345,#20346) -regexpConstValue(#20345,"a") -#20347=* -regexpterm(#20347,14,#20343,1,"z") -#20348=@"loc,{#10000},34,6,34,6" -locations_default(#20348,#10000,34,6,34,6) -hasLocation(#20347,#20348) -regexpConstValue(#20347,"z") -#20349=* -stmts(#20349,2,#20001,34,"/[^a-z]/;") -#20350=@"loc,{#10000},35,1,35,9" -locations_default(#20350,#10000,35,1,35,9) -hasLocation(#20349,#20350) -stmtContainers(#20349,#20001) -#20351=* -exprs(#20351,5,#20349,0,"/[^a-z]/") -#20352=@"loc,{#10000},35,1,35,8" -locations_default(#20352,#10000,35,1,35,8) -hasLocation(#20351,#20352) -enclosingStmt(#20351,#20349) -exprContainers(#20351,#20001) -literals("/[^a-z]/","/[^a-z]/",#20351) -#20353=* -regexpterm(#20353,23,#20351,0,"[^a-z]") -#20354=@"loc,{#10000},35,2,35,7" -locations_default(#20354,#10000,35,2,35,7) -hasLocation(#20353,#20354) -isInverted(#20353) -#20355=* -regexpterm(#20355,24,#20353,0,"a-z") -#20356=@"loc,{#10000},35,4,35,6" -locations_default(#20356,#10000,35,4,35,6) -hasLocation(#20355,#20356) -#20357=* -regexpterm(#20357,14,#20355,0,"a") -#20358=@"loc,{#10000},35,4,35,4" -locations_default(#20358,#10000,35,4,35,4) -hasLocation(#20357,#20358) -regexpConstValue(#20357,"a") -#20359=* -regexpterm(#20359,14,#20355,1,"z") -#20360=@"loc,{#10000},35,6,35,6" -locations_default(#20360,#10000,35,6,35,6) -hasLocation(#20359,#20360) -regexpConstValue(#20359,"z") -#20361=* -stmts(#20361,2,#20001,35,"/[a\b\x0c]/;") -#20362=@"loc,{#10000},36,1,36,12" -locations_default(#20362,#10000,36,1,36,12) -hasLocation(#20361,#20362) -stmtContainers(#20361,#20001) -#20363=* -exprs(#20363,5,#20361,0,"/[a\b\x0c]/") -#20364=@"loc,{#10000},36,1,36,11" -locations_default(#20364,#10000,36,1,36,11) -hasLocation(#20363,#20364) -enclosingStmt(#20363,#20361) -exprContainers(#20363,#20001) -literals("/[a\b\x0c]/","/[a\b\x0c]/",#20363) -#20365=* -regexpterm(#20365,23,#20363,0,"[a\b\x0c]") -#20366=@"loc,{#10000},36,2,36,10" -locations_default(#20366,#10000,36,2,36,10) -hasLocation(#20365,#20366) -#20367=* -regexpterm(#20367,14,#20365,0,"a") -#20368=@"loc,{#10000},36,3,36,3" -locations_default(#20368,#10000,36,3,36,3) -hasLocation(#20367,#20368) -regexpConstValue(#20367,"a") -#20369=* -regexpterm(#20369,19,#20365,1,"\b") -#20370=@"loc,{#10000},36,4,36,5" -locations_default(#20370,#10000,36,4,36,5) -hasLocation(#20369,#20370) -regexpConstValue(#20369,"") -#20371=* -regexpterm(#20371,15,#20365,2,"\x0c") -#20372=@"loc,{#10000},36,6,36,9" -locations_default(#20372,#10000,36,6,36,9) -hasLocation(#20371,#20372) -regexpConstValue(#20371," ") -#20373=* -stmts(#20373,2,#20001,36,"/a{/;") -#20374=@"loc,{#10000},37,1,37,5" -locations_default(#20374,#10000,37,1,37,5) -hasLocation(#20373,#20374) -stmtContainers(#20373,#20001) -#20375=* -exprs(#20375,5,#20373,0,"/a{/") -#20376=@"loc,{#10000},37,1,37,4" -locations_default(#20376,#10000,37,1,37,4) -hasLocation(#20375,#20376) -enclosingStmt(#20375,#20373) -exprContainers(#20375,#20001) -literals("/a{/","/a{/",#20375) -#20377=* -regexpterm(#20377,11,#20375,0,"a{") -#20378=@"loc,{#10000},37,2,37,3" -locations_default(#20378,#10000,37,2,37,3) -hasLocation(#20377,#20378) -isGreedy(#20377) -rangeQuantifierLowerBound(#20377,0) -#20379=* -regexpterm(#20379,14,#20377,0,"a") -#20380=@"loc,{#10000},37,2,37,2" -locations_default(#20380,#10000,37,2,37,2) -hasLocation(#20379,#20380) -regexpConstValue(#20379,"a") -#20381=* -regexpParseErrors(#20381,#20377,"expected digit") -#20382=@"loc,{#10000},37,4,37,4" -locations_default(#20382,#10000,37,4,37,4) -hasLocation(#20381,#20382) -#20383=* -regexpParseErrors(#20383,#20377,"expected '}'") -#20384=@"loc,{#10000},37,3,37,3" -locations_default(#20384,#10000,37,3,37,3) -hasLocation(#20383,#20384) -#20385=* -stmts(#20385,2,#20001,37,"/a{b}/;") -#20386=@"loc,{#10000},38,1,38,7" -locations_default(#20386,#10000,38,1,38,7) -hasLocation(#20385,#20386) -stmtContainers(#20385,#20001) -#20387=* -exprs(#20387,5,#20385,0,"/a{b}/") -#20388=@"loc,{#10000},38,1,38,6" -locations_default(#20388,#10000,38,1,38,6) -hasLocation(#20387,#20388) -enclosingStmt(#20387,#20385) -exprContainers(#20387,#20001) -literals("/a{b}/","/a{b}/",#20387) -#20389=* -regexpterm(#20389,1,#20387,0,"a{b}") -#20390=@"loc,{#10000},38,2,38,5" -locations_default(#20390,#10000,38,2,38,5) -hasLocation(#20389,#20390) -#20391=* -regexpterm(#20391,11,#20389,0,"a{") -#20392=@"loc,{#10000},38,2,38,3" -locations_default(#20392,#10000,38,2,38,3) -hasLocation(#20391,#20392) -isGreedy(#20391) -rangeQuantifierLowerBound(#20391,0) -#20393=* -regexpterm(#20393,14,#20391,0,"a") -#20394=@"loc,{#10000},38,2,38,2" -locations_default(#20394,#10000,38,2,38,2) -hasLocation(#20393,#20394) -regexpConstValue(#20393,"a") -#20395=* -regexpterm(#20395,14,#20389,1,"b") -#20396=@"loc,{#10000},38,4,38,4" -locations_default(#20396,#10000,38,4,38,4) -hasLocation(#20395,#20396) -regexpConstValue(#20395,"b") -#20397=* -regexpterm(#20397,14,#20389,2,"}") -#20398=@"loc,{#10000},38,5,38,5" -locations_default(#20398,#10000,38,5,38,5) -hasLocation(#20397,#20398) -regexpConstValue(#20397,"}") -#20399=* -regexpParseErrors(#20399,#20389,"expected digit") -hasLocation(#20399,#20396) +#20262=* +regexpterm(#20262,19,#20256,2,"\r") +#20263=@"loc,{#10000},27,6,27,7" +locations_default(#20263,#10000,27,6,27,7) +hasLocation(#20262,#20263) +regexpConstValue(#20262," ") +#20264=* +regexpterm(#20264,19,#20256,3,"\f") +#20265=@"loc,{#10000},27,8,27,9" +locations_default(#20265,#10000,27,8,27,9) +hasLocation(#20264,#20265) +regexpConstValue(#20264," ") +#20266=* +regexpterm(#20266,19,#20256,4,"\v") +#20267=@"loc,{#10000},27,10,27,11" +locations_default(#20267,#10000,27,10,27,11) +hasLocation(#20266,#20267) +regexpConstValue(#20266," ") +#20268=* +stmts(#20268,2,#20001,27,"/\ca\cN/;") +#20269=@"loc,{#10000},28,1,28,9" +locations_default(#20269,#10000,28,1,28,9) +hasLocation(#20268,#20269) +stmtContainers(#20268,#20001) +#20270=* +exprs(#20270,5,#20268,0,"/\ca\cN/") +#20271=@"loc,{#10000},28,1,28,8" +locations_default(#20271,#10000,28,1,28,8) +hasLocation(#20270,#20271) +enclosingStmt(#20270,#20268) +exprContainers(#20270,#20001) +literals("/\ca\cN/","/\ca\cN/",#20270) +#20272=* +regexpterm(#20272,1,#20270,0,"\ca\cN") +#20273=@"loc,{#10000},28,2,28,7" +locations_default(#20273,#10000,28,2,28,7) +hasLocation(#20272,#20273) +#20274=* +regexpterm(#20274,19,#20272,0,"\ca") +#20275=@"loc,{#10000},28,2,28,4" +locations_default(#20275,#10000,28,2,28,4) +hasLocation(#20274,#20275) +regexpConstValue(#20274,"") +#20276=* +regexpterm(#20276,19,#20272,1,"\cN") +#20277=@"loc,{#10000},28,5,28,7" +locations_default(#20277,#10000,28,5,28,7) +hasLocation(#20276,#20277) +regexpConstValue(#20276,"") +#20278=* +stmts(#20278,2,#20001,28,"/\w\S/;") +#20279=@"loc,{#10000},29,1,29,7" +locations_default(#20279,#10000,29,1,29,7) +hasLocation(#20278,#20279) +stmtContainers(#20278,#20001) +#20280=* +exprs(#20280,5,#20278,0,"/\w\S/") +#20281=@"loc,{#10000},29,1,29,6" +locations_default(#20281,#10000,29,1,29,6) +hasLocation(#20280,#20281) +enclosingStmt(#20280,#20278) +exprContainers(#20280,#20001) +literals("/\w\S/","/\w\S/",#20280) +#20282=* +regexpterm(#20282,1,#20280,0,"\w\S") +#20283=@"loc,{#10000},29,2,29,5" +locations_default(#20283,#10000,29,2,29,5) +hasLocation(#20282,#20283) +#20284=* +regexpterm(#20284,20,#20282,0,"\w") +#20285=@"loc,{#10000},29,2,29,3" +locations_default(#20285,#10000,29,2,29,3) +hasLocation(#20284,#20285) +charClassEscape(#20284,"w") +#20286=* +regexpterm(#20286,20,#20282,1,"\S") +#20287=@"loc,{#10000},29,4,29,5" +locations_default(#20287,#10000,29,4,29,5) +hasLocation(#20286,#20287) +charClassEscape(#20286,"S") +#20288=* +stmts(#20288,2,#20001,29,"/\\/;") +#20289=@"loc,{#10000},30,1,30,5" +locations_default(#20289,#10000,30,1,30,5) +hasLocation(#20288,#20289) +stmtContainers(#20288,#20001) +#20290=* +exprs(#20290,5,#20288,0,"/\\/") +#20291=@"loc,{#10000},30,1,30,4" +locations_default(#20291,#10000,30,1,30,4) +hasLocation(#20290,#20291) +enclosingStmt(#20290,#20288) +exprContainers(#20290,#20001) +literals("/\\/","/\\/",#20290) +#20292=* +regexpterm(#20292,21,#20290,0,"\\") +#20293=@"loc,{#10000},30,2,30,3" +locations_default(#20293,#10000,30,2,30,3) +hasLocation(#20292,#20293) +regexpConstValue(#20292,"\") +#20294=* +stmts(#20294,2,#20001,30,"/[abc]/;") +#20295=@"loc,{#10000},31,1,31,8" +locations_default(#20295,#10000,31,1,31,8) +hasLocation(#20294,#20295) +stmtContainers(#20294,#20001) +#20296=* +exprs(#20296,5,#20294,0,"/[abc]/") +#20297=@"loc,{#10000},31,1,31,7" +locations_default(#20297,#10000,31,1,31,7) +hasLocation(#20296,#20297) +enclosingStmt(#20296,#20294) +exprContainers(#20296,#20001) +literals("/[abc]/","/[abc]/",#20296) +#20298=* +regexpterm(#20298,23,#20296,0,"[abc]") +#20299=@"loc,{#10000},31,2,31,6" +locations_default(#20299,#10000,31,2,31,6) +hasLocation(#20298,#20299) +#20300=* +regexpterm(#20300,14,#20298,0,"a") +#20301=@"loc,{#10000},31,3,31,3" +locations_default(#20301,#10000,31,3,31,3) +hasLocation(#20300,#20301) +regexpConstValue(#20300,"a") +#20302=* +regexpterm(#20302,14,#20298,1,"b") +#20303=@"loc,{#10000},31,4,31,4" +locations_default(#20303,#10000,31,4,31,4) +hasLocation(#20302,#20303) +regexpConstValue(#20302,"b") +#20304=* +regexpterm(#20304,14,#20298,2,"c") +#20305=@"loc,{#10000},31,5,31,5" +locations_default(#20305,#10000,31,5,31,5) +hasLocation(#20304,#20305) +regexpConstValue(#20304,"c") +#20306=* +stmts(#20306,2,#20001,31,"/[a-z]/;") +#20307=@"loc,{#10000},32,1,32,8" +locations_default(#20307,#10000,32,1,32,8) +hasLocation(#20306,#20307) +stmtContainers(#20306,#20001) +#20308=* +exprs(#20308,5,#20306,0,"/[a-z]/") +#20309=@"loc,{#10000},32,1,32,7" +locations_default(#20309,#10000,32,1,32,7) +hasLocation(#20308,#20309) +enclosingStmt(#20308,#20306) +exprContainers(#20308,#20001) +literals("/[a-z]/","/[a-z]/",#20308) +#20310=* +regexpterm(#20310,23,#20308,0,"[a-z]") +#20311=@"loc,{#10000},32,2,32,6" +locations_default(#20311,#10000,32,2,32,6) +hasLocation(#20310,#20311) +#20312=* +regexpterm(#20312,24,#20310,0,"a-z") +#20313=@"loc,{#10000},32,3,32,5" +locations_default(#20313,#10000,32,3,32,5) +hasLocation(#20312,#20313) +#20314=* +regexpterm(#20314,14,#20312,0,"a") +#20315=@"loc,{#10000},32,3,32,3" +locations_default(#20315,#10000,32,3,32,3) +hasLocation(#20314,#20315) +regexpConstValue(#20314,"a") +#20316=* +regexpterm(#20316,14,#20312,1,"z") +#20317=@"loc,{#10000},32,5,32,5" +locations_default(#20317,#10000,32,5,32,5) +hasLocation(#20316,#20317) +regexpConstValue(#20316,"z") +#20318=* +stmts(#20318,2,#20001,32,"/[a-zA-Z]/;") +#20319=@"loc,{#10000},33,1,33,11" +locations_default(#20319,#10000,33,1,33,11) +hasLocation(#20318,#20319) +stmtContainers(#20318,#20001) +#20320=* +exprs(#20320,5,#20318,0,"/[a-zA-Z]/") +#20321=@"loc,{#10000},33,1,33,10" +locations_default(#20321,#10000,33,1,33,10) +hasLocation(#20320,#20321) +enclosingStmt(#20320,#20318) +exprContainers(#20320,#20001) +literals("/[a-zA-Z]/","/[a-zA-Z]/",#20320) +#20322=* +regexpterm(#20322,23,#20320,0,"[a-zA-Z]") +#20323=@"loc,{#10000},33,2,33,9" +locations_default(#20323,#10000,33,2,33,9) +hasLocation(#20322,#20323) +#20324=* +regexpterm(#20324,24,#20322,0,"a-z") +#20325=@"loc,{#10000},33,3,33,5" +locations_default(#20325,#10000,33,3,33,5) +hasLocation(#20324,#20325) +#20326=* +regexpterm(#20326,14,#20324,0,"a") +#20327=@"loc,{#10000},33,3,33,3" +locations_default(#20327,#10000,33,3,33,3) +hasLocation(#20326,#20327) +regexpConstValue(#20326,"a") +#20328=* +regexpterm(#20328,14,#20324,1,"z") +#20329=@"loc,{#10000},33,5,33,5" +locations_default(#20329,#10000,33,5,33,5) +hasLocation(#20328,#20329) +regexpConstValue(#20328,"z") +#20330=* +regexpterm(#20330,24,#20322,1,"A-Z") +#20331=@"loc,{#10000},33,6,33,8" +locations_default(#20331,#10000,33,6,33,8) +hasLocation(#20330,#20331) +#20332=* +regexpterm(#20332,14,#20330,0,"A") +#20333=@"loc,{#10000},33,6,33,6" +locations_default(#20333,#10000,33,6,33,6) +hasLocation(#20332,#20333) +regexpConstValue(#20332,"A") +#20334=* +regexpterm(#20334,14,#20330,1,"Z") +#20335=@"loc,{#10000},33,8,33,8" +locations_default(#20335,#10000,33,8,33,8) +hasLocation(#20334,#20335) +regexpConstValue(#20334,"Z") +#20336=* +stmts(#20336,2,#20001,33,"/[-a-z]/;") +#20337=@"loc,{#10000},34,1,34,9" +locations_default(#20337,#10000,34,1,34,9) +hasLocation(#20336,#20337) +stmtContainers(#20336,#20001) +#20338=* +exprs(#20338,5,#20336,0,"/[-a-z]/") +#20339=@"loc,{#10000},34,1,34,8" +locations_default(#20339,#10000,34,1,34,8) +hasLocation(#20338,#20339) +enclosingStmt(#20338,#20336) +exprContainers(#20338,#20001) +literals("/[-a-z]/","/[-a-z]/",#20338) +#20340=* +regexpterm(#20340,23,#20338,0,"[-a-z]") +#20341=@"loc,{#10000},34,2,34,7" +locations_default(#20341,#10000,34,2,34,7) +hasLocation(#20340,#20341) +#20342=* +regexpterm(#20342,14,#20340,0,"-") +#20343=@"loc,{#10000},34,3,34,3" +locations_default(#20343,#10000,34,3,34,3) +hasLocation(#20342,#20343) +regexpConstValue(#20342,"-") +#20344=* +regexpterm(#20344,24,#20340,1,"a-z") +#20345=@"loc,{#10000},34,4,34,6" +locations_default(#20345,#10000,34,4,34,6) +hasLocation(#20344,#20345) +#20346=* +regexpterm(#20346,14,#20344,0,"a") +#20347=@"loc,{#10000},34,4,34,4" +locations_default(#20347,#10000,34,4,34,4) +hasLocation(#20346,#20347) +regexpConstValue(#20346,"a") +#20348=* +regexpterm(#20348,14,#20344,1,"z") +#20349=@"loc,{#10000},34,6,34,6" +locations_default(#20349,#10000,34,6,34,6) +hasLocation(#20348,#20349) +regexpConstValue(#20348,"z") +#20350=* +stmts(#20350,2,#20001,34,"/[^a-z]/;") +#20351=@"loc,{#10000},35,1,35,9" +locations_default(#20351,#10000,35,1,35,9) +hasLocation(#20350,#20351) +stmtContainers(#20350,#20001) +#20352=* +exprs(#20352,5,#20350,0,"/[^a-z]/") +#20353=@"loc,{#10000},35,1,35,8" +locations_default(#20353,#10000,35,1,35,8) +hasLocation(#20352,#20353) +enclosingStmt(#20352,#20350) +exprContainers(#20352,#20001) +literals("/[^a-z]/","/[^a-z]/",#20352) +#20354=* +regexpterm(#20354,23,#20352,0,"[^a-z]") +#20355=@"loc,{#10000},35,2,35,7" +locations_default(#20355,#10000,35,2,35,7) +hasLocation(#20354,#20355) +isInverted(#20354) +#20356=* +regexpterm(#20356,24,#20354,0,"a-z") +#20357=@"loc,{#10000},35,4,35,6" +locations_default(#20357,#10000,35,4,35,6) +hasLocation(#20356,#20357) +#20358=* +regexpterm(#20358,14,#20356,0,"a") +#20359=@"loc,{#10000},35,4,35,4" +locations_default(#20359,#10000,35,4,35,4) +hasLocation(#20358,#20359) +regexpConstValue(#20358,"a") +#20360=* +regexpterm(#20360,14,#20356,1,"z") +#20361=@"loc,{#10000},35,6,35,6" +locations_default(#20361,#10000,35,6,35,6) +hasLocation(#20360,#20361) +regexpConstValue(#20360,"z") +#20362=* +stmts(#20362,2,#20001,35,"/[a\b\x0c]/;") +#20363=@"loc,{#10000},36,1,36,12" +locations_default(#20363,#10000,36,1,36,12) +hasLocation(#20362,#20363) +stmtContainers(#20362,#20001) +#20364=* +exprs(#20364,5,#20362,0,"/[a\b\x0c]/") +#20365=@"loc,{#10000},36,1,36,11" +locations_default(#20365,#10000,36,1,36,11) +hasLocation(#20364,#20365) +enclosingStmt(#20364,#20362) +exprContainers(#20364,#20001) +literals("/[a\b\x0c]/","/[a\b\x0c]/",#20364) +#20366=* +regexpterm(#20366,23,#20364,0,"[a\b\x0c]") +#20367=@"loc,{#10000},36,2,36,10" +locations_default(#20367,#10000,36,2,36,10) +hasLocation(#20366,#20367) +#20368=* +regexpterm(#20368,14,#20366,0,"a") +#20369=@"loc,{#10000},36,3,36,3" +locations_default(#20369,#10000,36,3,36,3) +hasLocation(#20368,#20369) +regexpConstValue(#20368,"a") +#20370=* +regexpterm(#20370,19,#20366,1,"\b") +#20371=@"loc,{#10000},36,4,36,5" +locations_default(#20371,#10000,36,4,36,5) +hasLocation(#20370,#20371) +regexpConstValue(#20370,"") +#20372=* +regexpterm(#20372,15,#20366,2,"\x0c") +#20373=@"loc,{#10000},36,6,36,9" +locations_default(#20373,#10000,36,6,36,9) +hasLocation(#20372,#20373) +regexpConstValue(#20372," ") +#20374=* +stmts(#20374,2,#20001,36,"/a{/;") +#20375=@"loc,{#10000},37,1,37,5" +locations_default(#20375,#10000,37,1,37,5) +hasLocation(#20374,#20375) +stmtContainers(#20374,#20001) +#20376=* +exprs(#20376,5,#20374,0,"/a{/") +#20377=@"loc,{#10000},37,1,37,4" +locations_default(#20377,#10000,37,1,37,4) +hasLocation(#20376,#20377) +enclosingStmt(#20376,#20374) +exprContainers(#20376,#20001) +literals("/a{/","/a{/",#20376) +#20378=* +regexpterm(#20378,11,#20376,0,"a{") +#20379=@"loc,{#10000},37,2,37,3" +locations_default(#20379,#10000,37,2,37,3) +hasLocation(#20378,#20379) +isGreedy(#20378) +rangeQuantifierLowerBound(#20378,0) +#20380=* +regexpterm(#20380,14,#20378,0,"a") +#20381=@"loc,{#10000},37,2,37,2" +locations_default(#20381,#10000,37,2,37,2) +hasLocation(#20380,#20381) +regexpConstValue(#20380,"a") +#20382=* +regexpParseErrors(#20382,#20378,"expected digit") +#20383=@"loc,{#10000},37,4,37,4" +locations_default(#20383,#10000,37,4,37,4) +hasLocation(#20382,#20383) +#20384=* +regexpParseErrors(#20384,#20378,"expected '}'") +#20385=@"loc,{#10000},37,3,37,3" +locations_default(#20385,#10000,37,3,37,3) +hasLocation(#20384,#20385) +#20386=* +stmts(#20386,2,#20001,37,"/a{b}/;") +#20387=@"loc,{#10000},38,1,38,7" +locations_default(#20387,#10000,38,1,38,7) +hasLocation(#20386,#20387) +stmtContainers(#20386,#20001) +#20388=* +exprs(#20388,5,#20386,0,"/a{b}/") +#20389=@"loc,{#10000},38,1,38,6" +locations_default(#20389,#10000,38,1,38,6) +hasLocation(#20388,#20389) +enclosingStmt(#20388,#20386) +exprContainers(#20388,#20001) +literals("/a{b}/","/a{b}/",#20388) +#20390=* +regexpterm(#20390,1,#20388,0,"a{b}") +#20391=@"loc,{#10000},38,2,38,5" +locations_default(#20391,#10000,38,2,38,5) +hasLocation(#20390,#20391) +#20392=* +regexpterm(#20392,11,#20390,0,"a{") +#20393=@"loc,{#10000},38,2,38,3" +locations_default(#20393,#10000,38,2,38,3) +hasLocation(#20392,#20393) +isGreedy(#20392) +rangeQuantifierLowerBound(#20392,0) +#20394=* +regexpterm(#20394,14,#20392,0,"a") +#20395=@"loc,{#10000},38,2,38,2" +locations_default(#20395,#10000,38,2,38,2) +hasLocation(#20394,#20395) +regexpConstValue(#20394,"a") +#20396=* +regexpterm(#20396,14,#20390,1,"b") +#20397=@"loc,{#10000},38,4,38,4" +locations_default(#20397,#10000,38,4,38,4) +hasLocation(#20396,#20397) +regexpConstValue(#20396,"b") +#20398=* +regexpterm(#20398,14,#20390,2,"}") +#20399=@"loc,{#10000},38,5,38,5" +locations_default(#20399,#10000,38,5,38,5) +hasLocation(#20398,#20399) +regexpConstValue(#20398,"}") #20400=* -regexpParseErrors(#20400,#20389,"expected '}'") -#20401=@"loc,{#10000},38,3,38,3" -locations_default(#20401,#10000,38,3,38,3) -hasLocation(#20400,#20401) -#20402=* -regexpParseErrors(#20402,#20389,"unexpected character") -hasLocation(#20402,#20398) +regexpParseErrors(#20400,#20390,"expected digit") +hasLocation(#20400,#20397) +#20401=* +regexpParseErrors(#20401,#20390,"expected '}'") +#20402=@"loc,{#10000},38,3,38,3" +locations_default(#20402,#10000,38,3,38,3) +hasLocation(#20401,#20402) #20403=* -stmts(#20403,2,#20001,38,"/a{2/;") -#20404=@"loc,{#10000},39,1,39,6" -locations_default(#20404,#10000,39,1,39,6) -hasLocation(#20403,#20404) -stmtContainers(#20403,#20001) -#20405=* -exprs(#20405,5,#20403,0,"/a{2/") -#20406=@"loc,{#10000},39,1,39,5" -locations_default(#20406,#10000,39,1,39,5) -hasLocation(#20405,#20406) -enclosingStmt(#20405,#20403) -exprContainers(#20405,#20001) -literals("/a{2/","/a{2/",#20405) -#20407=* -regexpterm(#20407,11,#20405,0,"a{2") -#20408=@"loc,{#10000},39,2,39,4" -locations_default(#20408,#10000,39,2,39,4) -hasLocation(#20407,#20408) -isGreedy(#20407) -rangeQuantifierLowerBound(#20407,2) -#20409=* -regexpterm(#20409,14,#20407,0,"a") -#20410=@"loc,{#10000},39,2,39,2" -locations_default(#20410,#10000,39,2,39,2) -hasLocation(#20409,#20410) -regexpConstValue(#20409,"a") -#20411=* -regexpParseErrors(#20411,#20407,"expected '}'") -#20412=@"loc,{#10000},39,4,39,4" -locations_default(#20412,#10000,39,4,39,4) -hasLocation(#20411,#20412) -#20413=* -stmts(#20413,2,#20001,39,"/\xa/;") -#20414=@"loc,{#10000},40,1,40,6" -locations_default(#20414,#10000,40,1,40,6) -hasLocation(#20413,#20414) -stmtContainers(#20413,#20001) -#20415=* -exprs(#20415,5,#20413,0,"/\xa/") -#20416=@"loc,{#10000},40,1,40,5" -locations_default(#20416,#10000,40,1,40,5) -hasLocation(#20415,#20416) -enclosingStmt(#20415,#20413) -exprContainers(#20415,#20001) -literals("/\xa/","/\xa/",#20415) -#20417=* -regexpterm(#20417,15,#20415,0,"\xa") -#20418=@"loc,{#10000},40,2,40,4" -locations_default(#20418,#10000,40,2,40,4) -hasLocation(#20417,#20418) -regexpConstValue(#20417," +regexpParseErrors(#20403,#20390,"unexpected character") +hasLocation(#20403,#20399) +#20404=* +stmts(#20404,2,#20001,38,"/a{2/;") +#20405=@"loc,{#10000},39,1,39,6" +locations_default(#20405,#10000,39,1,39,6) +hasLocation(#20404,#20405) +stmtContainers(#20404,#20001) +#20406=* +exprs(#20406,5,#20404,0,"/a{2/") +#20407=@"loc,{#10000},39,1,39,5" +locations_default(#20407,#10000,39,1,39,5) +hasLocation(#20406,#20407) +enclosingStmt(#20406,#20404) +exprContainers(#20406,#20001) +literals("/a{2/","/a{2/",#20406) +#20408=* +regexpterm(#20408,11,#20406,0,"a{2") +#20409=@"loc,{#10000},39,2,39,4" +locations_default(#20409,#10000,39,2,39,4) +hasLocation(#20408,#20409) +isGreedy(#20408) +rangeQuantifierLowerBound(#20408,2) +#20410=* +regexpterm(#20410,14,#20408,0,"a") +#20411=@"loc,{#10000},39,2,39,2" +locations_default(#20411,#10000,39,2,39,2) +hasLocation(#20410,#20411) +regexpConstValue(#20410,"a") +#20412=* +regexpParseErrors(#20412,#20408,"expected '}'") +#20413=@"loc,{#10000},39,4,39,4" +locations_default(#20413,#10000,39,4,39,4) +hasLocation(#20412,#20413) +#20414=* +stmts(#20414,2,#20001,39,"/\xa/;") +#20415=@"loc,{#10000},40,1,40,6" +locations_default(#20415,#10000,40,1,40,6) +hasLocation(#20414,#20415) +stmtContainers(#20414,#20001) +#20416=* +exprs(#20416,5,#20414,0,"/\xa/") +#20417=@"loc,{#10000},40,1,40,5" +locations_default(#20417,#10000,40,1,40,5) +hasLocation(#20416,#20417) +enclosingStmt(#20416,#20414) +exprContainers(#20416,#20001) +literals("/\xa/","/\xa/",#20416) +#20418=* +regexpterm(#20418,15,#20416,0,"\xa") +#20419=@"loc,{#10000},40,2,40,4" +locations_default(#20419,#10000,40,2,40,4) +hasLocation(#20418,#20419) +regexpConstValue(#20418," ") -#20419=* -regexpParseErrors(#20419,#20417,"unexpected end of regular expression") -#20420=@"loc,{#10000},40,5,40,5" -locations_default(#20420,#10000,40,5,40,5) -hasLocation(#20419,#20420) -#20421=* -stmts(#20421,2,#20001,40,"/\c0/;") -#20422=@"loc,{#10000},41,1,41,6" -locations_default(#20422,#10000,41,1,41,6) -hasLocation(#20421,#20422) -stmtContainers(#20421,#20001) -#20423=* -exprs(#20423,5,#20421,0,"/\c0/") -#20424=@"loc,{#10000},41,1,41,5" -locations_default(#20424,#10000,41,1,41,5) -hasLocation(#20423,#20424) -enclosingStmt(#20423,#20421) -exprContainers(#20423,#20001) -literals("/\c0/","/\c0/",#20423) -#20425=* -regexpterm(#20425,19,#20423,0,"\c0") -#20426=@"loc,{#10000},41,2,41,4" -locations_default(#20426,#10000,41,2,41,4) -hasLocation(#20425,#20426) -regexpConstValue(#20425,"") -#20427=* -regexpParseErrors(#20427,#20425,"expected control letter") -#20428=@"loc,{#10000},41,4,41,4" -locations_default(#20428,#10000,41,4,41,4) -hasLocation(#20427,#20428) -#20429=* -stmts(#20429,2,#20001,41,"/[]/;") -#20430=@"loc,{#10000},42,1,42,5" -locations_default(#20430,#10000,42,1,42,5) -hasLocation(#20429,#20430) -stmtContainers(#20429,#20001) -#20431=* -exprs(#20431,5,#20429,0,"/[]/") -#20432=@"loc,{#10000},42,1,42,4" -locations_default(#20432,#10000,42,1,42,4) -hasLocation(#20431,#20432) -enclosingStmt(#20431,#20429) -exprContainers(#20431,#20001) -literals("/[]/","/[]/",#20431) -#20433=* -regexpterm(#20433,23,#20431,0,"[]") -#20434=@"loc,{#10000},42,2,42,3" -locations_default(#20434,#10000,42,2,42,3) -hasLocation(#20433,#20434) -#20435=* -stmts(#20435,2,#20001,42,"/[^]/;") -#20436=@"loc,{#10000},43,1,43,6" -locations_default(#20436,#10000,43,1,43,6) -hasLocation(#20435,#20436) -stmtContainers(#20435,#20001) -#20437=* -exprs(#20437,5,#20435,0,"/[^]/") -#20438=@"loc,{#10000},43,1,43,5" -locations_default(#20438,#10000,43,1,43,5) -hasLocation(#20437,#20438) -enclosingStmt(#20437,#20435) -exprContainers(#20437,#20001) -literals("/[^]/","/[^]/",#20437) -#20439=* -regexpterm(#20439,23,#20437,0,"[^]") -#20440=@"loc,{#10000},43,2,43,4" -locations_default(#20440,#10000,43,2,43,4) -hasLocation(#20439,#20440) -isInverted(#20439) -#20441=* -stmts(#20441,2,#20001,43,"//;") -#20442=@"loc,{#10000},44,1,44,60" -locations_default(#20442,#10000,44,1,44,60) -hasLocation(#20441,#20442) -stmtContainers(#20441,#20001) -#20443=* -exprs(#20443,5,#20441,0,"//") -#20444=@"loc,{#10000},44,1,44,59" -locations_default(#20444,#10000,44,1,44,59) -hasLocation(#20443,#20444) -enclosingStmt(#20443,#20441) -exprContainers(#20443,#20001) -literals("/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/","/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/",#20443) -#20445=* -regexpterm(#20445,1,#20443,0,"]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>") -#20446=@"loc,{#10000},44,2,44,58" -locations_default(#20446,#10000,44,2,44,58) -hasLocation(#20445,#20446) -#20447=* -regexpterm(#20447,14,#20445,0,"<") -#20448=@"loc,{#10000},44,2,44,2" -locations_default(#20448,#10000,44,2,44,2) -hasLocation(#20447,#20448) -regexpConstValue(#20447,"<") -#20449=* -regexpterm(#20449,14,#20445,1,"t") -#20450=@"loc,{#10000},44,3,44,3" -locations_default(#20450,#10000,44,3,44,3) -hasLocation(#20449,#20450) -regexpConstValue(#20449,"t") -#20451=* -regexpterm(#20451,14,#20445,2,"p") -#20452=@"loc,{#10000},44,4,44,4" -locations_default(#20452,#10000,44,4,44,4) -hasLocation(#20451,#20452) -regexpConstValue(#20451,"p") -#20453=* -regexpterm(#20453,14,#20445,3,"l") -#20454=@"loc,{#10000},44,5,44,5" -locations_default(#20454,#10000,44,5,44,5) -hasLocation(#20453,#20454) -regexpConstValue(#20453,"l") -#20455=* -regexpterm(#20455,4,#20445,4,"\b") -#20456=@"loc,{#10000},44,6,44,7" -locations_default(#20456,#10000,44,6,44,7) -hasLocation(#20455,#20456) -#20457=* -regexpterm(#20457,8,#20445,5,"[^>]*") -#20458=@"loc,{#10000},44,8,44,12" -locations_default(#20458,#10000,44,8,44,12) -hasLocation(#20457,#20458) -isGreedy(#20457) -#20459=* -regexpterm(#20459,23,#20457,0,"[^>]") -#20460=@"loc,{#10000},44,8,44,11" -locations_default(#20460,#10000,44,8,44,11) -hasLocation(#20459,#20460) -isInverted(#20459) -#20461=* -regexpterm(#20461,14,#20459,0,">") -#20462=@"loc,{#10000},44,10,44,10" -locations_default(#20462,#10000,44,10,44,10) -hasLocation(#20461,#20462) -regexpConstValue(#20461,">") -#20463=* -regexpterm(#20463,14,#20445,6,">") -#20464=@"loc,{#10000},44,13,44,13" -locations_default(#20464,#10000,44,13,44,13) -hasLocation(#20463,#20464) -regexpConstValue(#20463,">") -#20465=* -regexpterm(#20465,13,#20445,7,"((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)") -#20466=@"loc,{#10000},44,14,44,51" -locations_default(#20466,#10000,44,14,44,51) -hasLocation(#20465,#20466) -isCapture(#20465,1) -#20467=* -regexpterm(#20467,8,#20465,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?") -#20468=@"loc,{#10000},44,15,44,50" -locations_default(#20468,#10000,44,15,44,50) -hasLocation(#20467,#20468) -#20469=* -regexpterm(#20469,13,#20467,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))") -#20470=@"loc,{#10000},44,15,44,48" -locations_default(#20470,#10000,44,15,44,48) -hasLocation(#20469,#20470) -#20471=* -regexpterm(#20471,0,#20469,0,"(?=([^<]+))\2|<(?!tpl\b[^>]*>)") -#20472=@"loc,{#10000},44,18,44,47" -locations_default(#20472,#10000,44,18,44,47) -hasLocation(#20471,#20472) -#20473=* -regexpterm(#20473,1,#20471,0,"(?=([^<]+))\2") -#20474=@"loc,{#10000},44,18,44,30" -locations_default(#20474,#10000,44,18,44,30) -hasLocation(#20473,#20474) -#20475=* -regexpterm(#20475,6,#20473,0,"(?=([^<]+))") -#20476=@"loc,{#10000},44,18,44,28" -locations_default(#20476,#10000,44,18,44,28) -hasLocation(#20475,#20476) -#20477=* -regexpterm(#20477,13,#20475,0,"([^<]+)") -#20478=@"loc,{#10000},44,21,44,27" -locations_default(#20478,#10000,44,21,44,27) -hasLocation(#20477,#20478) -isCapture(#20477,2) -#20479=* -regexpterm(#20479,9,#20477,0,"[^<]+") -#20480=@"loc,{#10000},44,22,44,26" -locations_default(#20480,#10000,44,22,44,26) -hasLocation(#20479,#20480) -isGreedy(#20479) -#20481=* -regexpterm(#20481,23,#20479,0,"[^<]") -#20482=@"loc,{#10000},44,22,44,25" -locations_default(#20482,#10000,44,22,44,25) -hasLocation(#20481,#20482) -isInverted(#20481) -#20483=* -regexpterm(#20483,14,#20481,0,"<") -#20484=@"loc,{#10000},44,24,44,24" -locations_default(#20484,#10000,44,24,44,24) -hasLocation(#20483,#20484) -regexpConstValue(#20483,"<") -#20485=* -regexpterm(#20485,22,#20473,1,"\2") -#20486=@"loc,{#10000},44,29,44,30" -locations_default(#20486,#10000,44,29,44,30) -hasLocation(#20485,#20486) -backref(#20485,2) -#20487=* -regexpterm(#20487,1,#20471,1,"<(?!tpl\b[^>]*>)") -#20488=@"loc,{#10000},44,32,44,47" -locations_default(#20488,#10000,44,32,44,47) -hasLocation(#20487,#20488) -#20489=* -regexpterm(#20489,14,#20487,0,"<") -#20490=@"loc,{#10000},44,32,44,32" -locations_default(#20490,#10000,44,32,44,32) -hasLocation(#20489,#20490) -regexpConstValue(#20489,"<") -#20491=* -regexpterm(#20491,7,#20487,1,"(?!tpl\b[^>]*>)") -#20492=@"loc,{#10000},44,33,44,47" -locations_default(#20492,#10000,44,33,44,47) -hasLocation(#20491,#20492) -#20493=* -regexpterm(#20493,1,#20491,0,"tpl\b[^>]*>") -#20494=@"loc,{#10000},44,36,44,46" -locations_default(#20494,#10000,44,36,44,46) -hasLocation(#20493,#20494) -#20495=* -regexpterm(#20495,14,#20493,0,"t") -#20496=@"loc,{#10000},44,36,44,36" -locations_default(#20496,#10000,44,36,44,36) -hasLocation(#20495,#20496) -regexpConstValue(#20495,"t") -#20497=* -regexpterm(#20497,14,#20493,1,"p") -#20498=@"loc,{#10000},44,37,44,37" -locations_default(#20498,#10000,44,37,44,37) -hasLocation(#20497,#20498) -regexpConstValue(#20497,"p") -#20499=* -regexpterm(#20499,14,#20493,2,"l") -#20500=@"loc,{#10000},44,38,44,38" -locations_default(#20500,#10000,44,38,44,38) -hasLocation(#20499,#20500) -regexpConstValue(#20499,"l") -#20501=* -regexpterm(#20501,4,#20493,3,"\b") -#20502=@"loc,{#10000},44,39,44,40" -locations_default(#20502,#10000,44,39,44,40) -hasLocation(#20501,#20502) -#20503=* -regexpterm(#20503,8,#20493,4,"[^>]*") -#20504=@"loc,{#10000},44,41,44,45" -locations_default(#20504,#10000,44,41,44,45) -hasLocation(#20503,#20504) -isGreedy(#20503) -#20505=* -regexpterm(#20505,23,#20503,0,"[^>]") -#20506=@"loc,{#10000},44,41,44,44" -locations_default(#20506,#10000,44,41,44,44) -hasLocation(#20505,#20506) -isInverted(#20505) -#20507=* -regexpterm(#20507,14,#20505,0,">") -#20508=@"loc,{#10000},44,43,44,43" -locations_default(#20508,#10000,44,43,44,43) -hasLocation(#20507,#20508) -regexpConstValue(#20507,">") -#20509=* -regexpterm(#20509,14,#20493,5,">") -#20510=@"loc,{#10000},44,46,44,46" -locations_default(#20510,#10000,44,46,44,46) -hasLocation(#20509,#20510) -regexpConstValue(#20509,">") -#20511=* -regexpterm(#20511,14,#20445,8,"<") -#20512=@"loc,{#10000},44,52,44,52" -locations_default(#20512,#10000,44,52,44,52) -hasLocation(#20511,#20512) -regexpConstValue(#20511,"<") -#20513=* -regexpterm(#20513,21,#20445,9,"\/") -#20514=@"loc,{#10000},44,53,44,54" -locations_default(#20514,#10000,44,53,44,54) -hasLocation(#20513,#20514) -regexpConstValue(#20513,"/") -#20515=* -regexpterm(#20515,14,#20445,10,"t") -#20516=@"loc,{#10000},44,55,44,55" -locations_default(#20516,#10000,44,55,44,55) -hasLocation(#20515,#20516) -regexpConstValue(#20515,"t") -#20517=* -regexpterm(#20517,14,#20445,11,"p") -#20518=@"loc,{#10000},44,56,44,56" -locations_default(#20518,#10000,44,56,44,56) -hasLocation(#20517,#20518) -regexpConstValue(#20517,"p") -#20519=* -regexpterm(#20519,14,#20445,12,"l") -#20520=@"loc,{#10000},44,57,44,57" -locations_default(#20520,#10000,44,57,44,57) -hasLocation(#20519,#20520) -regexpConstValue(#20519,"l") -#20521=* -regexpterm(#20521,14,#20445,13,">") -#20522=@"loc,{#10000},44,58,44,58" -locations_default(#20522,#10000,44,58,44,58) -hasLocation(#20521,#20522) -regexpConstValue(#20521,">") -#20523=* -lines(#20523,#20001,"/t/;"," -") -hasLocation(#20523,#20004) +#20420=* +regexpParseErrors(#20420,#20418,"unexpected end of regular expression") +#20421=@"loc,{#10000},40,5,40,5" +locations_default(#20421,#10000,40,5,40,5) +hasLocation(#20420,#20421) +#20422=* +stmts(#20422,2,#20001,40,"/\c0/;") +#20423=@"loc,{#10000},41,1,41,6" +locations_default(#20423,#10000,41,1,41,6) +hasLocation(#20422,#20423) +stmtContainers(#20422,#20001) +#20424=* +exprs(#20424,5,#20422,0,"/\c0/") +#20425=@"loc,{#10000},41,1,41,5" +locations_default(#20425,#10000,41,1,41,5) +hasLocation(#20424,#20425) +enclosingStmt(#20424,#20422) +exprContainers(#20424,#20001) +literals("/\c0/","/\c0/",#20424) +#20426=* +regexpterm(#20426,19,#20424,0,"\c0") +#20427=@"loc,{#10000},41,2,41,4" +locations_default(#20427,#10000,41,2,41,4) +hasLocation(#20426,#20427) +regexpConstValue(#20426,"") +#20428=* +regexpParseErrors(#20428,#20426,"expected control letter") +#20429=@"loc,{#10000},41,4,41,4" +locations_default(#20429,#10000,41,4,41,4) +hasLocation(#20428,#20429) +#20430=* +stmts(#20430,2,#20001,41,"/[]/;") +#20431=@"loc,{#10000},42,1,42,5" +locations_default(#20431,#10000,42,1,42,5) +hasLocation(#20430,#20431) +stmtContainers(#20430,#20001) +#20432=* +exprs(#20432,5,#20430,0,"/[]/") +#20433=@"loc,{#10000},42,1,42,4" +locations_default(#20433,#10000,42,1,42,4) +hasLocation(#20432,#20433) +enclosingStmt(#20432,#20430) +exprContainers(#20432,#20001) +literals("/[]/","/[]/",#20432) +#20434=* +regexpterm(#20434,23,#20432,0,"[]") +#20435=@"loc,{#10000},42,2,42,3" +locations_default(#20435,#10000,42,2,42,3) +hasLocation(#20434,#20435) +#20436=* +stmts(#20436,2,#20001,42,"/[^]/;") +#20437=@"loc,{#10000},43,1,43,6" +locations_default(#20437,#10000,43,1,43,6) +hasLocation(#20436,#20437) +stmtContainers(#20436,#20001) +#20438=* +exprs(#20438,5,#20436,0,"/[^]/") +#20439=@"loc,{#10000},43,1,43,5" +locations_default(#20439,#10000,43,1,43,5) +hasLocation(#20438,#20439) +enclosingStmt(#20438,#20436) +exprContainers(#20438,#20001) +literals("/[^]/","/[^]/",#20438) +#20440=* +regexpterm(#20440,23,#20438,0,"[^]") +#20441=@"loc,{#10000},43,2,43,4" +locations_default(#20441,#10000,43,2,43,4) +hasLocation(#20440,#20441) +isInverted(#20440) +#20442=* +stmts(#20442,2,#20001,43,"//;") +#20443=@"loc,{#10000},44,1,44,60" +locations_default(#20443,#10000,44,1,44,60) +hasLocation(#20442,#20443) +stmtContainers(#20442,#20001) +#20444=* +exprs(#20444,5,#20442,0,"//") +#20445=@"loc,{#10000},44,1,44,59" +locations_default(#20445,#10000,44,1,44,59) +hasLocation(#20444,#20445) +enclosingStmt(#20444,#20442) +exprContainers(#20444,#20001) +literals("/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/","/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/",#20444) +#20446=* +regexpterm(#20446,1,#20444,0,"]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>") +#20447=@"loc,{#10000},44,2,44,58" +locations_default(#20447,#10000,44,2,44,58) +hasLocation(#20446,#20447) +#20448=* +regexpterm(#20448,14,#20446,0,"<") +#20449=@"loc,{#10000},44,2,44,2" +locations_default(#20449,#10000,44,2,44,2) +hasLocation(#20448,#20449) +regexpConstValue(#20448,"<") +#20450=* +regexpterm(#20450,14,#20446,1,"t") +#20451=@"loc,{#10000},44,3,44,3" +locations_default(#20451,#10000,44,3,44,3) +hasLocation(#20450,#20451) +regexpConstValue(#20450,"t") +#20452=* +regexpterm(#20452,14,#20446,2,"p") +#20453=@"loc,{#10000},44,4,44,4" +locations_default(#20453,#10000,44,4,44,4) +hasLocation(#20452,#20453) +regexpConstValue(#20452,"p") +#20454=* +regexpterm(#20454,14,#20446,3,"l") +#20455=@"loc,{#10000},44,5,44,5" +locations_default(#20455,#10000,44,5,44,5) +hasLocation(#20454,#20455) +regexpConstValue(#20454,"l") +#20456=* +regexpterm(#20456,4,#20446,4,"\b") +#20457=@"loc,{#10000},44,6,44,7" +locations_default(#20457,#10000,44,6,44,7) +hasLocation(#20456,#20457) +#20458=* +regexpterm(#20458,8,#20446,5,"[^>]*") +#20459=@"loc,{#10000},44,8,44,12" +locations_default(#20459,#10000,44,8,44,12) +hasLocation(#20458,#20459) +isGreedy(#20458) +#20460=* +regexpterm(#20460,23,#20458,0,"[^>]") +#20461=@"loc,{#10000},44,8,44,11" +locations_default(#20461,#10000,44,8,44,11) +hasLocation(#20460,#20461) +isInverted(#20460) +#20462=* +regexpterm(#20462,14,#20460,0,">") +#20463=@"loc,{#10000},44,10,44,10" +locations_default(#20463,#10000,44,10,44,10) +hasLocation(#20462,#20463) +regexpConstValue(#20462,">") +#20464=* +regexpterm(#20464,14,#20446,6,">") +#20465=@"loc,{#10000},44,13,44,13" +locations_default(#20465,#10000,44,13,44,13) +hasLocation(#20464,#20465) +regexpConstValue(#20464,">") +#20466=* +regexpterm(#20466,13,#20446,7,"((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)") +#20467=@"loc,{#10000},44,14,44,51" +locations_default(#20467,#10000,44,14,44,51) +hasLocation(#20466,#20467) +isCapture(#20466,1) +#20468=* +regexpterm(#20468,8,#20466,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?") +#20469=@"loc,{#10000},44,15,44,50" +locations_default(#20469,#10000,44,15,44,50) +hasLocation(#20468,#20469) +#20470=* +regexpterm(#20470,13,#20468,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))") +#20471=@"loc,{#10000},44,15,44,48" +locations_default(#20471,#10000,44,15,44,48) +hasLocation(#20470,#20471) +#20472=* +regexpterm(#20472,0,#20470,0,"(?=([^<]+))\2|<(?!tpl\b[^>]*>)") +#20473=@"loc,{#10000},44,18,44,47" +locations_default(#20473,#10000,44,18,44,47) +hasLocation(#20472,#20473) +#20474=* +regexpterm(#20474,1,#20472,0,"(?=([^<]+))\2") +#20475=@"loc,{#10000},44,18,44,30" +locations_default(#20475,#10000,44,18,44,30) +hasLocation(#20474,#20475) +#20476=* +regexpterm(#20476,6,#20474,0,"(?=([^<]+))") +#20477=@"loc,{#10000},44,18,44,28" +locations_default(#20477,#10000,44,18,44,28) +hasLocation(#20476,#20477) +#20478=* +regexpterm(#20478,13,#20476,0,"([^<]+)") +#20479=@"loc,{#10000},44,21,44,27" +locations_default(#20479,#10000,44,21,44,27) +hasLocation(#20478,#20479) +isCapture(#20478,2) +#20480=* +regexpterm(#20480,9,#20478,0,"[^<]+") +#20481=@"loc,{#10000},44,22,44,26" +locations_default(#20481,#10000,44,22,44,26) +hasLocation(#20480,#20481) +isGreedy(#20480) +#20482=* +regexpterm(#20482,23,#20480,0,"[^<]") +#20483=@"loc,{#10000},44,22,44,25" +locations_default(#20483,#10000,44,22,44,25) +hasLocation(#20482,#20483) +isInverted(#20482) +#20484=* +regexpterm(#20484,14,#20482,0,"<") +#20485=@"loc,{#10000},44,24,44,24" +locations_default(#20485,#10000,44,24,44,24) +hasLocation(#20484,#20485) +regexpConstValue(#20484,"<") +#20486=* +regexpterm(#20486,22,#20474,1,"\2") +#20487=@"loc,{#10000},44,29,44,30" +locations_default(#20487,#10000,44,29,44,30) +hasLocation(#20486,#20487) +backref(#20486,2) +#20488=* +regexpterm(#20488,1,#20472,1,"<(?!tpl\b[^>]*>)") +#20489=@"loc,{#10000},44,32,44,47" +locations_default(#20489,#10000,44,32,44,47) +hasLocation(#20488,#20489) +#20490=* +regexpterm(#20490,14,#20488,0,"<") +#20491=@"loc,{#10000},44,32,44,32" +locations_default(#20491,#10000,44,32,44,32) +hasLocation(#20490,#20491) +regexpConstValue(#20490,"<") +#20492=* +regexpterm(#20492,7,#20488,1,"(?!tpl\b[^>]*>)") +#20493=@"loc,{#10000},44,33,44,47" +locations_default(#20493,#10000,44,33,44,47) +hasLocation(#20492,#20493) +#20494=* +regexpterm(#20494,1,#20492,0,"tpl\b[^>]*>") +#20495=@"loc,{#10000},44,36,44,46" +locations_default(#20495,#10000,44,36,44,46) +hasLocation(#20494,#20495) +#20496=* +regexpterm(#20496,14,#20494,0,"t") +#20497=@"loc,{#10000},44,36,44,36" +locations_default(#20497,#10000,44,36,44,36) +hasLocation(#20496,#20497) +regexpConstValue(#20496,"t") +#20498=* +regexpterm(#20498,14,#20494,1,"p") +#20499=@"loc,{#10000},44,37,44,37" +locations_default(#20499,#10000,44,37,44,37) +hasLocation(#20498,#20499) +regexpConstValue(#20498,"p") +#20500=* +regexpterm(#20500,14,#20494,2,"l") +#20501=@"loc,{#10000},44,38,44,38" +locations_default(#20501,#10000,44,38,44,38) +hasLocation(#20500,#20501) +regexpConstValue(#20500,"l") +#20502=* +regexpterm(#20502,4,#20494,3,"\b") +#20503=@"loc,{#10000},44,39,44,40" +locations_default(#20503,#10000,44,39,44,40) +hasLocation(#20502,#20503) +#20504=* +regexpterm(#20504,8,#20494,4,"[^>]*") +#20505=@"loc,{#10000},44,41,44,45" +locations_default(#20505,#10000,44,41,44,45) +hasLocation(#20504,#20505) +isGreedy(#20504) +#20506=* +regexpterm(#20506,23,#20504,0,"[^>]") +#20507=@"loc,{#10000},44,41,44,44" +locations_default(#20507,#10000,44,41,44,44) +hasLocation(#20506,#20507) +isInverted(#20506) +#20508=* +regexpterm(#20508,14,#20506,0,">") +#20509=@"loc,{#10000},44,43,44,43" +locations_default(#20509,#10000,44,43,44,43) +hasLocation(#20508,#20509) +regexpConstValue(#20508,">") +#20510=* +regexpterm(#20510,14,#20494,5,">") +#20511=@"loc,{#10000},44,46,44,46" +locations_default(#20511,#10000,44,46,44,46) +hasLocation(#20510,#20511) +regexpConstValue(#20510,">") +#20512=* +regexpterm(#20512,14,#20446,8,"<") +#20513=@"loc,{#10000},44,52,44,52" +locations_default(#20513,#10000,44,52,44,52) +hasLocation(#20512,#20513) +regexpConstValue(#20512,"<") +#20514=* +regexpterm(#20514,21,#20446,9,"\/") +#20515=@"loc,{#10000},44,53,44,54" +locations_default(#20515,#10000,44,53,44,54) +hasLocation(#20514,#20515) +regexpConstValue(#20514,"/") +#20516=* +regexpterm(#20516,14,#20446,10,"t") +#20517=@"loc,{#10000},44,55,44,55" +locations_default(#20517,#10000,44,55,44,55) +hasLocation(#20516,#20517) +regexpConstValue(#20516,"t") +#20518=* +regexpterm(#20518,14,#20446,11,"p") +#20519=@"loc,{#10000},44,56,44,56" +locations_default(#20519,#10000,44,56,44,56) +hasLocation(#20518,#20519) +regexpConstValue(#20518,"p") +#20520=* +regexpterm(#20520,14,#20446,12,"l") +#20521=@"loc,{#10000},44,57,44,57" +locations_default(#20521,#10000,44,57,44,57) +hasLocation(#20520,#20521) +regexpConstValue(#20520,"l") +#20522=* +regexpterm(#20522,14,#20446,13,">") +#20523=@"loc,{#10000},44,58,44,58" +locations_default(#20523,#10000,44,58,44,58) +hasLocation(#20522,#20523) +regexpConstValue(#20522,">") #20524=* -lines(#20524,#20001,"/foo|bar/;"," +lines(#20524,#20001,"/t/;"," ") -hasLocation(#20524,#20010) +hasLocation(#20524,#20004) #20525=* -lines(#20525,#20001,"/(?:)/;"," +lines(#20525,#20001,"/foo|bar/;"," ") -hasLocation(#20525,#20032) +hasLocation(#20525,#20010) #20526=* -lines(#20526,#20001,"/^abc$/;"," +lines(#20526,#20001,"/(?:)/;"," ") -hasLocation(#20526,#20040) +hasLocation(#20526,#20032) #20527=* -lines(#20527,#20001,"/\bx\b/;"," +lines(#20527,#20001,"/^abc$/;"," ") -hasLocation(#20527,#20056) +hasLocation(#20527,#20040) #20528=* -lines(#20528,#20001,"/\bx\B/;"," +lines(#20528,#20001,"/\bx\b/;"," ") -hasLocation(#20528,#20068) +hasLocation(#20528,#20056) #20529=* -lines(#20529,#20001,"/x(?=y)/;"," +lines(#20529,#20001,"/\bx\B/;"," ") -hasLocation(#20529,#20080) +hasLocation(#20529,#20068) #20530=* -lines(#20530,#20001,"/x(?!z)/;"," +lines(#20530,#20001,"/x(?=y)/;"," ") -hasLocation(#20530,#20092) +hasLocation(#20530,#20080) #20531=* -lines(#20531,#20001,"/a*/;"," +lines(#20531,#20001,"/x(?!z)/;"," ") -hasLocation(#20531,#20104) +hasLocation(#20531,#20092) #20532=* -lines(#20532,#20001,"/a*?/;"," +lines(#20532,#20001,"/a*/;"," ") -hasLocation(#20532,#20112) +hasLocation(#20532,#20104) #20533=* -lines(#20533,#20001,"/a+/;"," +lines(#20533,#20001,"/a*?/;"," ") -hasLocation(#20533,#20120) +hasLocation(#20533,#20112) #20534=* -lines(#20534,#20001,"/a+?/;"," +lines(#20534,#20001,"/a+/;"," ") -hasLocation(#20534,#20128) +hasLocation(#20534,#20120) #20535=* -lines(#20535,#20001,"/a?/;"," +lines(#20535,#20001,"/a+?/;"," ") -hasLocation(#20535,#20136) +hasLocation(#20535,#20128) #20536=* -lines(#20536,#20001,"/a??/;"," +lines(#20536,#20001,"/a?/;"," ") -hasLocation(#20536,#20144) +hasLocation(#20536,#20136) #20537=* -lines(#20537,#20001,"/a{1}/;"," +lines(#20537,#20001,"/a??/;"," ") -hasLocation(#20537,#20152) +hasLocation(#20537,#20144) #20538=* -lines(#20538,#20001,"/a{1,}/;"," +lines(#20538,#20001,"/a{1}/;"," ") -hasLocation(#20538,#20160) +hasLocation(#20538,#20152) #20539=* -lines(#20539,#20001,"/a{1,2}/;"," +lines(#20539,#20001,"/a{1,}/;"," ") -hasLocation(#20539,#20168) +hasLocation(#20539,#20160) #20540=* -lines(#20540,#20001,"/a{1}?/;"," +lines(#20540,#20001,"/a{1,2}/;"," ") -hasLocation(#20540,#20176) +hasLocation(#20540,#20168) #20541=* -lines(#20541,#20001,"/a{1,}?/;"," +lines(#20541,#20001,"/a{1}?/;"," ") -hasLocation(#20541,#20184) +hasLocation(#20541,#20176) #20542=* -lines(#20542,#20001,"/a{1,2}?/;"," +lines(#20542,#20001,"/a{1,}?/;"," ") -hasLocation(#20542,#20192) +hasLocation(#20542,#20184) #20543=* -lines(#20543,#20001,"/./;"," +lines(#20543,#20001,"/a{1,2}?/;"," ") -hasLocation(#20543,#20200) +hasLocation(#20543,#20192) #20544=* -lines(#20544,#20001,"/(abc)/;"," +lines(#20544,#20001,"/./;"," ") -hasLocation(#20544,#20206) +hasLocation(#20544,#20200) #20545=* -lines(#20545,#20001,"/(?:abc)/;"," +lines(#20545,#20001,"/(abc)/;"," ") -hasLocation(#20545,#20220) +hasLocation(#20545,#20206) #20546=* -lines(#20546,#20001,"/\x0a/;"," +lines(#20546,#20001,"/(?:abc)/;"," ") -hasLocation(#20546,#20234) +hasLocation(#20546,#20220) #20547=* -lines(#20547,#20001,"/\u000a/;"," +lines(#20547,#20001,"/\x0a/;"," ") -hasLocation(#20547,#20240) +hasLocation(#20547,#20234) #20548=* -lines(#20548,#20001,"/\10/;"," +lines(#20548,#20001,"/\u000a/;"," ") -hasLocation(#20548,#20246) +hasLocation(#20548,#20240) #20549=* -lines(#20549,#20001,"/\t\n\r\f\v/;"," +lines(#20549,#20001,"/\10/;"," ") -hasLocation(#20549,#20252) +hasLocation(#20549,#20246) #20550=* -lines(#20550,#20001,"/\ca\cN/;"," +lines(#20550,#20001,"/\t\n\r\f\v/;"," ") -hasLocation(#20550,#20268) +hasLocation(#20550,#20253) #20551=* -lines(#20551,#20001,"/\w\S/;"," +lines(#20551,#20001,"/\ca\cN/;"," ") -hasLocation(#20551,#20278) +hasLocation(#20551,#20269) #20552=* -lines(#20552,#20001,"/\\/;"," +lines(#20552,#20001,"/\w\S/;"," ") -hasLocation(#20552,#20288) +hasLocation(#20552,#20279) #20553=* -lines(#20553,#20001,"/[abc]/;"," +lines(#20553,#20001,"/\\/;"," ") -hasLocation(#20553,#20294) +hasLocation(#20553,#20289) #20554=* -lines(#20554,#20001,"/[a-z]/;"," +lines(#20554,#20001,"/[abc]/;"," ") -hasLocation(#20554,#20306) +hasLocation(#20554,#20295) #20555=* -lines(#20555,#20001,"/[a-zA-Z]/;"," +lines(#20555,#20001,"/[a-z]/;"," ") -hasLocation(#20555,#20318) +hasLocation(#20555,#20307) #20556=* -lines(#20556,#20001,"/[-a-z]/;"," +lines(#20556,#20001,"/[a-zA-Z]/;"," ") -hasLocation(#20556,#20336) +hasLocation(#20556,#20319) #20557=* -lines(#20557,#20001,"/[^a-z]/;"," +lines(#20557,#20001,"/[-a-z]/;"," ") -hasLocation(#20557,#20350) +hasLocation(#20557,#20337) #20558=* -lines(#20558,#20001,"/[a\b\x0c]/;"," +lines(#20558,#20001,"/[^a-z]/;"," ") -hasLocation(#20558,#20362) +hasLocation(#20558,#20351) #20559=* -lines(#20559,#20001,"/a{/;"," +lines(#20559,#20001,"/[a\b\x0c]/;"," ") -hasLocation(#20559,#20374) +hasLocation(#20559,#20363) #20560=* -lines(#20560,#20001,"/a{b}/;"," +lines(#20560,#20001,"/a{/;"," ") -hasLocation(#20560,#20386) +hasLocation(#20560,#20375) #20561=* -lines(#20561,#20001,"/a{2/;"," +lines(#20561,#20001,"/a{b}/;"," ") -hasLocation(#20561,#20404) +hasLocation(#20561,#20387) #20562=* -lines(#20562,#20001,"/\xa/;"," +lines(#20562,#20001,"/a{2/;"," ") -hasLocation(#20562,#20414) +hasLocation(#20562,#20405) #20563=* -lines(#20563,#20001,"/\c0/;"," +lines(#20563,#20001,"/\xa/;"," ") -hasLocation(#20563,#20422) +hasLocation(#20563,#20415) #20564=* -lines(#20564,#20001,"/[]/;"," +lines(#20564,#20001,"/\c0/;"," ") -hasLocation(#20564,#20430) +hasLocation(#20564,#20423) #20565=* -lines(#20565,#20001,"/[^]/;"," +lines(#20565,#20001,"/[]/;"," ") -hasLocation(#20565,#20436) +hasLocation(#20565,#20431) #20566=* -lines(#20566,#20001,"/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;","") -hasLocation(#20566,#20442) -numlines(#20001,44,44,0) +lines(#20566,#20001,"/[^]/;"," +") +hasLocation(#20566,#20437) #20567=* -tokeninfo(#20567,5,#20001,0,"/t/") -hasLocation(#20567,#20006) +lines(#20567,#20001,"/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;","") +hasLocation(#20567,#20443) +numlines(#20001,44,44,0) #20568=* -tokeninfo(#20568,8,#20001,1,";") -#20569=@"loc,{#10000},1,4,1,4" -locations_default(#20569,#10000,1,4,1,4) -hasLocation(#20568,#20569) -#20570=* -tokeninfo(#20570,5,#20001,2,"/foo|bar/") -hasLocation(#20570,#20012) +tokeninfo(#20568,5,#20001,0,"/t/") +hasLocation(#20568,#20006) +#20569=* +tokeninfo(#20569,8,#20001,1,";") +#20570=@"loc,{#10000},1,4,1,4" +locations_default(#20570,#10000,1,4,1,4) +hasLocation(#20569,#20570) #20571=* -tokeninfo(#20571,8,#20001,3,";") -#20572=@"loc,{#10000},2,10,2,10" -locations_default(#20572,#10000,2,10,2,10) -hasLocation(#20571,#20572) -#20573=* -tokeninfo(#20573,5,#20001,4,"/(?:)/") -hasLocation(#20573,#20034) +tokeninfo(#20571,5,#20001,2,"/foo|bar/") +hasLocation(#20571,#20012) +#20572=* +tokeninfo(#20572,8,#20001,3,";") +#20573=@"loc,{#10000},2,10,2,10" +locations_default(#20573,#10000,2,10,2,10) +hasLocation(#20572,#20573) #20574=* -tokeninfo(#20574,8,#20001,5,";") -#20575=@"loc,{#10000},3,7,3,7" -locations_default(#20575,#10000,3,7,3,7) -hasLocation(#20574,#20575) -#20576=* -tokeninfo(#20576,5,#20001,6,"/^abc$/") -hasLocation(#20576,#20042) +tokeninfo(#20574,5,#20001,4,"/(?:)/") +hasLocation(#20574,#20034) +#20575=* +tokeninfo(#20575,8,#20001,5,";") +#20576=@"loc,{#10000},3,7,3,7" +locations_default(#20576,#10000,3,7,3,7) +hasLocation(#20575,#20576) #20577=* -tokeninfo(#20577,8,#20001,7,";") -#20578=@"loc,{#10000},4,8,4,8" -locations_default(#20578,#10000,4,8,4,8) -hasLocation(#20577,#20578) -#20579=* -tokeninfo(#20579,5,#20001,8,"/\bx\b/") -hasLocation(#20579,#20058) +tokeninfo(#20577,5,#20001,6,"/^abc$/") +hasLocation(#20577,#20042) +#20578=* +tokeninfo(#20578,8,#20001,7,";") +#20579=@"loc,{#10000},4,8,4,8" +locations_default(#20579,#10000,4,8,4,8) +hasLocation(#20578,#20579) #20580=* -tokeninfo(#20580,8,#20001,9,";") -#20581=@"loc,{#10000},5,8,5,8" -locations_default(#20581,#10000,5,8,5,8) -hasLocation(#20580,#20581) -#20582=* -tokeninfo(#20582,5,#20001,10,"/\bx\B/") -hasLocation(#20582,#20070) +tokeninfo(#20580,5,#20001,8,"/\bx\b/") +hasLocation(#20580,#20058) +#20581=* +tokeninfo(#20581,8,#20001,9,";") +#20582=@"loc,{#10000},5,8,5,8" +locations_default(#20582,#10000,5,8,5,8) +hasLocation(#20581,#20582) #20583=* -tokeninfo(#20583,8,#20001,11,";") -#20584=@"loc,{#10000},6,8,6,8" -locations_default(#20584,#10000,6,8,6,8) -hasLocation(#20583,#20584) -#20585=* -tokeninfo(#20585,5,#20001,12,"/x(?=y)/") -hasLocation(#20585,#20082) +tokeninfo(#20583,5,#20001,10,"/\bx\B/") +hasLocation(#20583,#20070) +#20584=* +tokeninfo(#20584,8,#20001,11,";") +#20585=@"loc,{#10000},6,8,6,8" +locations_default(#20585,#10000,6,8,6,8) +hasLocation(#20584,#20585) #20586=* -tokeninfo(#20586,8,#20001,13,";") -#20587=@"loc,{#10000},7,9,7,9" -locations_default(#20587,#10000,7,9,7,9) -hasLocation(#20586,#20587) -#20588=* -tokeninfo(#20588,5,#20001,14,"/x(?!z)/") -hasLocation(#20588,#20094) +tokeninfo(#20586,5,#20001,12,"/x(?=y)/") +hasLocation(#20586,#20082) +#20587=* +tokeninfo(#20587,8,#20001,13,";") +#20588=@"loc,{#10000},7,9,7,9" +locations_default(#20588,#10000,7,9,7,9) +hasLocation(#20587,#20588) #20589=* -tokeninfo(#20589,8,#20001,15,";") -#20590=@"loc,{#10000},8,9,8,9" -locations_default(#20590,#10000,8,9,8,9) -hasLocation(#20589,#20590) -#20591=* -tokeninfo(#20591,5,#20001,16,"/a*/") -hasLocation(#20591,#20106) +tokeninfo(#20589,5,#20001,14,"/x(?!z)/") +hasLocation(#20589,#20094) +#20590=* +tokeninfo(#20590,8,#20001,15,";") +#20591=@"loc,{#10000},8,9,8,9" +locations_default(#20591,#10000,8,9,8,9) +hasLocation(#20590,#20591) #20592=* -tokeninfo(#20592,8,#20001,17,";") -#20593=@"loc,{#10000},9,5,9,5" -locations_default(#20593,#10000,9,5,9,5) -hasLocation(#20592,#20593) -#20594=* -tokeninfo(#20594,5,#20001,18,"/a*?/") -hasLocation(#20594,#20114) +tokeninfo(#20592,5,#20001,16,"/a*/") +hasLocation(#20592,#20106) +#20593=* +tokeninfo(#20593,8,#20001,17,";") +#20594=@"loc,{#10000},9,5,9,5" +locations_default(#20594,#10000,9,5,9,5) +hasLocation(#20593,#20594) #20595=* -tokeninfo(#20595,8,#20001,19,";") -#20596=@"loc,{#10000},10,6,10,6" -locations_default(#20596,#10000,10,6,10,6) -hasLocation(#20595,#20596) -#20597=* -tokeninfo(#20597,5,#20001,20,"/a+/") -hasLocation(#20597,#20122) +tokeninfo(#20595,5,#20001,18,"/a*?/") +hasLocation(#20595,#20114) +#20596=* +tokeninfo(#20596,8,#20001,19,";") +#20597=@"loc,{#10000},10,6,10,6" +locations_default(#20597,#10000,10,6,10,6) +hasLocation(#20596,#20597) #20598=* -tokeninfo(#20598,8,#20001,21,";") -#20599=@"loc,{#10000},11,5,11,5" -locations_default(#20599,#10000,11,5,11,5) -hasLocation(#20598,#20599) -#20600=* -tokeninfo(#20600,5,#20001,22,"/a+?/") -hasLocation(#20600,#20130) +tokeninfo(#20598,5,#20001,20,"/a+/") +hasLocation(#20598,#20122) +#20599=* +tokeninfo(#20599,8,#20001,21,";") +#20600=@"loc,{#10000},11,5,11,5" +locations_default(#20600,#10000,11,5,11,5) +hasLocation(#20599,#20600) #20601=* -tokeninfo(#20601,8,#20001,23,";") -#20602=@"loc,{#10000},12,6,12,6" -locations_default(#20602,#10000,12,6,12,6) -hasLocation(#20601,#20602) -#20603=* -tokeninfo(#20603,5,#20001,24,"/a?/") -hasLocation(#20603,#20138) +tokeninfo(#20601,5,#20001,22,"/a+?/") +hasLocation(#20601,#20130) +#20602=* +tokeninfo(#20602,8,#20001,23,";") +#20603=@"loc,{#10000},12,6,12,6" +locations_default(#20603,#10000,12,6,12,6) +hasLocation(#20602,#20603) #20604=* -tokeninfo(#20604,8,#20001,25,";") -#20605=@"loc,{#10000},13,5,13,5" -locations_default(#20605,#10000,13,5,13,5) -hasLocation(#20604,#20605) -#20606=* -tokeninfo(#20606,5,#20001,26,"/a??/") -hasLocation(#20606,#20146) +tokeninfo(#20604,5,#20001,24,"/a?/") +hasLocation(#20604,#20138) +#20605=* +tokeninfo(#20605,8,#20001,25,";") +#20606=@"loc,{#10000},13,5,13,5" +locations_default(#20606,#10000,13,5,13,5) +hasLocation(#20605,#20606) #20607=* -tokeninfo(#20607,8,#20001,27,";") -#20608=@"loc,{#10000},14,6,14,6" -locations_default(#20608,#10000,14,6,14,6) -hasLocation(#20607,#20608) -#20609=* -tokeninfo(#20609,5,#20001,28,"/a{1}/") -hasLocation(#20609,#20154) +tokeninfo(#20607,5,#20001,26,"/a??/") +hasLocation(#20607,#20146) +#20608=* +tokeninfo(#20608,8,#20001,27,";") +#20609=@"loc,{#10000},14,6,14,6" +locations_default(#20609,#10000,14,6,14,6) +hasLocation(#20608,#20609) #20610=* -tokeninfo(#20610,8,#20001,29,";") -#20611=@"loc,{#10000},15,7,15,7" -locations_default(#20611,#10000,15,7,15,7) -hasLocation(#20610,#20611) -#20612=* -tokeninfo(#20612,5,#20001,30,"/a{1,}/") -hasLocation(#20612,#20162) +tokeninfo(#20610,5,#20001,28,"/a{1}/") +hasLocation(#20610,#20154) +#20611=* +tokeninfo(#20611,8,#20001,29,";") +#20612=@"loc,{#10000},15,7,15,7" +locations_default(#20612,#10000,15,7,15,7) +hasLocation(#20611,#20612) #20613=* -tokeninfo(#20613,8,#20001,31,";") -#20614=@"loc,{#10000},16,8,16,8" -locations_default(#20614,#10000,16,8,16,8) -hasLocation(#20613,#20614) -#20615=* -tokeninfo(#20615,5,#20001,32,"/a{1,2}/") -hasLocation(#20615,#20170) +tokeninfo(#20613,5,#20001,30,"/a{1,}/") +hasLocation(#20613,#20162) +#20614=* +tokeninfo(#20614,8,#20001,31,";") +#20615=@"loc,{#10000},16,8,16,8" +locations_default(#20615,#10000,16,8,16,8) +hasLocation(#20614,#20615) #20616=* -tokeninfo(#20616,8,#20001,33,";") -#20617=@"loc,{#10000},17,9,17,9" -locations_default(#20617,#10000,17,9,17,9) -hasLocation(#20616,#20617) -#20618=* -tokeninfo(#20618,5,#20001,34,"/a{1}?/") -hasLocation(#20618,#20178) +tokeninfo(#20616,5,#20001,32,"/a{1,2}/") +hasLocation(#20616,#20170) +#20617=* +tokeninfo(#20617,8,#20001,33,";") +#20618=@"loc,{#10000},17,9,17,9" +locations_default(#20618,#10000,17,9,17,9) +hasLocation(#20617,#20618) #20619=* -tokeninfo(#20619,8,#20001,35,";") -#20620=@"loc,{#10000},18,8,18,8" -locations_default(#20620,#10000,18,8,18,8) -hasLocation(#20619,#20620) -#20621=* -tokeninfo(#20621,5,#20001,36,"/a{1,}?/") -hasLocation(#20621,#20186) +tokeninfo(#20619,5,#20001,34,"/a{1}?/") +hasLocation(#20619,#20178) +#20620=* +tokeninfo(#20620,8,#20001,35,";") +#20621=@"loc,{#10000},18,8,18,8" +locations_default(#20621,#10000,18,8,18,8) +hasLocation(#20620,#20621) #20622=* -tokeninfo(#20622,8,#20001,37,";") -#20623=@"loc,{#10000},19,9,19,9" -locations_default(#20623,#10000,19,9,19,9) -hasLocation(#20622,#20623) -#20624=* -tokeninfo(#20624,5,#20001,38,"/a{1,2}?/") -hasLocation(#20624,#20194) +tokeninfo(#20622,5,#20001,36,"/a{1,}?/") +hasLocation(#20622,#20186) +#20623=* +tokeninfo(#20623,8,#20001,37,";") +#20624=@"loc,{#10000},19,9,19,9" +locations_default(#20624,#10000,19,9,19,9) +hasLocation(#20623,#20624) #20625=* -tokeninfo(#20625,8,#20001,39,";") -#20626=@"loc,{#10000},20,10,20,10" -locations_default(#20626,#10000,20,10,20,10) -hasLocation(#20625,#20626) -#20627=* -tokeninfo(#20627,5,#20001,40,"/./") -hasLocation(#20627,#20202) +tokeninfo(#20625,5,#20001,38,"/a{1,2}?/") +hasLocation(#20625,#20194) +#20626=* +tokeninfo(#20626,8,#20001,39,";") +#20627=@"loc,{#10000},20,10,20,10" +locations_default(#20627,#10000,20,10,20,10) +hasLocation(#20626,#20627) #20628=* -tokeninfo(#20628,8,#20001,41,";") -#20629=@"loc,{#10000},21,4,21,4" -locations_default(#20629,#10000,21,4,21,4) -hasLocation(#20628,#20629) -#20630=* -tokeninfo(#20630,5,#20001,42,"/(abc)/") -hasLocation(#20630,#20208) +tokeninfo(#20628,5,#20001,40,"/./") +hasLocation(#20628,#20202) +#20629=* +tokeninfo(#20629,8,#20001,41,";") +#20630=@"loc,{#10000},21,4,21,4" +locations_default(#20630,#10000,21,4,21,4) +hasLocation(#20629,#20630) #20631=* -tokeninfo(#20631,8,#20001,43,";") -#20632=@"loc,{#10000},22,8,22,8" -locations_default(#20632,#10000,22,8,22,8) -hasLocation(#20631,#20632) -#20633=* -tokeninfo(#20633,5,#20001,44,"/(?:abc)/") -hasLocation(#20633,#20222) +tokeninfo(#20631,5,#20001,42,"/(abc)/") +hasLocation(#20631,#20208) +#20632=* +tokeninfo(#20632,8,#20001,43,";") +#20633=@"loc,{#10000},22,8,22,8" +locations_default(#20633,#10000,22,8,22,8) +hasLocation(#20632,#20633) #20634=* -tokeninfo(#20634,8,#20001,45,";") -#20635=@"loc,{#10000},23,10,23,10" -locations_default(#20635,#10000,23,10,23,10) -hasLocation(#20634,#20635) -#20636=* -tokeninfo(#20636,5,#20001,46,"/\x0a/") -hasLocation(#20636,#20236) +tokeninfo(#20634,5,#20001,44,"/(?:abc)/") +hasLocation(#20634,#20222) +#20635=* +tokeninfo(#20635,8,#20001,45,";") +#20636=@"loc,{#10000},23,10,23,10" +locations_default(#20636,#10000,23,10,23,10) +hasLocation(#20635,#20636) #20637=* -tokeninfo(#20637,8,#20001,47,";") -#20638=@"loc,{#10000},24,7,24,7" -locations_default(#20638,#10000,24,7,24,7) -hasLocation(#20637,#20638) -#20639=* -tokeninfo(#20639,5,#20001,48,"/\u000a/") -hasLocation(#20639,#20242) +tokeninfo(#20637,5,#20001,46,"/\x0a/") +hasLocation(#20637,#20236) +#20638=* +tokeninfo(#20638,8,#20001,47,";") +#20639=@"loc,{#10000},24,7,24,7" +locations_default(#20639,#10000,24,7,24,7) +hasLocation(#20638,#20639) #20640=* -tokeninfo(#20640,8,#20001,49,";") -#20641=@"loc,{#10000},25,9,25,9" -locations_default(#20641,#10000,25,9,25,9) -hasLocation(#20640,#20641) -#20642=* -tokeninfo(#20642,5,#20001,50,"/\10/") -hasLocation(#20642,#20248) +tokeninfo(#20640,5,#20001,48,"/\u000a/") +hasLocation(#20640,#20242) +#20641=* +tokeninfo(#20641,8,#20001,49,";") +#20642=@"loc,{#10000},25,9,25,9" +locations_default(#20642,#10000,25,9,25,9) +hasLocation(#20641,#20642) #20643=* -tokeninfo(#20643,8,#20001,51,";") -#20644=@"loc,{#10000},26,6,26,6" -locations_default(#20644,#10000,26,6,26,6) -hasLocation(#20643,#20644) -#20645=* -tokeninfo(#20645,5,#20001,52,"/\t\n\r\f\v/") -hasLocation(#20645,#20254) +tokeninfo(#20643,5,#20001,50,"/\10/") +hasLocation(#20643,#20248) +#20644=* +tokeninfo(#20644,8,#20001,51,";") +#20645=@"loc,{#10000},26,6,26,6" +locations_default(#20645,#10000,26,6,26,6) +hasLocation(#20644,#20645) #20646=* -tokeninfo(#20646,8,#20001,53,";") -#20647=@"loc,{#10000},27,13,27,13" -locations_default(#20647,#10000,27,13,27,13) -hasLocation(#20646,#20647) -#20648=* -tokeninfo(#20648,5,#20001,54,"/\ca\cN/") -hasLocation(#20648,#20270) +tokeninfo(#20646,5,#20001,52,"/\t\n\r\f\v/") +hasLocation(#20646,#20255) +#20647=* +tokeninfo(#20647,8,#20001,53,";") +#20648=@"loc,{#10000},27,13,27,13" +locations_default(#20648,#10000,27,13,27,13) +hasLocation(#20647,#20648) #20649=* -tokeninfo(#20649,8,#20001,55,";") -#20650=@"loc,{#10000},28,9,28,9" -locations_default(#20650,#10000,28,9,28,9) -hasLocation(#20649,#20650) -#20651=* -tokeninfo(#20651,5,#20001,56,"/\w\S/") -hasLocation(#20651,#20280) +tokeninfo(#20649,5,#20001,54,"/\ca\cN/") +hasLocation(#20649,#20271) +#20650=* +tokeninfo(#20650,8,#20001,55,";") +#20651=@"loc,{#10000},28,9,28,9" +locations_default(#20651,#10000,28,9,28,9) +hasLocation(#20650,#20651) #20652=* -tokeninfo(#20652,8,#20001,57,";") -#20653=@"loc,{#10000},29,7,29,7" -locations_default(#20653,#10000,29,7,29,7) -hasLocation(#20652,#20653) -#20654=* -tokeninfo(#20654,5,#20001,58,"/\\/") -hasLocation(#20654,#20290) +tokeninfo(#20652,5,#20001,56,"/\w\S/") +hasLocation(#20652,#20281) +#20653=* +tokeninfo(#20653,8,#20001,57,";") +#20654=@"loc,{#10000},29,7,29,7" +locations_default(#20654,#10000,29,7,29,7) +hasLocation(#20653,#20654) #20655=* -tokeninfo(#20655,8,#20001,59,";") -#20656=@"loc,{#10000},30,5,30,5" -locations_default(#20656,#10000,30,5,30,5) -hasLocation(#20655,#20656) -#20657=* -tokeninfo(#20657,5,#20001,60,"/[abc]/") -hasLocation(#20657,#20296) +tokeninfo(#20655,5,#20001,58,"/\\/") +hasLocation(#20655,#20291) +#20656=* +tokeninfo(#20656,8,#20001,59,";") +#20657=@"loc,{#10000},30,5,30,5" +locations_default(#20657,#10000,30,5,30,5) +hasLocation(#20656,#20657) #20658=* -tokeninfo(#20658,8,#20001,61,";") -#20659=@"loc,{#10000},31,8,31,8" -locations_default(#20659,#10000,31,8,31,8) -hasLocation(#20658,#20659) -#20660=* -tokeninfo(#20660,5,#20001,62,"/[a-z]/") -hasLocation(#20660,#20308) +tokeninfo(#20658,5,#20001,60,"/[abc]/") +hasLocation(#20658,#20297) +#20659=* +tokeninfo(#20659,8,#20001,61,";") +#20660=@"loc,{#10000},31,8,31,8" +locations_default(#20660,#10000,31,8,31,8) +hasLocation(#20659,#20660) #20661=* -tokeninfo(#20661,8,#20001,63,";") -#20662=@"loc,{#10000},32,8,32,8" -locations_default(#20662,#10000,32,8,32,8) -hasLocation(#20661,#20662) -#20663=* -tokeninfo(#20663,5,#20001,64,"/[a-zA-Z]/") -hasLocation(#20663,#20320) +tokeninfo(#20661,5,#20001,62,"/[a-z]/") +hasLocation(#20661,#20309) +#20662=* +tokeninfo(#20662,8,#20001,63,";") +#20663=@"loc,{#10000},32,8,32,8" +locations_default(#20663,#10000,32,8,32,8) +hasLocation(#20662,#20663) #20664=* -tokeninfo(#20664,8,#20001,65,";") -#20665=@"loc,{#10000},33,11,33,11" -locations_default(#20665,#10000,33,11,33,11) -hasLocation(#20664,#20665) -#20666=* -tokeninfo(#20666,5,#20001,66,"/[-a-z]/") -hasLocation(#20666,#20338) +tokeninfo(#20664,5,#20001,64,"/[a-zA-Z]/") +hasLocation(#20664,#20321) +#20665=* +tokeninfo(#20665,8,#20001,65,";") +#20666=@"loc,{#10000},33,11,33,11" +locations_default(#20666,#10000,33,11,33,11) +hasLocation(#20665,#20666) #20667=* -tokeninfo(#20667,8,#20001,67,";") -#20668=@"loc,{#10000},34,9,34,9" -locations_default(#20668,#10000,34,9,34,9) -hasLocation(#20667,#20668) -#20669=* -tokeninfo(#20669,5,#20001,68,"/[^a-z]/") -hasLocation(#20669,#20352) +tokeninfo(#20667,5,#20001,66,"/[-a-z]/") +hasLocation(#20667,#20339) +#20668=* +tokeninfo(#20668,8,#20001,67,";") +#20669=@"loc,{#10000},34,9,34,9" +locations_default(#20669,#10000,34,9,34,9) +hasLocation(#20668,#20669) #20670=* -tokeninfo(#20670,8,#20001,69,";") -#20671=@"loc,{#10000},35,9,35,9" -locations_default(#20671,#10000,35,9,35,9) -hasLocation(#20670,#20671) -#20672=* -tokeninfo(#20672,5,#20001,70,"/[a\b\x0c]/") -hasLocation(#20672,#20364) +tokeninfo(#20670,5,#20001,68,"/[^a-z]/") +hasLocation(#20670,#20353) +#20671=* +tokeninfo(#20671,8,#20001,69,";") +#20672=@"loc,{#10000},35,9,35,9" +locations_default(#20672,#10000,35,9,35,9) +hasLocation(#20671,#20672) #20673=* -tokeninfo(#20673,8,#20001,71,";") -#20674=@"loc,{#10000},36,12,36,12" -locations_default(#20674,#10000,36,12,36,12) -hasLocation(#20673,#20674) -#20675=* -tokeninfo(#20675,5,#20001,72,"/a{/") -hasLocation(#20675,#20376) +tokeninfo(#20673,5,#20001,70,"/[a\b\x0c]/") +hasLocation(#20673,#20365) +#20674=* +tokeninfo(#20674,8,#20001,71,";") +#20675=@"loc,{#10000},36,12,36,12" +locations_default(#20675,#10000,36,12,36,12) +hasLocation(#20674,#20675) #20676=* -tokeninfo(#20676,8,#20001,73,";") -#20677=@"loc,{#10000},37,5,37,5" -locations_default(#20677,#10000,37,5,37,5) -hasLocation(#20676,#20677) -#20678=* -tokeninfo(#20678,5,#20001,74,"/a{b}/") -hasLocation(#20678,#20388) +tokeninfo(#20676,5,#20001,72,"/a{/") +hasLocation(#20676,#20377) +#20677=* +tokeninfo(#20677,8,#20001,73,";") +#20678=@"loc,{#10000},37,5,37,5" +locations_default(#20678,#10000,37,5,37,5) +hasLocation(#20677,#20678) #20679=* -tokeninfo(#20679,8,#20001,75,";") -#20680=@"loc,{#10000},38,7,38,7" -locations_default(#20680,#10000,38,7,38,7) -hasLocation(#20679,#20680) -#20681=* -tokeninfo(#20681,5,#20001,76,"/a{2/") -hasLocation(#20681,#20406) +tokeninfo(#20679,5,#20001,74,"/a{b}/") +hasLocation(#20679,#20389) +#20680=* +tokeninfo(#20680,8,#20001,75,";") +#20681=@"loc,{#10000},38,7,38,7" +locations_default(#20681,#10000,38,7,38,7) +hasLocation(#20680,#20681) #20682=* -tokeninfo(#20682,8,#20001,77,";") -#20683=@"loc,{#10000},39,6,39,6" -locations_default(#20683,#10000,39,6,39,6) -hasLocation(#20682,#20683) -#20684=* -tokeninfo(#20684,5,#20001,78,"/\xa/") -hasLocation(#20684,#20416) +tokeninfo(#20682,5,#20001,76,"/a{2/") +hasLocation(#20682,#20407) +#20683=* +tokeninfo(#20683,8,#20001,77,";") +#20684=@"loc,{#10000},39,6,39,6" +locations_default(#20684,#10000,39,6,39,6) +hasLocation(#20683,#20684) #20685=* -tokeninfo(#20685,8,#20001,79,";") -#20686=@"loc,{#10000},40,6,40,6" -locations_default(#20686,#10000,40,6,40,6) -hasLocation(#20685,#20686) -#20687=* -tokeninfo(#20687,5,#20001,80,"/\c0/") -hasLocation(#20687,#20424) +tokeninfo(#20685,5,#20001,78,"/\xa/") +hasLocation(#20685,#20417) +#20686=* +tokeninfo(#20686,8,#20001,79,";") +#20687=@"loc,{#10000},40,6,40,6" +locations_default(#20687,#10000,40,6,40,6) +hasLocation(#20686,#20687) #20688=* -tokeninfo(#20688,8,#20001,81,";") -#20689=@"loc,{#10000},41,6,41,6" -locations_default(#20689,#10000,41,6,41,6) -hasLocation(#20688,#20689) -#20690=* -tokeninfo(#20690,5,#20001,82,"/[]/") -hasLocation(#20690,#20432) +tokeninfo(#20688,5,#20001,80,"/\c0/") +hasLocation(#20688,#20425) +#20689=* +tokeninfo(#20689,8,#20001,81,";") +#20690=@"loc,{#10000},41,6,41,6" +locations_default(#20690,#10000,41,6,41,6) +hasLocation(#20689,#20690) #20691=* -tokeninfo(#20691,8,#20001,83,";") -#20692=@"loc,{#10000},42,5,42,5" -locations_default(#20692,#10000,42,5,42,5) -hasLocation(#20691,#20692) -#20693=* -tokeninfo(#20693,5,#20001,84,"/[^]/") -hasLocation(#20693,#20438) +tokeninfo(#20691,5,#20001,82,"/[]/") +hasLocation(#20691,#20433) +#20692=* +tokeninfo(#20692,8,#20001,83,";") +#20693=@"loc,{#10000},42,5,42,5" +locations_default(#20693,#10000,42,5,42,5) +hasLocation(#20692,#20693) #20694=* -tokeninfo(#20694,8,#20001,85,";") -#20695=@"loc,{#10000},43,6,43,6" -locations_default(#20695,#10000,43,6,43,6) -hasLocation(#20694,#20695) -#20696=* -tokeninfo(#20696,5,#20001,86,"/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/") -hasLocation(#20696,#20444) +tokeninfo(#20694,5,#20001,84,"/[^]/") +hasLocation(#20694,#20439) +#20695=* +tokeninfo(#20695,8,#20001,85,";") +#20696=@"loc,{#10000},43,6,43,6" +locations_default(#20696,#10000,43,6,43,6) +hasLocation(#20695,#20696) #20697=* -tokeninfo(#20697,8,#20001,87,";") -#20698=@"loc,{#10000},44,60,44,60" -locations_default(#20698,#10000,44,60,44,60) -hasLocation(#20697,#20698) -#20699=* -tokeninfo(#20699,0,#20001,88,"") -#20700=@"loc,{#10000},44,61,44,60" -locations_default(#20700,#10000,44,61,44,60) -hasLocation(#20699,#20700) -#20701=* -entry_cfg_node(#20701,#20001) -#20702=@"loc,{#10000},1,1,1,0" -locations_default(#20702,#10000,1,1,1,0) -hasLocation(#20701,#20702) -#20703=* -exit_cfg_node(#20703,#20001) -hasLocation(#20703,#20700) -successor(#20441,#20443) -successor(#20443,#20703) -successor(#20435,#20437) -successor(#20437,#20441) -successor(#20429,#20431) -successor(#20431,#20435) -successor(#20421,#20423) -successor(#20423,#20429) -successor(#20413,#20415) -successor(#20415,#20421) -successor(#20403,#20405) -successor(#20405,#20413) -successor(#20385,#20387) -successor(#20387,#20403) -successor(#20373,#20375) -successor(#20375,#20385) -successor(#20361,#20363) -successor(#20363,#20373) -successor(#20349,#20351) -successor(#20351,#20361) -successor(#20335,#20337) -successor(#20337,#20349) -successor(#20317,#20319) -successor(#20319,#20335) -successor(#20305,#20307) -successor(#20307,#20317) -successor(#20293,#20295) -successor(#20295,#20305) -successor(#20287,#20289) -successor(#20289,#20293) -successor(#20277,#20279) -successor(#20279,#20287) -successor(#20267,#20269) -successor(#20269,#20277) -successor(#20251,#20253) -successor(#20253,#20267) +tokeninfo(#20697,5,#20001,86,"/]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/") +hasLocation(#20697,#20445) +#20698=* +tokeninfo(#20698,8,#20001,87,";") +#20699=@"loc,{#10000},44,60,44,60" +locations_default(#20699,#10000,44,60,44,60) +hasLocation(#20698,#20699) +#20700=* +tokeninfo(#20700,0,#20001,88,"") +#20701=@"loc,{#10000},44,61,44,60" +locations_default(#20701,#10000,44,61,44,60) +hasLocation(#20700,#20701) +#20702=* +entry_cfg_node(#20702,#20001) +#20703=@"loc,{#10000},1,1,1,0" +locations_default(#20703,#10000,1,1,1,0) +hasLocation(#20702,#20703) +#20704=* +exit_cfg_node(#20704,#20001) +hasLocation(#20704,#20701) +successor(#20442,#20444) +successor(#20444,#20704) +successor(#20436,#20438) +successor(#20438,#20442) +successor(#20430,#20432) +successor(#20432,#20436) +successor(#20422,#20424) +successor(#20424,#20430) +successor(#20414,#20416) +successor(#20416,#20422) +successor(#20404,#20406) +successor(#20406,#20414) +successor(#20386,#20388) +successor(#20388,#20404) +successor(#20374,#20376) +successor(#20376,#20386) +successor(#20362,#20364) +successor(#20364,#20374) +successor(#20350,#20352) +successor(#20352,#20362) +successor(#20336,#20338) +successor(#20338,#20350) +successor(#20318,#20320) +successor(#20320,#20336) +successor(#20306,#20308) +successor(#20308,#20318) +successor(#20294,#20296) +successor(#20296,#20306) +successor(#20288,#20290) +successor(#20290,#20294) +successor(#20278,#20280) +successor(#20280,#20288) +successor(#20268,#20270) +successor(#20270,#20278) +successor(#20252,#20254) +successor(#20254,#20268) successor(#20245,#20247) -successor(#20247,#20251) +successor(#20247,#20252) successor(#20239,#20241) successor(#20241,#20245) successor(#20233,#20235) @@ -2245,6 +2248,6 @@ successor(#20009,#20011) successor(#20011,#20031) successor(#20003,#20005) successor(#20005,#20009) -successor(#20701,#20003) +successor(#20702,#20003) numlines(#10000,44,44,0) filetype(#10000,"javascript") diff --git a/javascript/extractor/tests/regexp/input/es2018.js b/javascript/extractor/tests/regexp/input/es2018.js index f7d0d826b2c..fef868bf99b 100644 --- a/javascript/extractor/tests/regexp/input/es2018.js +++ b/javascript/extractor/tests/regexp/input/es2018.js @@ -3,3 +3,4 @@ /(?$/;") @@ -169,81 +169,125 @@ hasLocation(#20051,#20052) unicodePropertyEscapeName(#20051,"Script") unicodePropertyEscapeValue(#20051,"Greek") #20053=* -lines(#20053,#20001,"/^(?\s+)\w+\k$/;"," -") -hasLocation(#20053,#20004) -#20054=* -lines(#20054,#20001,"/(?<=.)/;"," -") -hasLocation(#20054,#20026) +stmts(#20053,2,#20001,5,"/\k\s+)\w+\k$/") -hasLocation(#20058,#20006) +regexpterm(#20057,22,#20055,0,"\k<") +#20058=@"loc,{#10000},6,2,6,4" +locations_default(#20058,#10000,6,2,6,4) +hasLocation(#20057,#20058) +namedBackref(#20057,"") #20059=* -tokeninfo(#20059,8,#20001,1,";") -#20060=@"loc,{#10000},1,24,1,24" -locations_default(#20060,#10000,1,24,1,24) +regexpParseErrors(#20059,#20057,"expected identifier") +#20060=@"loc,{#10000},6,5,6,5" +locations_default(#20060,#10000,6,5,6,5) hasLocation(#20059,#20060) #20061=* -tokeninfo(#20061,5,#20001,2,"/(?<=.)/") -hasLocation(#20061,#20028) -#20062=* -tokeninfo(#20062,8,#20001,3,";") -#20063=@"loc,{#10000},2,9,2,9" -locations_default(#20063,#10000,2,9,2,9) -hasLocation(#20062,#20063) +regexpParseErrors(#20061,#20057,"expected '>'") +#20062=@"loc,{#10000},6,4,6,4" +locations_default(#20062,#10000,6,4,6,4) +hasLocation(#20061,#20062) +#20063=* +lines(#20063,#20001,"/^(?\s+)\w+\k$/;"," +") +hasLocation(#20063,#20004) #20064=* -tokeninfo(#20064,5,#20001,4,"/(?\s+)\w+\k$/") +hasLocation(#20069,#20006) #20070=* -tokeninfo(#20070,5,#20001,8,"/\P{Script=Greek}/u") -hasLocation(#20070,#20050) -#20071=* -tokeninfo(#20071,8,#20001,9,";") -#20072=@"loc,{#10000},5,20,5,20" -locations_default(#20072,#10000,5,20,5,20) -hasLocation(#20071,#20072) +tokeninfo(#20070,8,#20001,1,";") +#20071=@"loc,{#10000},1,24,1,24" +locations_default(#20071,#10000,1,24,1,24) +hasLocation(#20070,#20071) +#20072=* +tokeninfo(#20072,5,#20001,2,"/(?<=.)/") +hasLocation(#20072,#20028) #20073=* -tokeninfo(#20073,0,#20001,10,"") -#20074=@"loc,{#10000},6,1,6,0" -locations_default(#20074,#10000,6,1,6,0) +tokeninfo(#20073,8,#20001,3,";") +#20074=@"loc,{#10000},2,9,2,9" +locations_default(#20074,#10000,2,9,2,9) hasLocation(#20073,#20074) #20075=* -entry_cfg_node(#20075,#20001) -#20076=@"loc,{#10000},1,1,1,0" -locations_default(#20076,#10000,1,1,1,0) -hasLocation(#20075,#20076) -#20077=* -exit_cfg_node(#20077,#20001) -hasLocation(#20077,#20074) +tokeninfo(#20075,5,#20001,4,"/(?