разбор файла определенного формата в ply (python)

у меня проблема с ply, я должен получить файл со списком токенов и грамматикой (bnf), я написал грамматику для распознавания ввода, и она почти работает (просто мелкие проблемы, мы их решаем), для пример это допустимый входной файл

#tokens = NUM PLUS TIMES
exp : exp PLUS exp | exp TIMES exp
exp : NUM

(в данном случае нас не волнует неоднозначная грамматика или что-то еще, это пример для ввода)

синтаксический анализ каждой строки по отдельности работает нормально, но я хочу проанализировать весь файл с помощью следующих правил:

  • #tokens должны быть только в первой строке, поэтому, если у нас есть объявление #tokens после грамматики, оно недействительно
  • у вас может быть 0 или более пустых строк после каждой строки «кода»
  • у вас может быть столько правил грамматики, сколько вы хотите

я попытался использовать цикл для сканирования и анализа каждой строки отдельно, но я не могу контролировать первое (и действительно важное) правило, поэтому я попробовал это в своем файле .py:

я определил t_NLINEA (новая строка), у меня также была проблема с использованием символа \n в качестве литерала, и файл был открыт в режиме rU, чтобы избежать конфликтов по поводу символов \r\n или \n, поэтому я добавил эти правила:

def p_S(p):
'''S : T N U'''
print("OK")

def p_N(p): '''N : NLINEA N''' пройти

def p_N2(p): '''N : ''' пройти

def p_U(p): '''U : R N U''' пройти

def p_U2(p): '''U : ''' пройти

(как я уже говорил вам выше, я должен был использовать правило N, потому что ply не принимал литерал \n в моей грамматике, я добавил \n к переменной «литералы»)

T - это правило для анализа объявления #tokens, а R используется для анализа правил грамматики, T и R работают нормально, если я использую их в одной строке, но когда я добавляю продукты, которые я написал выше, я получаю синтаксическую ошибку при разборе первое грамматическое правило, например A : B C я получаю синтаксическую ошибку с :

любое предложение? Спасибо


person user2961204    schedule 06.11.2013    source источник


Ответы (1)


Ply пытается определить «стартовое правило» на основе ваших правил. С тем, что вы написали, это сделает "exp" начальным правилом, которое говорит, что есть только одно выражение для каждой строки или файла. Если вам нужно несколько выражений, вам, вероятно, понадобится список выражений:

def p_exp_list(p):
    """exp_list :
                | exp_list exp
    """
    if len(p) == 1:
       p[0] = []
    else:
       p[0] = p[1] + [p[2]]

Тогда вашим начальным правилом будет "exp_list". Это позволит использовать несколько выражений в каждой строке. Если вы хотите ограничиться одним выражением в строке, то как насчет:

def p_line_list(p):
    """line_list :
                 | line_list line
    """
    if len(p) == 1:
       p[0] == []
    else:
       p[0] = p[1] + [p[2]]

def p_line(p):
    """line : exp NL"""
    p[0] = p[1]

Я не думаю, что вы можете использовать новую строку как литерал (потому что это может испортить регулярные выражения). Вероятно, вам нужно более конкретное правило токена:

t_NL = r'[\r*\n]'

Почти уверен, что это сработает, но не пробовал, так как этого недостаточно.

Что касается строки «#token», вы можете просто пропустить ее, если она больше нигде не встречается:

def t_COMMENT(t):
    r'#.*$'
    pass # ignore this token
person swstephe    schedule 06.11.2013
comment
привет, спасибо за ваше предложение, у меня все еще есть проблема с символом новой строки, я не знаю, является ли это проблемой слоя или python, или что-то еще, что я делаю неправильно, я всегда получаю синтаксическую ошибку даже во второй строке используя ваше решение, но все равно спасибо, я проанализирую первую строку отдельно и использую остальные строки в качестве входных данных с правилом R... - person user2961204; 07.11.2013
comment
Ply просто создает действительно большое регулярное выражение, которое использует модуль Python re. Регулярные выражения — это особенность, а не проблема. не принимает \n. Вы могли бы сделать #(.|\n)*$, но это означает, что одна строка комментария отбрасывает все после строки комментария. - person swstephe; 14.11.2013