Re[7]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 15:44
Оценка:
Здравствуйте, IT, Вы писали:

IT>Взять, например, Sybase T-SQL. Все ключевые слова и, если не ошибаюсь, именя некоторых системных функций регистронезависимые. Имена таблиц, полей, вью, пользовательский функций регистрозависимые.


Идентификаторы (имена таблиц) они вообще не задаются в грамматике явно. Идентификатор — это строка разбираемая по определенному правилу. Ну, например такому: ['A'..'Z', 'a'..'z', '_', '0'..'9']. А то как там у тебя эти идентификаторы будут обрабатываться — это уже отдельный вопрос. Таким образом грамматика то у Sybase T-SQL регистронезависимая, а вот интерпретация идентификторов — нет. Но это уже не имеет отношения к грамматике. Это семантика.

Ну, так никто не запрещает тебе получать идентификаторы в исходном виде (в виде заданном пользователем) и уже потом интерпретировать их как тебе угодно.

Что касается имен функций, то уверен, что встроенные функции скорее всего тоже регистронезависимые, так как это был бы уж больно явный косяк. Ну, или вызов функции в Sybase T-SQL описывается правилом: identifier "("s param* ")"s, т.е. имена функций не предопределены, а выбираются из какого-то списка (например, системной таблицы).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 16:50
Оценка:
Здравствуйте, alvas, Вы писали:

A>Я сделал для функции с 0 параметров и для функции с 1 параметром


A>
A>  func0                 : void -> float = ("pi" / "rnd")s;
A>  funcExpr0             : float = func0;
A>  func1                 : float -> float = ("round")s;
A>  funcExpr1             : float = func1 "("s expr ")"s;
A>


Выдает такие ворнинги

Warning 5 N10003: method CalcParser.func0(name : Nemerle.Peg.NToken) : void -> float is not externally visible and has never been referenced D:\Work\Nemerle\NConsole\CalcTest\CalcParser2.n 95 4 CalcTest
Warning 6 N10003: method CalcParser.funcExpr0(func0 : void -> float) : float is not externally visible and has never been referenced D:\Work\Nemerle\NConsole\CalcTest\CalcParser2.n 115 4 CalcTest
Warning 7 N10003: method CalcParser.func1(name : Nemerle.Peg.NToken) : float -> float is not externally visible and has never been referenced D:\Work\Nemerle\NConsole\CalcTest\CalcParser2.n 120 4 CalcTest
Warning 8 N10003: method CalcParser.funcExpr1(func1 : float -> float, _N_wildcard_2808 : Nemerle.Peg.NToken, firstArg : float, _N_wildcard_2809 : Nemerle.Peg.NToken) : float is not externally visible and has never been referenced D:\Work\Nemerle\NConsole\CalcTest\CalcParser2.n 135 4 CalcTest


Т.е. компилятор говорит что их использовать не собирается. Почему?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[4]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 17:16
Оценка:
Выкладываю весь код

using System;
using System.Globalization.CultureInfo;
using System.Linq;
using System.Console;
using SCG = System.Collections.Generic;

using Nemerle.Peg;//Options = EmitDebugSource, 

[PegGrammar(start, 
grammar
{
  any                   = ['\u0000'..'\uFFFF'];
  s : void              = ' '*;
  num                   : float = ['0'..'9']+ ((',' / '.') ['0'..'9']+)? s;
  parenthesesExpr       : float = "("s expr ")"s;
  func0                 : void -> float = ("pi" / "rnd")s;
  funcExpr0             : float = func0;
  func1                 : float -> float = ("round")s;
  funcExpr1             : float = func1 "("s expr ")"s;
  //func1str              : string -> float = ("len")s;
  //funcExpr1str          : float = func1str "("s expr ")"s;
  func                  : SCG.IEnumerable.[float] -> float = ("max" / "avg" / "sum")s;
  funcExpr              : float = func "("s expr (";"s expr)* ")"s;
  unaryExpr             : float = (("-" / "+")s)* (num / parenthesesExpr / funcExpr);
  multiplicationExpr    : float = unaryExpr ( ("*" / "/")s unaryExpr)*;
  additionExpr          : float = multiplicationExpr ( ("+" / "-")s multiplicationExpr)*;
  expr                  : float = additionExpr;
  start                 : float = s expr !any;
})]
public sealed class CalcParser
{
  private num(integerPart : NToken, floatPart : option[NToken * NToken]) : float
  {
    def number = match(floatPart)
    {
      | Some((_, floatPart)) =>
        GetText(integerPart)
        + InvariantCulture.NumberFormat.NumberDecimalSeparator
        + GetText(floatPart)
      | _ =>
        GetText(integerPart)
    };
    float.Parse(number, InvariantCulture)
  }

  private parenthesesExpr(_ : NToken, se : float, _ : NToken) : float
  {
    se
  }

  private func(name : NToken) : SCG.IEnumerable[float] -> float
  {
    def max(seq)
    {
      mutable acc = float.MinValue;
      foreach(x in seq)
        when(x > acc)
          acc = x;
      otherwise
        acc = float.NaN;
      acc
    }
    def avg(seq)
    {
      mutable acc = .0f;
      mutable count = 0;
      foreach(x in seq)
      {
        acc += x;
        count += 1;
      }
      if(count > 0)
        acc / count
      else
        float.NaN
    }
    def sum(seq)
    {
      mutable acc = .0f;
      foreach(x in seq)
        acc += x;
      otherwise
        acc = float.NaN;
      acc
    }
    match(GetText(name).ToLowerInvariant()) // из GetText приедет оригинальную строку
    {
      | "max" => max
      | "avg" => avg
      | "sum" => sum
      | _ => throw InvalidOperationException()
    }
  }

  private func0(name : NToken) : void -> float
  {
    def pi()
    {
        Math.PI :> float
    }
      
    def rnd()
    {
        Random().NextDouble() :> float
    }

    match(GetText(name).ToLowerInvariant()) // из GetText приедет оригинальную строку
    {
      | "pi" => pi
      | "rnd" => rnd
      | _ => throw InvalidOperationException()
    }
  }

  private funcExpr0(func0 : void -> float) : float
  {
    func0()
  }
  
  private func1(name : NToken) : float -> float
  {
    def round(x)
    {
      //Math.Round(x)
        11.1f;
    }
    
    match(GetText(name).ToLowerInvariant()) // из GetText приедет оригинальную строку
    {
      | "round" => round
      | _ => throw InvalidOperationException()
    }
  }

  private funcExpr1(func1 : float -> float, _ : NToken, firstArg : float, _ : NToken) : float
  {
    func1(firstArg)
  }
  
  private funcExpr(func : SCG.IEnumerable[float] -> float, _ : NToken, firstArg : float, tailArgs : SCG.List[NToken * float], _ : NToken) : float
  {
    func([firstArg].Concat(tailArgs.Select(t => t[1])))
  }

  private unaryExpr(unaryOps : SCG.List[NToken], value : float) : float
  {
    mutable acc = value;
    foreach(op in unaryOps)
    {
      match(GetText(op))
      {
        | "+" => ()
        | "-" => acc *= -1
        | _ => throw InvalidOperationException()
      }
    }
    acc
  }

  private multiplicationExpr(head : float, tail : SCG.List[NToken * float]) : float
  {
    mutable acc = head;
    foreach((op, value) in tail)
    {
      match(GetText(op))
      {
        | "*" => acc *= value
        | "/" => acc /= value
        | _ => throw InvalidOperationException()
      }
    }
    acc
  }

  private additionExpr(head : float, tail : SCG.List[NToken * float]) : float
  {
    mutable acc = head;
    foreach((op, value) in tail)
    {
      match(GetText(op))
      {
        | "+" => acc += value
        | "-" => acc -= value
        | _ => throw InvalidOperationException()
      }
    }
    acc
  }
}


module Program
{
  Main() : void
  {
    def parser = CalcParser();
    //while(true)
    {
      def input = "round(2)";// "AVG(-3,5; 2)";//"abs (-3,5 min 2)";//"10    +2 - 3- 4 *4 / 2/   2  + (2+6)/2  +(-1)"; //res =  8 
      SourceSnapshot(input).WithText(input.ToLowerInvariant()) |> parser.Parse |> WriteLine; // магия!
      _ = ReadLine();
    }
  }
}
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[5]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 19:45
Оценка: 3 (1)
Здравствуйте, alvas, Вы писали:

A>Выкладываю весь код


По порядку...

Привило funcExpr0 нигде не используется. Правило func0 используется только из него. Стало быть не странно, что компилятор выдает предупреждение. Оптимизатор грамматики выкидывает неиспользуемые правила, а обработчики для них становятся нигде не используемыми.

По уму надо выявлять неиспользуемые правила и давать об этом предупреждение. Но это может помешать при разработке грамматики.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:03
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, alvas, Вы писали:


A>>Выкладываю весь код


VD>По порядку...


VD>Привило funcExpr0 нигде не используется. Правило func0 используется только из него. Стало быть не странно, что компилятор выдает предупреждение. Оптимизатор грамматики выкидывает неиспользуемые правила, а обработчики для них становятся нигде не используемыми.


VD>По уму надо выявлять неиспользуемые правила и давать об этом предупреждение. Но это может помешать при разработке грамматики.


1. Заработало! Спасибо

2. В сейчас калькуляторе используется только один тип данных — float.
Можно ли смешивать несколько типов чтобы сделать такую функцию: len("nemerle") => 7?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[6]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:07
Оценка:
Здравствуйте, VladD2, Вы писали:

Для каких типов документов PegParser неприменим?
Например кривой html он потянет?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[5]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 20:10
Оценка:
Здравствуйте, alvas, Вы писали:

Сори отправил раньше времени... продолжим.

Пертурбации с void -> float я не понял на проч. Твой калькулятор вычисляет результат в формате float. Стало быть правила функций тоже должны возвращать float. Только их надо разбирать вместе с параметрами, а не по отдельности.

Большой вопрос нужно ли закладывать в грамматику имена функций или лучше оставить их просто идентификаторами, а уже поддерживаемые функции разбирать в обработчиках. При втором подходе нужно оставить правило:
funCall : float      = identifier args;
arg0    : list[expr] = "("s ")"s;
arg1    : list[expr] = "("s expr ")"s;
argMeny : list[expr] = "("s expr (";"s expr)+ ")"s;
args    : list[expr] = arg0 / arg1 / argMeny;

или так:
funCall : float      = identifier "("s args ")"s;
args    : list[expr] = (expr (";"s expr)+)?;

ну, а конкретные функции проверять паттерн-матчингом:
match (funName, args)
{
  | ("round", [arg]) => Math.Round(arg)
  | ("round", _)     => throw InvalidArgumentException("The 'round' function has one parameter.")
  | ("max", [_])
  | ("max", [])      => throw InvalidArgumentException("The 'max' function must have 2 or more arguments.")
  ...
}


В случае если имена функций зашиваются в грамматику, то нужно разбирать весь вызов, а не только имя функции. А весь список вариантов вызовов нужно перечислить в операторе приоритетного выбора в некотором правиле. Например в funcExpr.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:13
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, alvas, Вы писали:


VD>Сори отправил раньше времени... продолжим.


Понял. Буду смотреть в эту сторону. Делал просто по аналогии с


  func                  : SCG.IEnumerable.[float] -> float = ("max" / "avg" / "sum")s;
  funcExpr              : float = func "("s expr (";"s expr)* ")"s;
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[7]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 20:19
Оценка:
Здравствуйте, alvas, Вы писали:

A>1. Заработало! Спасибо


Там еще много чего править нужно.

A>2. В сейчас калькуляторе используется только один тип данных — float.

A>Можно ли смешивать несколько типов чтобы сделать такую функцию: len("nemerle") => 7?

Раз это калькулятор, он должен возвращать одно значение (не считая исключений).

Так что или возвращай в своих функциях всегда float (лучше double или даже decimal), или сначала преобразуй свой калькулятор к AST, а уже потом производи вычисления на АСТ.

Еще как вариант можно организовать динамическую типизацию . Это делается элементарно заводишь вариантный тип данных в котором перечисляешь доступные в твоем языке типы данных. Например:
variant CalcObject
{
  | Int    { value : int; }
  | Double { value : double; }
  | String { value : string; }
}

Ну, а там вычисляешь их динамически (проверяя соответствие типов).

Для статики придется описывать функции в грамматике и задавать им явно типы параметров и возвращаемого значения.

Ну, или строить АСТ, а потом производить процесс типизации (выявления и проверки типов). Но это уже почти компилятор получится.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 20:22
Оценка:
Здравствуйте, alvas, Вы писали:

A>Для каких типов документов PegParser неприменим?


Парсеры парсят языки, а не документы.

A>Например кривой html он потянет?


Да. Как и для любого компьютерного языка. Парсер XML-я можно наблюдать здесь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 20:25
Оценка:
Здравствуйте, alvas, Вы писали:


A>Понял. Буду смотреть в эту сторону. Делал просто по аналогии с


A>
A>  func                  : SCG.IEnumerable.[float] -> float = ("max" / "avg" / "sum")s;
A>  funcExpr              : float = func "("s expr (";"s expr)* ")"s;
A>


Это у кого-то был перебор ФП или очень веселое настроение. Короче, овердизайн.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:26
Оценка:
Здравствуйте, VladD2, Вы писали:

Этот код для функции, которая принимает 1..n параметров. Я правильно понял?

func                  : SCG.IEnumerable.[float] -> float = ("max" / "avg" / "sum")s;
funcExpr              : float = func "("s expr (";"s expr)* ")"s;


void -> float для функций без параметров — pi, random.
float -> float для функций с одним параметром

1. Как объявить для функции с 1 параметром + 1 опциональным параметром?
round(1[;2]) — пример понятен?
Я думаю что нужно просто поставить какой-то другой символ вместо снежинки (*) в коде выше. Может плюс (+)?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[8]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:32
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, alvas, Вы писали:


A>>Для каких типов документов PegParser неприменим?


VD>Парсеры парсят языки, а не документы.


Просто слово не смог подобрать

A>>Например кривой html он потянет?


VD>Да. Как и для любого компьютерного языка. Парсер XML-я можно наблюдать здесь.


Ну xml как правило правильный. А такой html можно парсить?

<ul>
<li> 1
<li> 2 </li>
<li/> 3
</ul>
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[7]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 20:35
Оценка:
Здравствуйте, alvas, Вы писали:

A>Этот код для функции, которая принимает 1..n параметров. Я правильно понял?

A>
A>func                  : SCG.IEnumerable.[float] -> float = ("max" / "avg" / "sum")s;
A>funcExpr              : float = func "("s expr (";"s expr)* ")"s;
A>


Да. Вот только max для одного параметра — это какой-то "зденъ".

A>void -> float для функций без параметров — pi, random.

A>float -> float для функций с одним параметром

Видимо. Только это опят же изврат, на мой взгляд.
Решение должно быть максимально простым и понятным. Упражнения с функциями должны что-то давать. Упрощать код, например.

A>1. Как объявить для функции с 1 параметром + 1 опциональным параметром?

A>round(1[;2]) — пример понятен?

Если зашивать это в грамматику, то путем описания двух правил и перечисления их в операторе приоритетного выбора.
Но проще разобрать более общий случай (вызов функции с 0..х параметрами), а уже аргументы функций проверить отдельно. Например, можно завести хэш-таблицу в которую записать в качестве ключа имена фукнций, а в качестве значений описания их параметров (списком, чтобы перегрузки поддерживать). Тогда описать функции можно будет простеньким ДСЛ-ем, а их проверку сделать универсальной.

A>Я думаю что нужно просто поставить какой-то другой символ вместо снежинки (*) в коде выше. Может плюс (+)?


Можно делать по разному. Я бы не стал хардкодить функции в грамматике.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:37
Оценка:
Здравствуйте, VladD2, Вы писали:

A>>2. В сейчас калькуляторе используется только один тип данных — float.

A>>Можно ли смешивать несколько типов чтобы сделать такую функцию: len("nemerle") => 7?

VD>Раз это калькулятор, он должен возвращать одно значение (не считая исключений).


Так моя функция вроде как одно значение и возрващает. Нет?

VD>
VD>variant CalcObject
VD>{
VD>  | Int    { value : int; }
VD>  | Double { value : double; }
VD>  | String { value : string; }
VD>}
VD>

VD>Ну, а там вычисляешь их динамически (проверяя соответствие типов).

OK, обмозгую. Я в общем делаю эксель
Если получится смешивать типы — гуд. Если нет — сделаю для каждого типа отдельный парсер
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[8]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 03.05.11 20:44
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, alvas, Вы писали:


A>>Этот код для функции, которая принимает 1..n параметров. Я правильно понял?

A>>
A>>func                  : SCG.IEnumerable.[float] -> float = ("max" / "avg" / "sum")s;
A>>funcExpr              : float = func "("s expr (";"s expr)* ")"s;
A>>


VD>Да. Вот только max для одного параметра — это какой-то "зденъ".


What is "зденъ"?

VD>Если зашивать это в грамматику, то путем описания двух правил и перечисления их в операторе приоритетного выбора.

VD>Но проще разобрать более общий случай (вызов функции с 0..х параметрами), а уже аргументы функций проверить отдельно. Например, можно завести хэш-таблицу в которую записать в качестве ключа имена фукнций, а в качестве значений описания их параметров (списком, чтобы перегрузки поддерживать). Тогда описать функции можно будет простеньким ДСЛ-ем, а их проверку сделать универсальной.

Обмозгую.

A>>Я думаю что нужно просто поставить какой-то другой символ вместо снежинки (*) в коде выше. Может плюс (+)?


VD>Можно делать по разному. Я бы не стал хардкодить функции в грамматике.


Я это уже понял, но где посмотреть описание синтаксиса для

funcExpr              : float = func "("s expr (";"s expr)* ")"s;



Снежинка означает 0..n. Я прав? А что может быть еще кроме снежинки?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[9]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 20:45
Оценка:
Здравствуйте, alvas, Вы писали:

A>Ну xml как правило правильный. А такой html можно парсить?


A><ul>

A><li> 1
A><li> 2 </li>
A><li/> 3
A></ul>

Можно. Можно парсить любой однозначный язык. Главное чтобы у него не было множества деревьев разбора. Т.е. чтобы он не парсился (правильно) более чем одним способом.

В данном случае все очень просто.
Тег <li> может быть:
1. Закрыт явно.
2. Закрыт следующим <li>.
3. Закрыт </ul>.

Ну, это на вскидку. У HTML есть спецификация где все эти правила должны быть описаны. Возможно у него и свой BNF есть.

Если парсер HTML нужен для дела, а не для игр, то возможно разумнее взять готовый вариант. Для дотнета оный точно существует. Парсить HTML вручную имеет смысл только если в кроме HTML нужно распозновать еще что-то. Например $-вхождения (сплайсы) или какие-то вложенные языки. Хотя и тут возможно лучше сначала отпарсить его готовым парсером (бо HTML весьма не простой формат).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 21:04
Оценка:
Здравствуйте, alvas, Вы писали:

A>Так моя функция вроде как одно значение и возрващает. Нет?


Я имел в виду, что тип возвращаемого значения правила вызова функции должен быть float.

VD>>
VD>>variant CalcObject
VD>>{
VD>>  | Int    { value : int; }
VD>>  | Double { value : double; }
VD>>  | String { value : string; }
VD>>}
VD>>

VD>>Ну, а там вычисляешь их динамически (проверяя соответствие типов).

A>OK, обмозгую. Я в общем делаю эксель


Я заметил.

A>Если получится смешивать типы — гуд. Если нет — сделаю для каждого типа отдельный парсер


Ехелевский Васик странная штука. Скажем сложение двух ячеей автоматом приводит тип. А сумирование функцией СУММ почему-то строки игнорирует. Но по всей видимости там динамическая типизация.
Но вообще, там явно динамика.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: [PEG] Регистронезависимый парсинг
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.11 21:07
Оценка:
Здравствуйте, alvas, Вы писали:

A>What is "зденъ"?


Джен буддизм. Ну, в общем нелимитированные извращения вызванные религиозными позывами .

VD>>Если зашивать это в грамматику, то путем описания двух правил и перечисления их в операторе приоритетного выбора.

VD>>Но проще разобрать более общий случай (вызов функции с 0..х параметрами), а уже аргументы функций проверить отдельно. Например, можно завести хэш-таблицу в которую записать в качестве ключа имена фукнций, а в качестве значений описания их параметров (списком, чтобы перегрузки поддерживать). Тогда описать функции можно будет простеньким ДСЛ-ем, а их проверку сделать универсальной.

A>Обмозгую.


Если эммулируешь выражения ёксела, то точно не стоит хардкодить функции в грамматику.

A>Я это уже понял, но где посмотреть описание синтаксиса для

A>
A>funcExpr              : float = func "("s expr (";"s expr)* ")"s;
A>


Что значит "где посмотреть описание синтаксиса". Ты же сам его и приводишь. Пример грамматики разбирающей 0..х параметров я привел в прошлом сообщении.

A>Снежинка означает 0..n. Я прав?


Да.

A>А что может быть еще кроме снежинки?


+ или ?

Читай доки
Автор(ы): Чистяков Владислав Юрьевич
Дата: 07.06.2011
Макрос PegGrammar – это макрос Nemerle, позволяющий добавлять в приложения парсеры, описываемые в нотации PEG.
.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: [PEG] Регистронезависимый парсинг
От: alvas  
Дата: 04.05.11 04:57
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Можно. Можно парсить любой однозначный язык. Главное чтобы у него не было множества деревьев разбора. Т.е. чтобы он не парсился (правильно) более чем одним способом.


Можешь привести пример неоднозначного языка?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.