lexer.cs

来自「全功能c#编译器」· CS 代码 · 共 767 行 · 第 1/2 页

CS
767
字号
				}
			}
			
			if (nextChar == -1) {
				errors.Error(y, x, String.Format("End of file reached inside verbatim string literal"));
			}
			
			return new Token(Tokens.Literal, x, y, originalValue.ToString(), sb.ToString());
		}
		
		char[] escapeSequenceBuffer = new char[12];
		string ReadEscapeSequence(out char ch)
		{
			int nextChar = reader.Read();
			if (nextChar == -1) {
				errors.Error(line, col, String.Format("End of file reached inside escape sequence"));
				ch = '\0';
				return String.Empty;
			}
			char c = (char)nextChar;
			int curPos              = 1;
			escapeSequenceBuffer[0] = c;
			++col;
			switch (c)  {
				case '\'':
					ch = '\'';
					break;
				case '\"':
					ch = '\"';
					break;
				case '\\':
					ch = '\\';
					break;
				case '0':
					ch = '\0';
					break;
				case 'a':
					ch = '\a';
					break;
				case 'b':
					ch = '\b';
					break;
				case 'f':
					ch = '\f';
					break;
				case 'n':
					ch = '\n';
					break;
				case 'r':
					ch = '\r';
					break;
				case 't':
					ch = '\t';
					break;
				case 'v':
					ch = '\v';
					break;
				case 'u':
				case 'x':
					c = (char)reader.Read();
					int number = GetHexNumber(c);
					
					if (number < 0) {
						errors.Error(line, col, String.Format("Invalid char in literal : {0}", c));
					}
					escapeSequenceBuffer[curPos++] = c;
					for (int i = 0; i < 3; ++i) {
						if (IsHex((char)reader.Peek())) {
							c = (char)reader.Read();
							
							int idx = GetHexNumber(c);
							escapeSequenceBuffer[curPos++] = c;
							number = idx * (16 * (i + 1)) + number;
						} else {
							break;
						}
					}
					ch = (char)number;
					break;
				default:
					errors.Error(line, col, String.Format("Unexpected escape sequence : {0}", c));
					ch = '\0';
					break;
			}
			return new String(escapeSequenceBuffer, 0, curPos);
		}
		
		Token ReadChar()
		{
			int x = col;
			int y = line;
			int nextChar = reader.Read();
			if (nextChar == -1) {
				errors.Error(y, x, String.Format("End of file reached inside character literal"));
				return null;
			}
			char ch = (char)nextChar;
			++col;
			string escapeSequence = String.Empty;
			if (ch == '\\') {
				escapeSequence = ReadEscapeSequence(out ch);
			}
			
			if ((char)reader.Read() != '\'') {
				errors.Error(y, x, String.Format("Char not terminated"));
			}
			return new Token(Tokens.Literal, x, y, "'" + ch + escapeSequence + "'", ch);
		}
		
		Token ReadOperator(char ch)
		{
			int x = col;
			int y = line;
			++col;
			switch (ch) {
				case '+':
					switch (reader.Peek()) {
						case '+':
							reader.Read();
							++col;
							return new Token(Tokens.Increment, x, y);
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.PlusAssign, x, y);
					}
					return new Token(Tokens.Plus, x, y);
				case '-':
					switch (reader.Peek()) {
						case '-':
							reader.Read();
							++col;
							return new Token(Tokens.Decrement, x, y);
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.MinusAssign, x, y);
						case '>':
							reader.Read();
							++col;
							return new Token(Tokens.Pointer, x, y);
					}
					return new Token(Tokens.Minus, x, y);
				case '*':
					switch (reader.Peek()) {
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.TimesAssign, x, y);
						default:
							break;
					}
					return new Token(Tokens.Times, x, y);
				case '/':
					switch (reader.Peek()) {
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.DivAssign, x, y);
					}
					return new Token(Tokens.Div, x, y);
				case '%':
					switch (reader.Peek()) {
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.ModAssign, x, y);
					}
					return new Token(Tokens.Mod, x, y);
				case '&':
					switch (reader.Peek()) {
						case '&':
							reader.Read();
							++col;
							return new Token(Tokens.LogicalAnd, x, y);
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.BitwiseAndAssign, x, y);
					}
					return new Token(Tokens.BitwiseAnd, x, y);
				case '|':
					switch (reader.Peek()) {
						case '|':
							reader.Read();
							++col;
							return new Token(Tokens.LogicalOr, x, y);
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.BitwiseOrAssign, x, y);
					}
					return new Token(Tokens.BitwiseOr, x, y);
				case '^':
					switch (reader.Peek()) {
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.XorAssign, x, y);
						default:
							break;
					}
					return new Token(Tokens.Xor, x, y);
				case '!':
					switch (reader.Peek()) {
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.NotEqual, x, y);
					}
					return new Token(Tokens.Not, x, y);
				case '~':
					return new Token(Tokens.BitwiseComplement, x, y);
				case '=':
					switch (reader.Peek()) {
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.Equal, x, y);
					}
					return new Token(Tokens.Assign, x, y);
				case '<':
					switch (reader.Peek()) {
						case '<':
							reader.Read();
							if (reader.Peek() != -1) {
								switch ((char)reader.Peek()) {
									case '=':
										reader.Read();
										col += 2;
										return new Token(Tokens.ShiftLeftAssign, x, y);
									default:
										++col;
										break;
								}
							}
							return new Token(Tokens.ShiftLeft, x, y);
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.LessEqual, x, y);
					}
					return new Token(Tokens.LessThan, x, y);
				case '>':
					switch (reader.Peek()) {
						case '>':
							reader.Read();
							if (reader.Peek() != -1) {
								switch ((char)reader.Peek()) {
									case '=':
										reader.Read();
										col += 2;
										return new Token(Tokens.ShiftRightAssign, x, y);
									default:
										++col;
										break;
								}
							}
							return new Token(Tokens.ShiftRight, x, y);
						case '=':
							reader.Read();
							++col;
							return new Token(Tokens.GreaterEqual, x, y);
					}
					return new Token(Tokens.GreaterThan, x, y);
				case '?':
					return new Token(Tokens.Question, x, y);
				case ';':
					return new Token(Tokens.Semicolon, x, y);
				case ':':
					return new Token(Tokens.Colon, x, y);
				case ',':
					return new Token(Tokens.Comma, x, y);
				case '.':
					if (Char.IsDigit((char)reader.Peek())) {
						 col -= 2;
						 return ReadDigit('.', col + 1);
					}
					return new Token(Tokens.Dot, x, y);
				case ')':
					return new Token(Tokens.CloseParenthesis, x, y);
				case '(':
					return new Token(Tokens.OpenParenthesis, x, y);
				case ']':
					return new Token(Tokens.CloseSquareBracket, x, y);
				case '[':
					return new Token(Tokens.OpenSquareBracket, x, y);
				case '}':
					return new Token(Tokens.CloseCurlyBrace, x, y);
				case '{':
					return new Token(Tokens.OpenCurlyBrace, x, y);
				default:
					--col;
					return null;
			}
		}
		
		void ReadComment()
		{
			++col;
			switch (reader.Read()) {
				case '*':
					ReadMultiLineComment();
					break;
				case '/':
					if (reader.Peek() == '/') {
						reader.Read();
						ReadSingleLineComment(CommentType.Documentation);
					} else {
						ReadSingleLineComment(CommentType.SingleLine);
					}
					break;
				default:
					errors.Error(line, col, String.Format("Error while reading comment"));
					break;
			}
		}
		
		string ReadCommentToEOL()
		{
			sb.Length = 0;
			StringBuilder curWord = specialCommentHash != null ? new StringBuilder() : null;
			
			int nextChar;
			while ((nextChar = reader.Read()) != -1) {
				char ch = (char)nextChar;
				++col;
				
				if (HandleLineEnd(ch)) {
					return sb.ToString();;
				}
				
				if (specialCommentHash != null) {
					if (Char.IsLetter(ch)) {
						curWord.Append(ch);
					} else {
						string tag = curWord.ToString();
						curWord = new StringBuilder();
						if (specialCommentHash[tag] != null) {
							Point p = new Point(col ,line);
							string comment = ReadToEOL();
							tagComments.Add(new TagComment(tag, comment, p));
							sb.Append(tag);
							sb.Append(comment);
							return sb.ToString();
						}
					}
				}
				sb.Append(ch);
			}
			return sb.ToString();
		}
		
		void ReadSingleLineComment(CommentType commentType)
		{
			ReadCommentToEOL();
		}
		
		void ReadMultiLineComment()
		{
			int nextChar;
			while ((nextChar = reader.Read()) != -1) {
				char ch = (char)nextChar;
				++col;
				
				if (HandleLineEnd(ch)) {
					continue;
				}
				
				// End of multiline comment reached ?
				if (ch == '*' && reader.Peek() == '/') {
					reader.Read();
					++col;
					return;
				}
			}
			
			// Reached EOF before end of multiline comment.
			errors.Error(line, col, String.Format("Reached EOF before the end of a multiline comment"));
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?