/// <summary> /// Contructor /// </summary> /// <param name="parameters"></param> public DscParameterParser(string parameters) { byte[] bytes = System.Text.Encoding.ASCII.GetBytes(parameters); ms = new MemoryStream(bytes); stream = new StreamReader(ms); this.reader = new EpsStreamReader(stream); lexer = new LexerBase(); }
private LexerToken ScanHexadecimalString(EpsStreamReader reader) { Debug.Assert(reader.CurrentChar == Chars.Less); ClearToken(); char[] hex = new char[2]; ScanNextChar(reader); while (true) { MoveToNonWhiteSpace(reader); if (reader.CurrentChar == '>') { ScanNextChar(reader); break; } if (char.IsLetterOrDigit(reader.CurrentChar)) { hex[0] = char.ToUpper(reader.CurrentChar); var nextChar = reader.NextChar; if (nextChar != '>') { hex[1] = char.ToUpper(nextChar); } else { hex[1] = '0'; } int ch = int.Parse(new string(hex), NumberStyles.AllowHexSpecifier); Token.Append(Convert.ToChar(ch)); ScanNextChar(reader); ScanNextChar(reader); } } string chars = Token.ToString(); int count = chars.Length; if (count > 2 && chars[0] == (char)0xFE && chars[1] == (char)0xFF) { Debug.Assert(count % 2 == 0); Token.Length = 0; for (int idx = 2; idx < count; idx += 2) { Token.Append((char)(chars[idx] * 256 + chars[idx + 1])); } } return(Symbol = LexerToken.HexString); }
/// <summary> /// Constructor /// </summary> public Parser(EpsStreamReader reader) { // The reader is passed in here but you should know // the reader is used at other places as well. The parser // has by design no exclusive access to it. That means // the state of the reader might change between calls to // the parser and to the lexer. this.reader = reader; lexer = new Lexer(); }
/// <summary> /// Scans an operator. /// </summary> private LexerToken ScanOperator(EpsStreamReader reader) { ClearToken(); char ch = reader.CurrentChar; while (IsOperatorFirstChar(ch) || char.IsDigit(ch) || ch == '-') { ch = AppendAndScanNextChar(reader); } return(Symbol = LexerToken.Operator); }
/// <summary> /// Scans a dsc comment token /// </summary> private LexerToken ScanDscComment(EpsStreamReader reader) { Debug.Assert(reader.CurrentChar == Chars.Percent); ClearToken(); char ch; do { ch = AppendAndScanNextChar(reader); }while (!IsWhiteSpace(ch) && ch != Chars.EOF); return(Symbol = LexerToken.DscComment); }
/// <summary> /// Scans a name. /// </summary> private LexerToken ScanName(EpsStreamReader reader) { Debug.Assert(reader.CurrentChar == Chars.Slash); ScanNextChar(reader); ClearToken(); char ch; do { ch = AppendAndScanNextChar(reader); }while (!IsWhiteSpace(ch) && !IsDelimiter(ch)); return(Symbol = LexerToken.Name); }
/// <summary> /// Continues scanning an integer or real number when the first char is already read /// </summary> /// <param name="reader"></param> protected LexerToken ScanNumberContinue(EpsStreamReader reader) { ClearToken(); var ch = MoveToNonWhiteSpace(reader); while (char.IsDigit(ch) || ch == '+' || ch == '-' || ch == 'e' || ch == 'E' || ch == '.' || ch == '#') { ch = AppendAndScanNextChar(reader); } var match = radixRegex.Match(StringToken); if (match.Success) { var radix = int.Parse(match.Groups[1].Value); IntegerToken = Convert.ToInt32(match.Groups[2].Value, radix); return(LexerToken.Integer); } match = integerRegex.Match(StringToken); if (match.Success) { var dbl = double.Parse(StringToken); if (int.MinValue <= dbl && dbl <= int.MaxValue) { IntegerToken = int.Parse(StringToken); return(LexerToken.Integer); } RealToken = dbl; return(LexerToken.Real); } match = doubleRegex.Match(StringToken); if (match.Success) { RealToken = double.Parse(StringToken, CultureInfo.InvariantCulture); return(LexerToken.Real); } return(LexerToken.Name); }
/// <summary> /// MoveToNonWhiteSpace /// </summary> protected char MoveToNonWhiteSpace(EpsStreamReader reader) { var currChar = reader.CurrentChar; while (currChar != Chars.EOF) { if (!whiteSpaceChars.Contains(currChar)) { return(currChar); } currChar = ScanNextChar(reader); } return(currChar); }
/// <summary> /// Scan ASCII base85 string /// </summary> /// <param name="reader"></param> private LexerToken ScanAsciiBase85String(EpsStreamReader reader) { ClearToken(); ScanNextChar(reader); ScanNextChar(reader); char ch = reader.CurrentChar; while (ch != '~' && ch != Chars.EOF) { ch = AppendAndScanNextChar(reader); } ScanNextChar(reader); ScanNextChar(reader); return(Symbol = LexerToken.AsciiBase85String); }
/// <summary> /// Scans an integer or real number. /// </summary> public LexerToken ScanNumber(EpsStreamReader reader) { ScanNextChar(reader); return(ScanNumberContinue(reader)); }
/// <summary> /// Appends current character to the token and reads next one. /// </summary> protected char AppendAndScanNextChar(EpsStreamReader reader) { Token.Append(reader.CurrentChar); return(ScanNextChar(reader)); }
/// <summary> /// Move current position one character further in content stream. /// </summary> protected char ScanNextChar(EpsStreamReader reader) { var currChar = reader.Read(); return(currChar); }
/// <summary> /// Reads the next token and returns its type. /// </summary> public LexerToken ScanNextToken(EpsStreamReader reader) { while (true) { ClearToken(); char ch = MoveToNonWhiteSpace(reader); switch (ch) { case Chars.EOF: { return(Symbol = LexerToken.Eof); } case '%': { if (reader.IsFirstCharOfLine) { return(Symbol = ScanDscComment(reader)); } ScanComment(reader); continue; } case '/': { if (reader.NextChar == '/') { ScanNextChar(reader); ScanNextChar(reader); ScanOperator(reader); return(Symbol = LexerToken.ImmediateOperator); } return(Symbol = ScanName(reader)); } case '[': { ScanNextChar(reader); return(Symbol = LexerToken.BeginArray); } case ']': { ScanNextChar(reader); return(Symbol = LexerToken.EndArray); } case '{': { ScanNextChar(reader); return(Symbol = LexerToken.BeginProcedure); } case '}': { ScanNextChar(reader); return(Symbol = LexerToken.EndProcedure); } case '(': { return(Symbol = ScanLiteralString(reader)); } case '<': { if (reader.NextChar == '<') { ScanNextChar(reader); ScanNextChar(reader); return(Symbol = LexerToken.BeginDictionary); } if (reader.NextChar == '~') { return(Symbol = ScanAsciiBase85String(reader)); } return(Symbol = ScanHexadecimalString(reader)); } case '>': { if (reader.NextChar == '>') { ScanNextChar(reader); ScanNextChar(reader); return(Symbol = LexerToken.EndDictionary); } throw new Exception($"Unexpected Character {ch}"); } } if (char.IsDigit(ch) || ch == '+' || ch == '-' || ch == '.') { return(Symbol = ScanNumberContinue(reader)); } if (IsOperatorFirstChar(ch)) { return(Symbol = ScanOperator(reader)); } throw new Exception($"Unexpected Character {ch}"); } }
private LexerToken ScanLiteralString(EpsStreamReader reader) { Debug.Assert(reader.CurrentChar == Chars.ParenLeft); ClearToken(); int parenLevel = 0; char ch = ScanNextChar(reader); while (true) { SkipChar: switch (ch) { case '(': parenLevel++; break; case ')': if (parenLevel == 0) { ScanNextChar(reader); return(Symbol = LexerToken.String); } parenLevel--; break; case '\\': { ch = ScanNextChar(reader); switch (ch) { case 'n': ch = Chars.LF; break; case 'r': ch = Chars.CR; break; case 't': ch = Chars.HT; break; case 'b': ch = Chars.BS; break; case 'f': ch = Chars.FF; break; case '(': ch = Chars.ParenLeft; break; case ')': ch = Chars.ParenRight; break; case '\\': ch = Chars.BackSlash; break; case Chars.LF: ch = ScanNextChar(reader); goto SkipChar; default: if (char.IsDigit(ch)) { // Octal character code. int n = ch - '0'; if (char.IsDigit(reader.NextChar)) { n = n * 8 + ScanNextChar(reader) - '0'; if (char.IsDigit(reader.NextChar)) { n = n * 8 + ScanNextChar(reader) - '0'; } } ch = (char)n; } break; } break; } default: // Every other char is appended to the token. break; } Token.Append(ch); ch = ScanNextChar(reader); } }