python - 为什么我定义的语法不使用标记?

标签 python yacc lex ply pushdown-automaton

我正在使用 lex 和 yacc 定义一种新语言。词法分析器工作正常,但解析器却不行。我认为问题是语法无法识别标记,但经过大量研究和试验后,我确实陷入了困境。我不太确定语法是否完全正确。我从解析器收到“输入中的语法错误”,但数据中没有语法错误。

点击查看LEX and YACC files

输入的数据是:

F 100

这是此语法的另一个示例:

L 36 [L 4 [F 100 R 90] R 10]

我的词法分析器(lexing.py)代码:

import lex

tokens = (
    'NUMBER',
    'RED',
    'GREEN',
    'BLUE',
    'BLACK',
    'FORW',
    'RIGHT',
    'LOOP',
    'COLOR',
    'PEN',
    'LSQB',
    'RSQB',
    'EMPTY'
) 

t_FORW    = r'F'
t_RIGHT   = r'R'
t_LOOP   = r'L'
t_COLOR  = r'COLOR'
t_PEN  = r'PEN'
t_LSQB  = r'\['
t_RSQB  = r'\]'
t_RED  = r'K'
t_GREEN  = r'Y'
t_BLUE  = r'M'
t_BLACK  = r'S'
t_EMPTY = r'\ ' 

def t_NUMBER(t):
    r'\d+'
    t.value = int(t.value)    
    return t 

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

t_ignore  = ' \t' 

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

lexer = lex.lex()


data = '''
F 100
''' 

lexer.input(data)
 
for tok in lexer:
    print(tok)

这是解析代码:

import yacc
from lexing import tokens


def p_root(p):
    '''root : function NUMBER option
            | COLOR colors option
            | PEN NUMBER option '''
    
def p_option(p):
    '''option : root
              | LSQB root RSQB root
              | EMPTY '''
def p_function(p):
    '''function : FORW 
                | RIGHT 
                | LOOP '''
    
def p_colors(p):
    '''colors : RED 
              | BLUE 
              | GREEN 
              | BLACK ''' 
              
def p_error(p):
    print("Syntax error in input!")

from lexing import data

# Build the parser

parser=yacc.yacc()
result=parser.parse(data)
#print (result)

我尝试了所有我知道的方法。如您所见,我还没有编写 p 参数,但尝试编写这并不是解决方案。真正的问题可能是什么?

最佳答案

眼前的问题是您使用 EMPTY 作为标记(单个空格字符)。该定义与 t_ignore 中的忽略字符列表冲突,这也会成为一个问题。但请注意,您的输入末尾没有空格字符(输入以换行符结尾,该换行符将被忽略),并且您的语法要求 optionEMPTY 结尾。这肯定会产生语法错误。 (在这个答案的第一个版本中,我说 t_ignore 被显式标记模式覆盖,但事实证明我错了。您可以在内部使用被忽略的字符一条规则,但不在开头;以被忽略的字符开头的标记永远不会匹配。)

特别是如果这是您的第一个项目,您应该遵循更系统的调试技术。首先确保输入按照您期望的方式进行标记,而不尝试解析标记流。当您开始解析流时,请确保任何语法错误都会报告产生错误的标记,包括其在输入中的位置。

词法分析器和解析器都可以使用关键字参数debug=True来调用,这将提供解析器操作的调试日志。这绝对应该是您调试的一部分。

尽管如此,我觉得你的语法对于确定输入的结构并不是很有用。良好的语法读取方式与您用自己的语言描述输入的方式相同,其中可能包括如下描述:

  • 输入是命令列表。
  • 命令可以是正向命令、向右命令……或循环命令。
  • 转发命令是一个 F 后跟一个数字。
  • 循环命令是一个 L 后跟一个数字,后跟 [] 内的命令列表。

关于python - 为什么我定义的语法不使用标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72317628/

相关文章:

python - 全局名称 'reverse' 未定义

python - 从字符串列表中删除空白字符串值

yacc - 单引号、双引号或标记?

Python YACC EOF 立即到达

grammar - Flex/Bison (Lex/Yacc) 无法比拟的简单正则表达式模式

python - 加速beautifulsoup

python - 识别出现在语料库文档中少于 1% 的单词

python - 如何从单独的文件运行解析器?

parsing - YAML 解析 - lex 还是手卷?

c++ - CMake : Flex custom_command never called