// Parse the rest of a UTF-8 sequence within an encoded URI. private static int ParseRestOfUTF8(int utf8, string uri, ref int _index) { int index = _index; int size; int utf8Char; if ((utf8 & 0xE0) == 0xC0) { size = 1; utf8 &= 0x1F; } else if ((utf8 & 0xF0) == 0xE0) { size = 2; utf8 &= 0x0F; } else if ((utf8 & 0xF8) == 0xF0) { size = 3; utf8 &= 0x07; } else if ((utf8 & 0xFC) == 0xF8) { size = 4; utf8 &= 0x03; } else { // Invalid UTF-8 start character. throw new JScriptException(JSError.URIDecodeError); } while (size > 0) { if ((index + 2) >= uri.Length || uri[index] != '%' || !JSScanner.IsHexDigit(uri[index + 1]) || !JSScanner.IsHexDigit(uri[index + 2])) { throw new JScriptException(JSError.URIDecodeError); } utf8Char = (JSScanner.FromHex(uri[index + 1]) << 4) | JSScanner.FromHex(uri[index + 2]); if ((utf8Char & 0xC0) != 0x80) { // Invalid UTF-8 component character. throw new JScriptException(JSError.URIDecodeError); } index += 3; utf8 = (utf8 << 6) | (utf8Char & 0x3F); --size; } _index = index; if (utf8 < 0) { // Invalid UTF-8 character. throw new JScriptException(JSError.URIDecodeError); } return(utf8); }
//--------------------------------------------------------------------------------------- // JSParser // // create a parser with a context. The context is the code that has to be compiled. // Typically used by the runtime //--------------------------------------------------------------------------------------- public JSParser(Context context){ this.sourceContext = context; this.currentToken = context.Clone(); this.scanner = new JSScanner(this.currentToken); this.noSkipTokenSet = new NoSkipTokenSet(); this.errorToken = null; this.program = null; this.blockType = new ArrayList(16); this.labelTable = new SimpleHashtable(16); this.finallyEscaped = 0; this.Globals = context.document.engine.Globals; this.Severity = 5; }
// Constructor. public JSParser(Context context) { this.context = context; if(context != null) { scanner = new JSScanner(context); } else { scanner = new JSScanner(); } tokenInfo = scanner.GetTokenContext(); token = tokenInfo.token; numErrors = 0; }
public static string unescape(object str) { string s = Convert.ToString(str); StringBuilder builder = new StringBuilder(s.Length); int index = 0; char ch; while (index < s.Length) { ch = s[index++]; if (ch != '%') { builder.Append(ch); } else if ((index + 1) < s.Length && JSScanner.IsHexDigit(s[index]) && JSScanner.IsHexDigit(s[index + 1])) { ch = (char)((JSScanner.FromHex(s[index]) << 4) | JSScanner.FromHex(s[index + 1])); builder.Append(ch); index += 2; } else if ((index + 4) < s.Length && s[index] == 'u' && JSScanner.IsHexDigit(s[index + 1]) && JSScanner.IsHexDigit(s[index + 2]) && JSScanner.IsHexDigit(s[index + 3]) && JSScanner.IsHexDigit(s[index + 4])) { ch = (char)((JSScanner.FromHex(s[index + 1]) << 12) | (JSScanner.FromHex(s[index + 2]) << 8) | (JSScanner.FromHex(s[index + 3]) << 4) | JSScanner.FromHex(s[index + 4])); builder.Append(ch); index += 5; } else { builder.Append(ch); } } return(builder.ToString()); }
// GetScannerInstance is used by IsValidNamespaceName and IsValidIdentifier to validate names. // We return an instance of the scanner only if there is no whitespace in the name text, since // we do not want to allow, say, "not. valid" to be a valid namespace name even though that // would produce a valid sequence of tokens. private JSScanner GetScannerInstance(string name){ // make sure there's no whitespace in the name (values copied from documentation on String.Trim()) char[] anyWhiteSpace = { (char)0x0009, (char)0x000A, (char)0x000B, (char)0x000C, (char)0x000D, (char)0x0020, (char)0x00A0, (char)0x2000, (char)0x2001, (char)0x2002, (char)0x2003, (char)0x2004, (char)0x2005, (char)0x2006, (char)0x2007, (char)0x2008, (char)0x2009, (char)0x200A, (char)0x200B, (char)0x3000, (char)0xFEFF }; if (name == null || name.IndexOfAny(anyWhiteSpace) > -1) return null; // Create a code item whose source is the given text VsaItem item = new VsaStaticCode(this, "itemName", VsaItemFlag.None); Context context = new Context(new DocumentContext(item), name); context.errorReported = -1; JSScanner scanner = new JSScanner(); //Use this constructor to avoid allocating a Globals instance scanner.SetSource(context); return scanner; }
// Parse a regular expression from a scanner. public static bool TestParseRegex(JSScanner scanner, out String regex) { return(scanner.ParseRegex(out regex)); }
// Extract token information from a scanner. public static Context TestGetTokenContext(JSScanner scanner) { return(scanner.GetTokenContext()); }
// Get the last-parsed identifier name from a scanner. public static String TestGetIdentifierName(JSScanner scanner) { return(scanner.GetIdentifierName()); }
// Internal URI decoding logic. private static string InternalDecode(string uri, bool reserved) { StringBuilder builder = new StringBuilder(uri.Length); int index = 0; char ch; int utf8Char; int start; while (index < uri.Length) { ch = uri[index++]; if (ch != '%') { builder.Append(ch); } else if ((index + 1) >= uri.Length || !JSScanner.IsHexDigit(uri[index]) || !JSScanner.IsHexDigit(uri[index + 1])) { // Invalid hexadecimal sequence. throw new JScriptException(JSError.URIDecodeError); } else { start = index - 1; utf8Char = (JSScanner.FromHex(uri[index]) << 4) | JSScanner.FromHex(uri[index + 1]); index += 2; if (utf8Char >= 0x80) { // Parse the rest of the UTF-8 sequence. utf8Char = ParseRestOfUTF8 (utf8Char, uri, ref index); } if (utf8Char < 0x10000) { // Single-character. if (reserved && IsURIReserved((char)utf8Char)) { builder.Append(uri, start, index - start); } else { builder.Append((char)utf8Char); } } else if (utf8Char < 0x110000) { // Surrogate pair. utf8Char -= 0x10000; builder.Append((char)((utf8Char >> 10) + 0xD800)); builder.Append((char)((utf8Char & 0x3FF) + 0xDC00)); } else { // UTF-8 character is out of range. throw new JScriptException(JSError.URIDecodeError); } } } return(builder.ToString()); }
// Determine if a namespace name is valid. protected override bool IsValidNamespaceName(String name) { if(name == null) { return false; } JSScanner scanner = new JSScanner(name); if(scanner.FetchIdentifier() == null) { return false; } while(scanner.Peek() == '.') { scanner.Fetch(); if(scanner.FetchIdentifier() == null) { return false; } } return (scanner.Fetch() == -1); }
// Determine if an identifier is valid for this engine. public override bool IsValidIdentifier(String identifier) { if(identifier == null) { return false; } JSScanner scanner = new JSScanner(identifier); if(scanner.FetchIdentifier() == null) { return false; } return (scanner.Fetch() == -1); }
private JSScanner GetScannerInstance(string name) { char[] anyOf = new char[] { '\t', '\n', '\v', '\f', '\r', ' ', '\x00a0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', ' ', '' }; if ((name == null) || (name.IndexOfAny(anyOf) > -1)) { return null; } VsaItem sourceItem = new VsaStaticCode(this, "itemName", JSVsaItemFlag.None); Context sourceContext = new Context(new DocumentContext(sourceItem), name) { errorReported = -1 }; JSScanner scanner = new JSScanner(); scanner.SetSource(sourceContext); return scanner; }
// Parse a regular expression from a scanner. public static bool TestParseRegex(JSScanner scanner, out String regex) { return scanner.ParseRegex(out regex); }
// Extract token information from a scanner. public static Context TestGetTokenContext(JSScanner scanner) { return scanner.GetTokenContext(); }
// Get the last-parsed identifier name from a scanner. public static String TestGetIdentifierName(JSScanner scanner) { return scanner.GetIdentifierName(); }