Вопрос о приоритете правил с grako

Я переделываю minilanguage, который я первоначально построил на Perl (см. Chessa # on github ), но я сталкиваюсь с рядом проблем, когда я иду применять семантику.

Вот грамматика :

  • Внедрение парсера для языка с уценкой
  • (* integers *) DEC = /([1-9][0-9]*|0+)/; int = /(0b[01]+|0o[0-7]+|0x[0-9a-fA-F]+)/ | DEC; (* floats *) pointfloat = /([0-9]*\.[0-9]+|[0-9]+\.)/; expfloat = /([0-9]+\.?|[0-9]*\.)[eE][+-]?[0-9]+/; float = pointfloat | expfloat; list = '[' @+:atom {',' @+:atom}* ']'; (* atoms *) identifier = /[_a-zA-Z][_a-zA-Z0-9]*/; symbol = int | float | identifier | list; (* functions *) arglist = @+:atom {',' @+:atom}*; function = identifier '(' [arglist] ')'; atom = function | symbol; prec8 = '(' atom ')' | atom; prec7 = [('+' | '-' | '~')] prec8; prec6 = prec7 ['!']; prec5 = [prec6 '**'] prec6; prec4 = [prec5 ('*' | '/' | '%' | 'd')] prec5; prec3 = [prec4 ('+' | '-')] prec4; (* <| and >| are rotate-left and rotate-right, respectively. They assume the nearest C size. *) prec2 = [prec3 ('<<' | '>>' | '<|' | '>|')] prec3; prec1 = [prec2 ('&' | '|' | '^')] prec2; expr = prec1 $; 

    Проблема, с которой я сталкиваюсь, заключается в том, что оператор d втягивается в правило идентификатора, когда между оператором и любыми последующими буквенно-цифровыми строками не существует пробелов. Хотя сама грамматика LL (2), я не понимаю, где проблема здесь.

    Например, 4d6 останавливает парсер, потому что он интерпретируется как 4 d6 , где d6 – идентификатор. Что должно произойти, так это то, что оно интерпретируется как 4 d 6 , причем d является оператором. В анализаторе LL это действительно так.

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

  • Внедрение парсера для языка с уценкой
  • 2 Solutions collect form web for “Вопрос о приоритете правил с grako”

    Проблема с вашим примером заключается в том, что у nameguard включена функция nameguard включенная по умолчанию, и это не позволит анализировать только d когда d6 впереди.

    Чтобы отключить эту функцию, создайте экземпляр собственного Buffer и передайте его экземпляру сгенерированного синтаксического анализатора:

     from grako.buffering import Buffer from myparser import MyParser # get the text parser = MyParser() parser.parse(Buffer(text, nameguard=False), 'expre') 

    Вершина версии Grako в репозитории Bitbucket добавляет --no-nameguard командной строки --no-nameguard для сгенерированных парсеров.

    В Perl вы можете использовать Marpa , общий синтаксический анализатор BNF, который поддерживает обобщенный приоритет с ассоциативностью (и многими другими) из коробки, например

     :start ::= Script Script ::= Expression+ separator => comma comma ~ [,] Expression ::= Number bless => primary | '(' Expression ')' bless => paren assoc => group || Expression '**' Expression bless => exponentiate assoc => right || Expression '*' Expression bless => multiply | Expression '/' Expression bless => divide || Expression '+' Expression bless => add | Expression '-' Expression bless => subtract 

    Полный рабочий пример здесь . Что касается языков программирования, то существует парсер C на основе Marpa .

    Надеюсь это поможет.

    Python - лучший язык программирования в мире.