Как узнать номер правила, с которого произошло сокращение в слое? - PullRequest
0 голосов
/ 11 марта 2019

Предположим, у меня есть следующие правила в моей грамматике. Я хочу знать, из какого правила происходит сокращение.

iteration_statement : WHILE push_scope LPAREN expression  RPAREN  compound_statement pop_scope 
                           | DO push_scope compound_statement WHILE LPAREN expression  RPAREN  SEMICOLON pop_scope 
                           | FOR LPAREN push_scope for_init_statement expression SEMICOLON expression  RPAREN  compound_statement pop_scope 
                           | FOR LPAREN push_scope for_init_statement SEMICOLON expression  RPAREN  compound_statement pop_scope 
                           | FOR LPAREN push_scope for_init_statement expression SEMICOLON  RPAREN  compound_statement pop_scope 
                           | FOR LPAREN push_scope for_init_statement SEMICOLON  RPAREN  compound_statement pop_scope

Я хочу сделать что-то подобное

if p.ruleno==1:
   #action for while
elif p.ruleno==2:
  # action for do while
elif p.ruleno==3:
    # action for for in rule 3
elif p.ruleno==4:
   # action for for in rule 4
elif p.ruleno==5:
    # action for for in rule 5
elif p.ruleno==6:
   # action for for in rule 6

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Вы можете поместить различные типы циклов в различные функции:

def p_while(p):
    'iteration_statement : WHILE push_scope LPAREN expression  RPAREN  compound_statement pop_scope'
    #action for while

def p_do_while(p):
    'iteration_statement : DO push_scope compound_statement WHILE LPAREN expression  RPAREN  SEMICOLON pop_scope'
    #action for do while

def p_for(p):
    'iteration_statement : FOR LPAREN push_scope for_init_statement expression_opt SEMICOLON expression_opt  RPAREN  compound_statement pop_scope'
    # action for for

Примечание. Я упростил ваше правило для циклов for, чтобы иметь только один регистр (с необязательными выражениями), поэтому вы можете обрабатывать циклы for в одном методе, не проверяя каким-либо из четырех вариантов было подобрано.

1 голос
/ 11 марта 2019

Это не так, как работает Ply.Поместите каждое производство в его собственную функцию:

def p_iter_1(p):
    '''iteration_statement : WHILE push_scope LPAREN expression  RPAREN  statement pop_scope'''
     # Do action 1

def p_iter_2(p):
    '''iteration_statement : DO push_scope statement WHILE LPAREN expression  RPAREN  SEMICOLON pop_scope''''
    # Do action 2

def p_iter_3(p):
    '''iteration_statement : FOR LPAREN push_scope for_init_statement expression SEMICOLON expression  RPAREN  compound_statement pop_scope'''
    # Do action 3

# Etc.

Анализатор связывает функцию сокращения с каждым производством.Если вы поместите более одной продукции в строку документации для функции сокращения, эта функция будет связана с каждой продукцией.Это нормально, если действие такое же.(И их даже не нужно сводить к одному и тому же нетерминалу.) Но если действия разные, самое простое решение - использовать разные функции.

...