改变检测块层y末端的方法

2024-05-19 16:35:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一个python到c++的翻译程序。现在我正在完成我的句法语法和我有一个小问题,如果我的else块。 问题是我不知道如何用表格来检测块的末尾。 现在我要测试这个文件:

print(33)
if a<3:
    print(test);
b=5

结果如下:

Program
|  print
|  |  '33'
|  if
|  |  < (2)
|  |  |  'a'
|  |  |  '3'
|  |  Program
|  |  |  print
|  |  |  |  'test'
|  =
|  |  'b'
|  |  '5'

这是正确的,因为b=5和我的if处于同一水平。 这是我的莱克斯代币:

reserved_words = (
    'if',
    'print',
    'range',
    'for',
    'in',
    'while'
)

tokens = (
    'COMPARATOR',
    'IDENTIFIER',
    'ILLEGAL',
    'FLOAT',
    'INT',
    'EQU',
    'ENTER',
    'POINTS',
    'TAB',
    'END'
    ) + tuple(map(lambda s:s.upper(),reserved_words))



literals = ';():\s'

def t_ENTER(t):
    r'\n'
    return t



def t_ADD_OP(t):
    r'\+|-'
    return t

def t_POINTS(t):
    r':'
    return t

def t_EQU(t):
    r'\='
    return t    

def t_MUL_OP(t):
    r'\*|/'
    return t

def t_COMPARATOR(t):
    r'[<>]'
    return t


def t_INT(t):
    #r'\d+(?!\.)(?![a-zA-Z])'
    r'\b(?<!\.)\d+(?!\.)\b'
    try:
        t.value = t.value   
    except ValueError:
        print ("Line %d: Problem while parsing %s!" % (t.lineno,t.value))
        t.value = 0
    return t

def t_ILLEGAL(t):
    r'\d+[a-zA-z]+'
    try:
        t.value = t.value   
    except ValueError:
        print ("Line %d: Problem while parsing %s!" % (t.lineno,t.value))
        t.value = 0
    return t

def t_FLOAT(t):
    r'\d+\.{1}\d+'
    try:
        t.value = float(t.value)   
    except ValueError:
        print ("Line %d: Problem while parsing %s!" % (t.lineno,t.value))
        t.value = 0.0
    return t

def t_IDENTIFIER(t):
    r'[A-Za-z_]\w*'
    if t.value in reserved_words:
        t.type = t.value.upper()
    return t

def t_TAB(t):
    r'[ \t]{4}'
    return t

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


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

t_ignore = ' '

lex.lex()

我的规则是:

    vars = {}

def p_programme_statement(p):
    ''' programme : statement  '''
    p[0] = AST.ProgramNode(p[1])

def p_programme_recursive(p):
    ''' programme : statement ENTER programme '''
    p[0] = AST.ProgramNode([p[1]]+p[3].children)

def p_statement(p):
    ''' statement : assignation
                        | structure '''
    p[0] = p[1]

def p_expression_num_or_var(p):
    '''expression : INT
        | FLOAT 
        | IDENTIFIER 
        '''
    p[0] = AST.TokenNode(p[1])

def p_statement_print(p):
    ''' statement : PRINT '(' expression ')' '''
    p[0] = AST.PrintNode(p[3])

def p_expression_comp(p):
    ''' expression : expression COMPARATOR expression'''
    p[0] = AST.OpNode(p[2],[p[1],p[3]])

def p_structure_if(p):
    '''structure : IF expression POINTS ENTER programme ';' '''
    p[0] = AST.IfNode([p[2],p[5]])

def p_structure_while(p):
    ''' structure : WHILE expression POINTS ENTER programme '''
    p[0] = AST.WhileNode([p[2],p[5]])

def p_expression_paren(p):
    '''expression : '(' expression ')' '''
    p[0] = p[2]

def p_assign_block(p):
    ''' assignation : TAB IDENTIFIER EQU expression'''
    p[0] = AST.AssignNode([AST.TokenNode(p[2]),p[4]])

def p_assign(p):
    ''' assignation : IDENTIFIER EQU expression '''
    p[0] = AST.AssignNode([AST.TokenNode(p[1]),p[3]])

def p_error(p):
    print ("Syntax error in line %d" % p.lineno)
    yacc.errok()

问题是:我的p_结构是错误的,因为现在我说块的末尾是“;”出现。如何通过检查表格来检测块的结尾(如果下一行不在另一行的表格级别,那么它就不是同一个块,然后不使用';'角色


Tags: returnifvaluedefaststructurestatementprint
1条回答
网友
1楼 · 发布于 2024-05-19 16:35:30

提前道歉,这不是一个完整的答案,但这是一个非常适合的评论,我希望它对你有用

官方Python文档包括BNF grammar for the full language

棘手的部分是,您需要生成适当数量的“dedent”标记以与选项卡一起使用(官方语法称之为INDENT)。同样,我们只关心行开头的空格

t_TAB正则表达式需要类似于^[ \t]*(因为您需要能够检查没有任何前导空格的行,以便知道代码何时返回顶层)。然而,这当然(通过设计)匹配一个空字符串,所以每行只需要测试一次-我不确定ply是否能胜任这项任务,或者至少我不知道如何立即使它工作

无论如何,您将需要检查t_TAB()中的空白字符串,以确定它对应于哪个缩进级别(如果您想匹配Python的形式行为,请使用以前看到的缩进字符串堆栈;如果你想做更严格的事情,我想你可以计算一下制表符/空格的数量),然后发出一个缩进或者零个或更多的DEDENTs(这是我不确定的另一件事,ply是否支持从一个标记regex生成多个标记-您可能需要使用t.lexer属性或其他一些东西

相关问题 更多 >