internal static AliasIdentifierToken Read(ILexerStream stream) { var extent = new SourceExtent(stream); var sourceChars = new List<char>(); // read the first character sourceChars.Add(stream.ReadChar('$')); // read the name var nameChars = new List<char>(); while (!stream.Eof) { extent = extent.WithEndExtent(stream); var peek = stream.Peek(); if (char.IsLetterOrDigit(peek) || ("_".IndexOf(peek) != -1) ) { var @char = stream.Read(); sourceChars.Add(@char); nameChars.Add(@char); } else { break; } } // return the result extent = extent.WithText(sourceChars); var name = new string(nameChars.ToArray()); return new AliasIdentifierToken(extent, name); }
internal static StringLiteralToken Read(ILexerStream stream) { var extent = new SourceExtent(stream); var sourceChars = new List<char>(); // read the first character sourceChars.Add(stream.ReadChar('"')); // read the remaining characters var parser = new StringParser(); while (!stream.Eof) { var peek = stream.Peek(); sourceChars.Add(peek); if ((peek == '"') && !parser.IsEscaped) { parser.ConsumeEof(); break; } else { parser.ConsumeChar(stream.Read()); } } // read the last character sourceChars.Add(stream.ReadChar('"')); // process any escape sequences in the string var unescaped = parser.OutputString.ToString(); // return the result extent = extent.WithText(sourceChars); return new StringLiteralToken(extent, unescaped); }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> /// <remarks> /// /// See http://www.dmtf.org/sites/default/files/standards/documents/DSP0221_3.0.0a.pdf /// /// A.17.3 String values /// /// Unless explicitly specified via ABNF rule WS, no whitespace is allowed between the elements of the rules /// in this ABNF section. /// /// stringValue = DOUBLEQUOTE *stringChar DOUBLEQUOTE /// *( *WS DOUBLEQUOTE *stringChar DOUBLEQUOTE ) /// stringChar = stringUCSchar / stringEscapeSequence /// /// </remarks> private static StringLiteralToken ReadStringLiteralToken(ILexerStream stream) { // BUGBUG - no support for *( *WS DOUBLEQUOTE *stringChar DOUBLEQUOTE ) // BUGBUG - incomplete escape sequences // BUGBUG - no support for UCS characters var sourceChars = new List <SourceChar>(); // read the first character sourceChars.Add(stream.ReadChar('"')); // read the remaining characters var parser = new StringLiteralParser(); while (!stream.Eof) { var peek = stream.Peek(); if (StringValidator.IsDoubleQuote(peek.Value) && !parser.IsEscaped) { parser.ConsumeEos(); break; } else { sourceChars.Add(peek); parser.ConsumeChar(stream.Read()); } } // read the last character sourceChars.Add(stream.ReadChar('"')); // process any escape sequences in the string var unescaped = parser.OutputString.ToString(); // return the result var extent = new SourceExtent(sourceChars); return(new StringLiteralToken(extent, unescaped)); }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> /// <remarks> /// /// See http://www.dmtf.org/sites/default/files/standards/documents/DSP0221_3.0.0.pdf /// /// A.13 Names /// /// MOF names are identifiers with the format defined by the IDENTIFIER rule. /// No whitespace is allowed between the elements of the rules in this ABNF section. /// /// IDENTIFIER = firstIdentifierChar *( nextIdentifierChar ) /// firstIdentifierChar = UPPERALPHA / LOWERALPHA / UNDERSCORE /// nextIdentifierChar = firstIdentifierChar / decimalDigit /// elementName = localName / schemaQualifiedName /// localName = IDENTIFIER /// /// </remarks> private static IdentifierToken ReadIdentifierToken(ILexerStream stream) { var sourceChars = new List <SourceChar>(); var nameChars = new List <char>(); // firstIdentifierChar var peek = stream.Peek(); if (!StringValidator.IsFirstIdentifierChar(peek.Value)) { throw new InvalidOperationException( string.Format("Unexpected character '{0}' encountered", peek.Value)); } // *( nextIdentifierChar ) while (!stream.Eof) { peek = stream.Peek(); if (StringValidator.IsNextIdentifierChar(peek.Value)) { var @char = stream.Read(); sourceChars.Add(@char); nameChars.Add(@char.Value); } else { break; } } // return the result var extent = new SourceExtent(sourceChars); var name = new string(nameChars.ToArray()); return(new IdentifierToken(extent, name)); }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> /// <remarks> /// /// See http://www.dmtf.org/sites/default/files/standards/documents/DSP0221_3.0.0a.pdf /// /// A.17.1 Integer value /// /// No whitespace is allowed between the elements of the rules in this ABNF section. /// /// integerValue = binaryValue / octalValue / hexValue / decimalValue /// /// binaryValue = [ "+" / "-" ] 1*binaryDigit ( "b" / "B" ) /// binaryDigit = "0" / "1" /// /// octalValue = [ "+" / "-" ] unsignedOctalValue /// unsignedOctalValue = "0" 1*octalDigit /// octalDigit = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" /// /// hexValue = [ "+" / "-" ] ( "0x" / "0X" ) 1*hexDigit /// hexDigit = decimalDigit / "a" / "A" / "b" / "B" / "c" / "C" / /// "d" / "D" / "e" / "E" / "f" / "F" /// /// decimalValue = [ "+" / "-" ] unsignedDecimalValue /// unsignedDecimalValue = positiveDecimalDigit *decimalDigit /// decimalDigit = "0" / positiveDecimalDigit /// positiveDecimalDigit = "1"..."9" /// /// </remarks> private static NumericLiteralToken ReadNumericLiteralToken(ILexerStream stream) { var sourceChars = new List <SourceChar>(); // read the sign (if there is one) var sign = 0; var peek = stream.Peek(); switch (peek.Value) { case '+': sign = 1; sourceChars.Add(stream.Read()); break; case '-': sign = -1; sourceChars.Add(stream.Read()); break; } // read the remaining characters sourceChars.Add(stream.ReadDigit()); while (!stream.Eof && stream.PeekDigit()) { sourceChars.Add(stream.ReadDigit()); } // return the result var extent = new SourceExtent(sourceChars); long longValue; decimal decimalValue; if (long.TryParse(extent.Text, out longValue)) { return(new IntegerLiteralToken(extent, longValue)); } if (decimal.TryParse(extent.Text, out decimalValue)) { return(new RealLiteralToken(extent, decimalValue)); } throw new NotSupportedException($"{extent.Text} is not a valid number"); }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> /// <remarks> /// /// See http://www.dmtf.org/sites/default/files/standards/documents/DSP0221_3.0.0.pdf /// /// 5.4 Comments /// Comments in a MOF file do not create, modify, or annotate language elements. They shall be treated as if /// they were whitespace. /// /// Comments may appear anywhere in MOF syntax where whitespace is allowed and are indicated by either /// a leading double slash( // ) or a pair of matching /* and */ character sequences. Occurrences of these /// character sequences in string literals shall not be treated as comments. /// /// A // comment is terminated by the end of line (see 5.3), as shown in the example below. /// /// uint16 MyProperty; // This is an example of a single-line comment /// /// A comment that begins with /* is terminated by the next */ sequence, or by the end of the MOF file, /// whichever comes first. /// /// /* example of a comment between property definition tokens and a multi-line comment */ /// uint16 /* 16-bit integer property */ MyProperty; /* and a multi-line /// comment */ /// /// </remarks> private static CommentToken ReadCommentToken(ILexerStream stream) { var sourceChars = new List <SourceChar>(); sourceChars.Add(stream.ReadChar('/')); switch (stream.Peek().Value) { case '/': // single-line sourceChars.Add(stream.ReadChar('/')); // read the comment text while (!stream.Eof && !StringValidator.IsLineTerminator(stream.Peek().Value)) { sourceChars.Add(stream.Read()); } ; break; case '*': // multi-line sourceChars.Add(stream.ReadChar('*')); // read the comment text while (!stream.Eof) { var @char = stream.Read(); sourceChars.Add(@char); if ((@char.Value == '*') && stream.PeekChar('/')) { // read the closing sequence sourceChars.Add(stream.ReadChar('/')); break; } } break; default: throw new InvalidOperationException( string.Format("Unexpected character '{0}'.", stream.Peek())); } // return the result var extent = new SourceExtent(sourceChars); return(new CommentToken(extent)); }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> /// <remarks> /// /// See http://www.dmtf.org/sites/default/files/standards/documents/DSP0221_3.0.0a.pdf /// 5.2 - Whitespace /// /// Whitespace in a MOF file is any combination of the following characters: /// /// Space (U+0020), /// Horizontal Tab (U+0009), /// Carriage Return (U+000D) and /// Line Feed (U+000A). /// /// </remarks> internal static WhitespaceToken Read(ILexerStream stream) { var extent = new SourceExtent(stream); var sourceChars = new List<char>(); // read the first whitespace character sourceChars.Add(stream.ReadWhitespace()); // read the remaining whitespace while (!stream.Eof && char.IsWhiteSpace(stream.Peek())) { sourceChars.Add(stream.Read()); } // return the result extent = extent.WithText(sourceChars); return new WhitespaceToken(extent); }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> /// <remarks> /// /// See http://www.dmtf.org/sites/default/files/standards/documents/DSP0221_3.0.0a.pdf /// /// 5.2 - Whitespace /// /// Whitespace in a MOF file is any combination of the following characters: /// /// Space (U+0020), /// Horizontal Tab (U+0009), /// Carriage Return (U+000D) and /// Line Feed (U+000A). /// /// The WS ABNF rule represents any one of these whitespace characters: /// /// WS = U+0020 / U+0009 / U+000D / U+000A /// /// </remarks> private static WhitespaceToken ReadWhitespaceToken(ILexerStream stream) { var sourceChars = new List <SourceChar>(); // read the first whitespace character sourceChars.Add(stream.ReadWhitespace()); // read the remaining whitespace while (!stream.Eof && StringValidator.IsWhitespace(stream.Peek().Value)) { sourceChars.Add(stream.Read()); } // return the result var extent = new SourceExtent(sourceChars); return(new WhitespaceToken(extent)); }
internal static MultilineCommentToken Read(ILexerStream stream) { var extent = new SourceExtent(stream); var sourceChars = new List<char>(); // read the opening sequence sourceChars.Add(stream.ReadChar('/')); sourceChars.Add(stream.ReadChar('*')); // read the comment text while (!stream.Eof) { var c = stream.Read(); sourceChars.Add(c); if (c == '*' && stream.PeekChar('/')) break; } // read the closing sequence sourceChars.Add(stream.ReadChar('/')); // return the result extent = extent.WithText(sourceChars); return new MultilineCommentToken(extent); }