Сообщение Re[4]: [Nitra] Парсинг языков базирующихся на отсупах от 02.10.2014 11:59
Изменено 02.10.2014 12:01 STDray
VD>Часть из этих языков уже довольно старые. Ну, и не сложно найти еще большую тучу скобочных языков.
Согласен, не сложно. С другой стороны, я просматривал различные генераторы парсеров и практически нигде проблема разбора языков с синтаксисом на отступах из коробки не решена. Хотя устойчивый интерес есть.
VD>Как я уже говорил, можно относительно не сложно, и полностью автоматически сделать аналог немерлововго решения, когда некий препроцессор расставляет вымышлинные скобки на базе некоторого алгоритма, а далее парсинг происходит по обычным принципам.
Я делал что-то вроде
и использование
То есть была какая-то идея, чтобы
— использовать символы из приватного диапазона юникода для расстановки виртуальных скобок.
— использовать некий BadDedent для разметки кривых отступов, чтобы парсер мог сгенерировать ошибку вида "Dedent expected", восстановиться и разбирать дальше.
— использовать this(originalText : string, text : string, fileIndex : int, fileName : string, lineIndexes : array[int], textOffset : int); для корректного позиционирования ошибок после расстановки виртуальных скобок.
Но потом я от этой идеи отказался, потому что непонятно, как дружить все это дело со студийной интеграцией. Да и то, что надо в двух местах указывать символы для виртуальных скобок мне не понравилось. Так что я считаю, пусть какое-то простенькое решение, но должно быть в коробке.
Согласен, не сложно. С другой стороны, я просматривал различные генераторы парсеров и практически нигде проблема разбора языков с синтаксисом на отступах из коробки не решена. Хотя устойчивый интерес есть.
VD>Как я уже говорил, можно относительно не сложно, и полностью автоматически сделать аналог немерлововго решения, когда некий препроцессор расставляет вымышлинные скобки на базе некоторого алгоритма, а далее парсинг происходит по обычным принципам.
Я делал что-то вроде
#pragma indent
using Nemerle
using Nemerle.Imperative
using System
using System.IO
using System.Text
using SCG = System.Collections.Generic
namespace SampleParserApplication2
[Record] class IndentPreprocessor
public Indent : char
public Dedent : char
public BadDedent : char
public Preprocess(input : string) : string
input |> StringReader |> Preprocess
public Preprocess(reader : TextReader) : string
def builder = StringBuilder()
def indentSizes = SCG.Stack()
mutable prevIndentSize : int? = null
for(mutable line = reader.ReadLine(); line != null; line = reader.ReadLine())
def currentIndentSize = GetIndentSize(line)
when(currentIndentSize == line.Length && line.Length >= 0)
continue;
when(!prevIndentSize.HasValue)
prevIndentSize = currentIndentSize
if(prevIndentSize.Value < currentIndentSize)
indentSizes.Push(prevIndentSize.Value)
_ = builder.Append(Indent)
else when(prevIndentSize.Value > currentIndentSize)
_ = builder.Append <|
if(indentSizes.Count > 0)
match(indentSizes.Peek())
| x when x == currentIndentSize => _ = indentSizes.Pop(); Dedent
| x when x > currentIndentSize => _ = indentSizes.Pop(); BadDedent
| _ => BadDedent
else BadDedent
prevIndentSize = currentIndentSize
_ = builder.Append(Environment.NewLine).Append(line)
foreach(currentIndentSize in indentSizes)
_ = builder.Append <|
if(currentIndentSize < prevIndentSize.Value) Dedent
else BadDedent
builder.ToString();
static GetIndentSize(line : string) : int
mutable size = 0
while(size < line.Length && line[size] == ' ')
size++
size
и использование
def preprocessor = IndentPreprocessor('\uE001', '\uE002', '\uE003');
def result = preprocessor.Preprocess(str);
def source = SourceSnapshot(result);
token INDENT = '\uE001';
token BADDENT = '\uE003';
token DEDENT = BADDENT? '\uE002';
То есть была какая-то идея, чтобы
— использовать символы из приватного диапазона юникода для расстановки виртуальных скобок.
— использовать некий BadDedent для разметки кривых отступов, чтобы парсер мог сгенерировать ошибку вида "Dedent expected", восстановиться и разбирать дальше.
— использовать this(originalText : string, text : string, fileIndex : int, fileName : string, lineIndexes : array[int], textOffset : int); для корректного позиционирования ошибок после расстановки виртуальных скобок.
Но потом я от этой идеи отказался, потому что непонятно, как дружить все это дело со студийной интеграцией. Да и то, что надо в двух местах указывать символы для виртуальных скобок мне не понравилось. Так что я считаю, пусть какое-то простенькое решение, но должно быть в коробке.
Re[4]: [Nitra] Парсинг языков базирующихся на отсупах
VD>Часть из этих языков уже довольно старые. Ну, и не сложно найти еще большую тучу скобочных языков.
Согласен, не сложно. С другой стороны, я просматривал различные генераторы парсеров и практически нигде проблема разбора языков с синтаксисом на отступах из коробки не решена. Хотя устойчивый интерес есть.
VD>Как я уже говорил, можно относительно не сложно, и полностью автоматически сделать аналог немерлововго решения, когда некий препроцессор расставляет вымышлинные скобки на базе некоторого алгоритма, а далее парсинг происходит по обычным принципам.
Я делал что-то вроде
и использование
То есть была какая-то идея, чтобы
— использовать символы из приватного диапазона юникода для расстановки виртуальных скобок.
— использовать некий BadDedent для разметки кривых отступов, чтобы парсер мог сгенерировать ошибку вида "Dedent expected", восстановиться и разбирать дальше.
— использовать конструктор SourceSnapshot this(originalText : string, text : string, fileIndex : int, fileName : string, lineIndexes : array[int], textOffset : int); для корректного позиционирования ошибок после расстановки виртуальных скобок.
Но потом я от этой идеи отказался, потому что непонятно, как дружить все это дело со студийной интеграцией. Да и то, что надо в двух местах указывать символы для виртуальных скобок мне не понравилось. Так что я считаю, пусть какое-то простенькое решение, но должно быть в коробке.
Согласен, не сложно. С другой стороны, я просматривал различные генераторы парсеров и практически нигде проблема разбора языков с синтаксисом на отступах из коробки не решена. Хотя устойчивый интерес есть.
VD>Как я уже говорил, можно относительно не сложно, и полностью автоматически сделать аналог немерлововго решения, когда некий препроцессор расставляет вымышлинные скобки на базе некоторого алгоритма, а далее парсинг происходит по обычным принципам.
Я делал что-то вроде
#pragma indent
using Nemerle
using Nemerle.Imperative
using System
using System.IO
using System.Text
using SCG = System.Collections.Generic
namespace SampleParserApplication2
[Record] class IndentPreprocessor
public Indent : char
public Dedent : char
public BadDedent : char
public Preprocess(input : string) : string
input |> StringReader |> Preprocess
public Preprocess(reader : TextReader) : string
def builder = StringBuilder()
def indentSizes = SCG.Stack()
mutable prevIndentSize : int? = null
for(mutable line = reader.ReadLine(); line != null; line = reader.ReadLine())
def currentIndentSize = GetIndentSize(line)
when(currentIndentSize == line.Length && line.Length >= 0)
continue;
when(!prevIndentSize.HasValue)
prevIndentSize = currentIndentSize
if(prevIndentSize.Value < currentIndentSize)
indentSizes.Push(prevIndentSize.Value)
_ = builder.Append(Indent)
else when(prevIndentSize.Value > currentIndentSize)
_ = builder.Append <|
if(indentSizes.Count > 0)
match(indentSizes.Peek())
| x when x == currentIndentSize => _ = indentSizes.Pop(); Dedent
| x when x > currentIndentSize => _ = indentSizes.Pop(); BadDedent
| _ => BadDedent
else BadDedent
prevIndentSize = currentIndentSize
_ = builder.Append(Environment.NewLine).Append(line)
foreach(currentIndentSize in indentSizes)
_ = builder.Append <|
if(currentIndentSize < prevIndentSize.Value) Dedent
else BadDedent
builder.ToString();
static GetIndentSize(line : string) : int
mutable size = 0
while(size < line.Length && line[size] == ' ')
size++
size
и использование
def preprocessor = IndentPreprocessor('\uE001', '\uE002', '\uE003');
def result = preprocessor.Preprocess(str);
def source = SourceSnapshot(result);
token INDENT = '\uE001';
token BADDENT = '\uE003';
token DEDENT = BADDENT? '\uE002';
То есть была какая-то идея, чтобы
— использовать символы из приватного диапазона юникода для расстановки виртуальных скобок.
— использовать некий BadDedent для разметки кривых отступов, чтобы парсер мог сгенерировать ошибку вида "Dedent expected", восстановиться и разбирать дальше.
— использовать конструктор SourceSnapshot this(originalText : string, text : string, fileIndex : int, fileName : string, lineIndexes : array[int], textOffset : int); для корректного позиционирования ошибок после расстановки виртуальных скобок.
Но потом я от этой идеи отказался, потому что непонятно, как дружить все это дело со студийной интеграцией. Да и то, что надо в двух местах указывать символы для виртуальных скобок мне не понравилось. Так что я считаю, пусть какое-то простенькое решение, но должно быть в коробке.