# sly **Repository Path**: liantianbaiyun/sly ## Basic Information - **Project Name**: sly - **Description**: SLY is a 100% Python implementation of the lex and yacc tools commonly used to write parsers and compilers. Parsing is based on the same LALR(1) algorithm used by many yacc tools. - **Primary Language**: Unknown - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-08-23 - **Last Updated**: 2024-10-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # sly #### 介绍 SLY是一个用于编写解析器和编译器的库。它在很大程度上基于传统的编译器构建工具lex和yacc,并实现了相同的LALR(1)解析算法。大多数在lex和yacc中可用的功能,在SLY中也可以使用。需要注意的是,SLY并没有提供很多额外的功能(例如,自动构建抽象语法树、树遍历等)。你也不应该将它视为一个解析框架。相反,你会发现它是一个简洁但功能齐全的库,用于在Python中编写解析器。 #### 使用说明 SLY的最佳说明方式可能是通过一个示例。下面是编写一个解析器的示例,该解析器可以计算简单的算术表达式并存储变量: ``` # ----------------------------------------------------------------------------- # calc.py # ----------------------------------------------------------------------------- from sly import Lexer, Parser class CalcLexer(Lexer): tokens = { NAME, NUMBER, PLUS, TIMES, MINUS, DIVIDE, ASSIGN, LPAREN, RPAREN } ignore = ' \t' # Tokens NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' NUMBER = r'\d+' # Special symbols PLUS = r'\+' MINUS = r'-' TIMES = r'\*' DIVIDE = r'/' ASSIGN = r'=' LPAREN = r'\(' RPAREN = r'\)' # Ignored pattern ignore_newline = r'\n+' # Extra action for newlines def ignore_newline(self, t): self.lineno += t.value.count('\n') def error(self, t): print("Illegal character '%s'" % t.value[0]) self.index += 1 class CalcParser(Parser): tokens = CalcLexer.tokens precedence = ( ('left', PLUS, MINUS), ('left', TIMES, DIVIDE), ('right', UMINUS), ) def __init__(self): self.names = { } @_('NAME ASSIGN expr') def statement(self, p): self.names[p.NAME] = p.expr @_('expr') def statement(self, p): print(p.expr) @_('expr PLUS expr') def expr(self, p): return p.expr0 + p.expr1 @_('expr MINUS expr') def expr(self, p): return p.expr0 - p.expr1 @_('expr TIMES expr') def expr(self, p): return p.expr0 * p.expr1 @_('expr DIVIDE expr') def expr(self, p): return p.expr0 / p.expr1 @_('MINUS expr %prec UMINUS') def expr(self, p): return -p.expr @_('LPAREN expr RPAREN') def expr(self, p): return p.expr @_('NUMBER') def expr(self, p): return int(p.NUMBER) @_('NAME') def expr(self, p): try: return self.names[p.NAME] except LookupError: print(f'Undefined name {p.NAME!r}') return 0 if __name__ == '__main__': lexer = CalcLexer() parser = CalcParser() while True: try: text = input('calc > ') except EOFError: break if text: parser.parse(lexer.tokenize(text)) ```