/
EvilBeaver
/
OneScript
Обзор
Документация
Войти
/
EvilBeaver
/
OneScript
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
src/OneScript.Language/LexicalAnalysis/SourceCodeIterator.cs
243 строки
6 KB
Mr-Rm
сокращено получение CurrentColumn
21 дек 2025, 23:12
21 дек 2025, 23:12
a7c5fad
Код
Авторство
О чём код?
/*---------------------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; using System.Collections.Generic; using OneScript.Sources; namespace OneScript.Language.LexicalAnalysis { public class SourceCodeIterator : ISourceCodeIndexer { private string _code; private char _currentSymbol; private int _lineCounter; private int _index; private int _startPosition; private int _codeLength; private List<int> _lineBounds; private bool _onNewLine; public bool OnNewLine { get; private set; } public bool StayOnSameLine { get; set; } private const int OUT_OF_TEXT = -1; public SourceCodeIterator(SourceCode code) { Source = code; InitOnString(code.GetSourceCode()); } internal SourceCodeIterator() { InitOnString(String.Empty); } public SourceCode Source { get; } private void InitOnString(string code) { _code = code; _codeLength = code.Length; int cap = code.Length < 512 ? 32 : 512; _lineBounds = new List<int>(cap); _index = OUT_OF_TEXT; _startPosition = OUT_OF_TEXT; _currentSymbol = '\0'; _onNewLine = true; OnNewLine = true; if (!String.IsNullOrEmpty(code)) { _lineCounter = 1; _lineBounds.Add(0); } else { _lineCounter = OUT_OF_TEXT; } } public int Position => _index; public int CurrentLine => _lineCounter; public int CurrentColumn => _startPosition == OUT_OF_TEXT ? OUT_OF_TEXT : _index - _lineBounds[^1] + 1; // CurrentLine's start is last in _lineBounds public char CurrentSymbol => _currentSymbol; public bool MoveNext() { _index++; if (_index < _codeLength) { _currentSymbol = _code[_index]; if (_currentSymbol == '\n') { _lineCounter++; _lineBounds.Add(_index + 1); } return true; } else { _currentSymbol = '\0'; return false; } } public char PeekNext() { char result = '\0'; if (_index + 1 < _codeLength) { result = _code[_index + 1]; } return result; } public bool MoveToContent() { if (SkipSpaces()) { _startPosition = _index; OnNewLine = _onNewLine; return true; } else { return false; } } public bool SkipSpaces() { if (_index == OUT_OF_TEXT && !MoveNext()) { return false; } while (Char.IsWhiteSpace(_currentSymbol)) { if (_currentSymbol == '\n') { if (StayOnSameLine) return false; _onNewLine = true; } if (!MoveNext()) { return false; } } if (_index >= _codeLength) { return false; } return true; } public char ReadNextChar() { while (Char.IsWhiteSpace(_currentSymbol)) { if (_currentSymbol == '\n') { _onNewLine = true; } if (!MoveNext()) { break; } } return _currentSymbol; } public string ReadToLineEnd() { while (_currentSymbol != '\n' && MoveNext()) { } var res = GetContents(); _onNewLine = true; OnNewLine = true; return res.Trim(); } public string GetCodeLine(int lineNumber) { int start = GetLineBound(lineNumber); if (start >= _code.Length) return String.Empty; int end = _code.IndexOf('\n', start); if (end >= 0) { return _code.Substring(start, end - start); } else { return _code.Substring(start); } } private int GetLineBound(int lineNumber) { return _lineBounds[lineNumber - 1]; } public ReadOnlyMemory<char> GetContentSpan() { int len; if (_startPosition == _index && _startPosition < _codeLength) { len = 1; } else if (_startPosition < _index) { len = _index - _startPosition; } else { return ReadOnlyMemory<char>.Empty; } var contents = _code.AsMemory(_startPosition, len); _startPosition = _index + 1; OnNewLine = _onNewLine; _onNewLine = false; return contents; } public string GetContents() { return GetContentSpan().ToString(); } } }