You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Sly库时遭遇未使用规则及语法错误问题求助

解决Sly库中未使用规则及语法错误问题

问题现象

运行代码后收到大量未使用规则警告,执行命令时还会抛出语法错误:

警告: C:\Program Files\adbms\strg_eng\done.py:66: 已定义规则'change_tname'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:70: 已定义规则'create_db'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:74: 已定义规则'create_tb'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:78: 已定义规则'sort'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:82: 已定义规则'delete_db'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:86: 已定义规则'delete_tb'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:90: 已定义规则'delete_rec'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:94: 已定义规则'delete_column'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:98: 已定义规则'create_column'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:102: 已定义规则'create_rec'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:106: 已定义规则'display_tb'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:110: 已定义规则'update_c'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:114: 已定义规则'update_r'但未使用
警告: C:\Program Files\adbms\strg_eng\done.py:118: 已定义规则'get_list'但未使用
警告: 存在14条未使用规则
警告: 符号'change_tname'不可达
警告: 符号'create_db'不可达
警告: 符号'create_tb'不可达
警告: 符号'sort'不可达
警告: 符号'delete_db'不可达
警告: 符号'delete_tb'不可达
警告: 符号'delete_rec'不可达
警告: 符号'delete_column'不可达
警告: 符号'create_column'不可达
警告: 符号'create_rec'不可达
警告: 符号'display_tb'不可达
警告: 符号'update_c'不可达
警告: 符号'update_r'不可达
警告: 符号'get_list'不可达
FileLang> create_db test_tb
sly: 第1行语法错误,令牌=CREATE_DB

问题原因

  1. 缺少起始规则:Sly Parser要求必须有一个起始规则,所有其他语法规则都要能被起始规则关联。当前代码中的命令规则都是独立的,没有被任何起始规则引用,导致Parser无法识别,标记为未使用/不可达。
  2. Tokens集合不完整:Lexer中定义的NUMBER和TEXT方法没有加入tokens集合,可能导致数值和文本类型的token无法被正确识别。
  3. Token匹配冲突:MIN、MAX的正则表达式[0-9]+和NUMBER规则重复,Sly按定义顺序优先匹配,会导致数值被错误识别为MIN/MAX而非NUMBER。

解决方案

  1. 添加起始规则:定义statement作为起始规则,将所有命令规则作为它的备选项,让Parser能遍历到所有命令。
  2. 完善Tokens集合:将NUMBER和TEXT加入Lexer的tokens集合。
  3. 调整Token匹配逻辑:删除MIN、MAX的单独定义,在语法规则中直接使用NUMBER(MIN/MAX本质就是数值),避免匹配冲突。

修改后的完整代码

from sly import Lexer, Parser
from drm import *  # Import everything from the drm module

# Lexer
class FileLexer(Lexer):
    tokens = {CREATE_DB, CREATE_TB, CREATE_REC, CREATE_COLUMN,
              DELETE_DB, DELETE_TB, DELETE_REC, DELETE_COLUMN,
              CHANGE_DBNAME, CHANGE_TNAME, SORT, DISPLAY_TB,
              UPDATE_C, UPDATE_R, GET_LIST, COLUMN_NAME, VALUE,
              TYPE, CONSTRAINT, DBNAME, TNAME, NEWNAME, NUMBER, TEXT}

    ignore = ' \t\n'

    # 关键字优先定义
    CREATE_DB = r'create_db'
    CREATE_TB = r'create_tb'
    CREATE_REC = r'create_rec'
    CREATE_COLUMN = r'create_column'
    DELETE_DB = r'delete_db'
    DELETE_TB = r'delete_tb'
    DELETE_REC = r'delete_rec'
    DELETE_COLUMN = r'delete_column'
    CHANGE_DBNAME = r'change_dbname'
    CHANGE_TNAME = r'change_tname'
    SORT = r'sort'
    DISPLAY_TB = r'display_tb'
    UPDATE_C = r'update_c'
    UPDATE_R = r'update_r'
    GET_LIST = r'get_list'

    TYPE = r'(st|num)'
    CONSTRAINT = r'(NONE|NOTNONE|UNIQUE|NOUNI)'

    DBNAME = r'[a-zA-Z0-9_.-]+'
    TNAME = r'[a-zA-Z0-9_.-]+'
    NEWNAME = r'[a-zA-Z0-9_.-]+'
    COLUMN_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
    VALUE = r'[a-zA-Z_0-9]+'

    # 数值和文本定义放在后面,避免和关键字冲突
    @_(r'[0-9]+')
    def NUMBER(self, t):
        t.value = int(t.value)
        return t

    @_(r'"[^"]*"')
    def TEXT(self, t):
        t.value = t.value.strip('"')
        return t

    def error(self, t):
        print(f'Illegal character {t.value[0]} at line {self.lineno}')
        self.index += 1

# Parser
class FileParser(Parser):
    tokens = FileLexer.tokens
    # 指定起始规则
    start = 'statement'

    def __init__(self):
        self.symbol_table = {}

    # 起始规则,包含所有命令选项
    @_('change_dbname',
       'change_tname',
       'create_db',
       'create_tb',
       'sort',
       'delete_db',
       'delete_tb',
       'delete_rec',
       'delete_column',
       'create_column',
       'create_rec',
       'display_tb',
       'update_c',
       'update_r',
       'get_list')
    def statement(self, p):
        pass

    @_('CHANGE_DBNAME DBNAME NEWNAME')
    def change_dbname(self, p):
        print(f'Change DB Name: {p.DBNAME} to {p.NEWNAME}')

    @_('CHANGE_TNAME DBNAME TNAME NEWNAME')
    def change_tname(self, p):
        print(f'Change Table Name: {p.DBNAME} {p.TNAME} to {p.NEWNAME}')

    @_('CREATE_DB DBNAME')
    def create_db(self, p):
        print(f'Create DB: {p.DBNAME}')

    @_('CREATE_TB DBNAME TNAME')
    def create_tb(self, p):
        print(f'Create Table: {p.DBNAME} {p.TNAME}')

    @_('SORT DBNAME TNAME')
    def sort(self, p):
        print(f'Sort: {p.DBNAME} {p.TNAME}')

    @_('DELETE_DB DBNAME')
    def delete_db(self, p):
        print(f'Delete DB: {p.DBNAME}')

    @_('DELETE_TB DBNAME TNAME')
    def delete_tb(self, p):
        print(f'Delete Table: {p.DBNAME} {p.TNAME}')

    @_('DELETE_REC DBNAME TNAME')
    def delete_rec(self, p):
        print(f'Delete Record: {p.DBNAME} {p.TNAME}')

    @_('DELETE_COLUMN DBNAME TNAME COLUMN_NAME')
    def delete_column(self, p):
        print(f'Delete Column: {p.DBNAME} {p.TNAME} {p.COLUMN_NAME}')

    # 将MIN/MAX替换为NUMBER
    @_('CREATE_COLUMN DBNAME TNAME COLUMN_NAME TYPE NUMBER NUMBER CONSTRAINT')
    def create_column(self, p):
        print(f'Create Column: {p.DBNAME} {p.TNAME} {p.COLUMN_NAME} {p.TYPE} {p.NUMBER0} {p.NUMBER1} {p.CONSTRAINT}')

    @_('CREATE_REC DBNAME TNAME')
    def create_rec(self, p):
        print(f'Create Record: {p.DBNAME} {p.TNAME}')

    @_('DISPLAY_TB DBNAME TNAME')
    def display_tb(self, p):
        print(f'Display Table: {p.DBNAME} {p.TNAME}')

    @_('UPDATE_C DBNAME TNAME COLUMN_NAME VALUE')
    def update_c(self, p):
        print(f'Update Column: {p.DBNAME} {p.TNAME} {p.COLUMN_NAME} {p.VALUE}')

    @_('UPDATE_R DBNAME TNAME COLUMN_NAME VALUE')
    def update_r(self, p):
        print(f'Update Record: {p.DBNAME} {p.TNAME} {p.COLUMN_NAME} {p.VALUE}')

    @_('GET_LIST DBNAME TNAME COLUMN_NAME')
    def get_list(self, p):
        print(f'Get List: {p.DBNAME} {p.TNAME} {p.COLUMN_NAME}')

# Example usage
if __name__ == '__main__':
    lexer = FileLexer()
    parser = FileParser()

    while True:
        try:
            text = input('FileLang> ')
            tokens = lexer.tokenize(text)
            parser.parse(tokens)
        except EOFError:
            break

说明

  • 新增start = 'statement'指定起始规则,statement规则包含所有命令作为备选项,解决了规则不可达的问题。
  • 将MIN、MAX从tokens中移除,改用NUMBER匹配数值,避免了token冲突。
  • 修正TEXT的正则表达式,直接用"[^"]*"并处理去掉引号的逻辑,更符合实际使用场景。
  • 将NUMBER和TEXT加入tokens集合,确保能被正确识别。

内容的提问来源于stack exchange,提问作者METTALIC STAR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:07:02