EBNF / parboiled: как перевести регулярное выражение в PEG? - PullRequest
3 голосов
/ 03 марта 2011

Это вопрос, относящийся как к инфраструктуре парсированного парсера, так и к BNF / PEG в целом.

Допустим, у меня есть довольно простое регулярное выражение

^\\s*([A-Za-z_][A-Za-z_0-9]*)\\s*=\\s*(\\S+)\\s*$

, которое представляетпсевдо-EBNF из

<line>               ::= <ws>? <identifier> <ws>? '=' <nonwhitespace> <ws>?
<ws>                 ::= (' ' | '\t' | {other whitespace characters})+
<identifier>         ::= <identifier-head> <identifier-tail>
<identifier-head>    ::= <letter> | '_'    
<identifier-tail>    ::= (<letter> | <digit> | '_')*
<letter>             ::= ('A'..'Z') | ('a'..'z')
<digit>              ::= '0'..'9'
<nonwhitespace>      ::= ___________

Как бы вы определили непробельные символы (один или несколько символов, которые не являются пробелами) в EBNF?

Для тех из вас, кто знаком с библиотекой Java с пропаркой, какНе могли бы вы реализовать правило, которое определяет непробельные символы?

Ответы [ 2 ]

5 голосов
/ 03 марта 2011

Вы застряли в соглашениях вашего лексического генератора для определения диапазонов символов и операций над диапазонами символов.

Многие генераторы лексеров принимают шестнадцатеричные значения (например, 0x) для представления символов, поэтому вы можете написать:

 '0'..'9'
 0x30..\0x39

для цифр.

Для незаполненных пространств вам необходимо знать, какой набор символов вы используете. Для 7-битного ASCII, непустое пространство - это концептуально все печатные символы:

0x21..\0x7E

Для ISO8859-1:

( 0x21..\0x7E | 0x80-0xFF )

Вы можете сами решить, являются ли коды символов выше 0x80 пробелами или нет (неразрывный пробел - пробел?). Вы также можете выбрать статус управляющих символов 0x0..0x1F. Является ли символ табуляции (0x9) символом пробела? Как насчет CR 0xD и LF 0xA? Как насчет управляющего символа ETB?

Юникод сложнее, потому что его огромный набор, и ваш список становится большим и грязным. C'est la vie . Наш DMS Software Reengineering Toolkit используется для создания синтаксических анализаторов для широкого спектра языков и должен поддерживать лексеры для ASCII, ISO8859-z для большого количества z и Unicode. Вместо того чтобы писать сложные «аддитивные» диапазоны регулярных выражений, DMS допускает вычитающих регулярных выражений, и поэтому мы можем написать:

 <UniCodeLegalCharacters>-<UniCodeWhiteSpace>

, который намного легче понять и понимает это с первой попытки.

2 голосов
/ 04 октября 2013

В EBNF я бы просто определил непробельный символ как любой символ, не являющийся пробелом:

nonwhitespace ::= anycharacter - whitespace

Для этого требуется наличие литерала anycharacter, который определяет весь диапазон возможных символов, и четкогоопределение того, какие символы являются пробелами.

В Parboiled вы можете сделать это, используя правила TestNot и ANY, поэтому, например, непробельные символы будут определены как любой символ, который не соответствует правилу WhiteSpace ():

Sequence( TestNot(WhiteSpace()) , ANY )
...