/
EvilBeaver
/
OneScript
Обзор
Документация
Войти
/
EvilBeaver
/
OneScript
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
v2.0.0
src/OneScript.Language/LexicalAnalysis/LexerBuilder.cs
95 строк
3 KB
EvilBeaver
Существенно ускорена компиляция большого числа модулей
19 июн 2025, 16:36
19 июн 2025, 16:36
6b3bb3d
Код
Авторство
О чём код?
/*---------------------------------------------------------- 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 System.Linq.Expressions; using System.Threading; namespace OneScript.Language.LexicalAnalysis { public class LexerBuilder { private List<LexerDetectorBuilder> _detectors = new List<LexerDetectorBuilder>(); private static Expression nullState = Expression.Constant(default, typeof(LexerState)); private readonly Lazy<LexerStateSelector> _selectorFunction; public LexerBuilder() { _selectorFunction = new Lazy<LexerStateSelector>(MakeSelectorFunction, LazyThreadSafetyMode.PublicationOnly); } public LexerDetectorBuilder Detect(Expression<Func<char, SourceCodeIterator, bool>> detectExpression) { var detector = new LexerDetectorBuilder(detectExpression); _detectors.Add(detector); return detector; } public ILexer Build() { return new ExpressionBasedLexer(_selectorFunction.Value); } private LexerStateSelector MakeSelectorFunction() { Expression expr; var charParam = Expression.Parameter(typeof(char), "cs"); var iteratorParam = Expression.Parameter(typeof(SourceCodeIterator), "i"); using (var iterator = _detectors.GetEnumerator()) { var map = new Dictionary<Type, ParameterExpression>() { {typeof(char), charParam}, {typeof(SourceCodeIterator), iteratorParam} }; var remapper = new ParameterRemapper(map); expr = BuildNode(iterator, remapper); } var lambda = Expression.Lambda<LexerStateSelector>(expr, iteratorParam, charParam); var selectorFunction = lambda.Compile(); return selectorFunction; } private Expression BuildNode(IEnumerator<LexerDetectorBuilder> iterator, ParameterRemapper parameterRemapper) { if (iterator.MoveNext()) { var test = parameterRemapper.Visit(iterator.Current.DetectExpression.Body); var truePart = Expression.Convert(iterator.Current.HandlerExpression, typeof(LexerState)); var falsePart = BuildNode(iterator, parameterRemapper); return Expression.Condition(test, truePart, falsePart); } return nullState; } private class ParameterRemapper : ExpressionVisitor { private readonly Dictionary<Type, ParameterExpression> _map; public ParameterRemapper(Dictionary<Type, ParameterExpression> map) { _map = map; } public override Expression Visit(Expression node) { if (node?.NodeType == ExpressionType.Parameter) { return _map[node.Type]; } return base.Visit(node); } } } }