【问题标题】:How to do an IF statement in PLY?如何在 PLY 中做 IF 语句?
【发布时间】:2015-11-01 03:34:27
【问题描述】:

我正在使用 PLY 进行编译器。我已经成功实现了算术和逻辑运算,但是我在使用“if 语句”时遇到了问题。

这是我当前的代码:

-词法分析器:

tokens = (
    'NAME','INT', 'DOUBLE', 'GREATER', 'LESS',
    'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
    'LPAREN','RPAREN', 'CHAR', 'TRUE', 'FALSE',
    'GREATEQ', 'LESSEQ', 'EQEQ', 'NOTEQ', 'AND',
    'OR', 'COLON', 'IF'
    )

# Reserved words
reserved = {
    'if' : 'IF'
}

# Tokens

t_PLUS    = r'\+'
t_MINUS   = r'-'
t_TIMES   = r'\*'
t_DIVIDE  = r'/'
t_EQUALS  = r'='
t_LPAREN  = r'\('
t_RPAREN  = r'\)'
t_NAME    = r'[a-zA-Z][a-zA-Z0-9_]*'
t_CHAR    = r'\'[a-zA-Z0-9_+\*\- :,\s]*\''
t_TRUE    = r'\t'
t_FALSE   = r'\f'
t_GREATER = r'>'
t_LESS    = r'<'
t_GREATEQ = r'>='
t_LESSEQ  = r'<='
t_EQEQ    = r'=='
t_NOTEQ   = r'!='
t_AND     = r'&'
t_OR      = r'\|'
t_COLON   = r':'

def t_DOUBLE(t):
    r'[0-9]+\.[0-9]+'
    try:
        t.value = float(t.value)
    except ValueError:
        print("Integer value too large %d", t.value)
        t.value = 0
    return t

def t_INT(t):
    r'[0-9]+'
    try:
        t.value = int(t.value)
    except ValueError:
        print("Double value too large %d", t.value)
        t.value = 0
    return t

# Ignored characters
t_ignore = " \t"

def t_IF(t):
    r'if'
    return t

def t_newline(t):
    r'\n+'
    t.lexer.lineno += t.value.count("\n")

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

# Build the lexer
import ply.lex as lex
lexer = lex.lex()

-解析器:

# Parsing rules

precedence = (
    ('left','AND','OR'),
    ('left','GREATER','LESS', 'GREATEQ', 'LESSEQ', 'EQEQ', 'NOTEQ'),
    ('left','PLUS','MINUS'),
    ('left','TIMES','DIVIDE'),
    ('right','UMINUS'),
    )

# dictionary of names
names = { }

def p_statement_assign(t):
    'statement : NAME EQUALS expression'
    names[t[1]] = t[3]

def p_statement_expr(t):
    'statement : expression'
    print(t[1])

def p_statement_if(t):
    'statement : IF LPAREN expression RPAREN DP statement'  
    pass

def p_expression_ariop(t):
    '''expression : expression PLUS expression
                  | expression MINUS expression
                  | expression TIMES expression
                  | expression DIVIDE expression'''
    if t[2] == '+'  : t[0] = t[1] + t[3]
    elif t[2] == '-': t[0] = t[1] - t[3]
    elif t[2] == '*': t[0] = t[1] * t[3]
    elif t[2] == '/': t[0] = t[1] / t[3]

def p_expression_logop(t):
    '''expression : expression GREATER expression
                  | expression LESS expression
                  | expression GREATEQ expression
                  | expression LESSEQ expression
                  | expression EQEQ expression
                  | expression NOTEQ expression
                  | expression AND expression
                  | expression OR expression'''
    if t[2] == '>'  : t[0] = t[1] > t[3]
    elif t[2] == '<': t[0] = t[1] < t[3]
    elif t[2] == '>=': t[0] = t[1] >= t[3]
    elif t[2] == '<=': t[0] = t[1] <= t[3]
    elif t[2] == '==': t[0] = t[1] == t[3]
    elif t[2] == '!=': t[0] = t[1] != t[3]
    elif t[2] == '&': t[0] = t[1] and t[3]
    elif t[2] == '|': t[0] = t[1] or t[3]

def p_expression_uminus(t):
    'expression : MINUS expression %prec UMINUS'
    t[0] = -t[2]

def p_expression_group(t):
    'expression : LPAREN expression RPAREN'
    t[0] = t[2]

def p_expression_int(t):
    'expression : INT'
    t[0] = t[1]

def p_expression_double(t):
    'expression : DOUBLE'
    t[0] = t[1]

def p_expression_char(t):
    'expression : CHAR'
    t[0] = t[1]

def p_expression_name(t):
    'expression : NAME'
    try:
        t[0] = names[t[1]]
    except LookupError:
        print("Undefined name '%s'" % t[1])
        t[0] = 0

def p_expression_bool(t):
    'expression : bool'
    t[0] = t[1]

def p_true(t):
    'bool : TRUE'
    t[0] = True

def p_false(t):
    'bool : FALSE'
    t[0] = False

def p_error(t):
    print("Syntax error at '%s'" % t.value)

import ply.yacc as yacc
parser = yacc.yacc()

我也在解析器中尝试过这样的事情:

def p_statement_if(t):
    'statement : IF expression COLON statement' 
    t[0] = ('if',t[2],t[4])

无论表达式是真还是假,我的编译器总是执行语句
我做错了什么?

谢谢

【问题讨论】:

  • 顺便说一句,t_NAME 应该是r'[a-zA-Z_][a-zA-Z0-9_]*',第一个列表中带有下划线。
  • 编译器在什么意义上?在我看来,它就像是在进行评估,而不是生成一个以后可以执行的程序。由于每条语句都是在解析时对其进行评估的,因此在减少 if 语句时,条件语句将已经执行。

标签: python if-statement compiler-construction ply


【解决方案1】:

我最近处理了这个问题。我认为您的代码应该更改以减少生产。我的减少产品如下:

"""
start :   expression
       |  if_statement
"""
"""
if_statement :  IF expression then_statement else_statement ENDIF
"""
"""
then_statement :   THEN if_statement
                |  THEN  expression
"""
"""
else_statement :    ELSE expression
                |   ELSE if_statement
                |   empty
"""

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 2015-01-26
    • 2014-12-20
    • 2023-01-13
    • 1970-01-01
    • 2016-06-28
    相关资源
    最近更新 更多