# ParseBuillder
## О синтаксисе
ParseBuilder - библиотека для автоматического построения базовых парсеров для интерпретаторов. Пока что библиотека строит парсеры лишь на Python, но в будущем планируется расширение функционала в виде поддаржки таких языков, как: C++, Go, Java/Kotlin. Для построения лексера можно воспользоваться библиотекой LexBuilder.
## Примеры
```python
from ParseBuilder.Builder import PyBuilder
parser = PyBuilder()
parser.build()
```
```python
from Lexer import *
class Parser:
def __init__(self, lexer, symbol_table):
'''
Конструктор класса Parser.
Параметры:
- lexer: экземпляр класса Lexer для токенизации входного текста.
- symbol_table: экземпляр класса SymbolTable для отслеживания переменных.
symbol_table - объект класса SymbolTable, используется для
хранения и управления переменными.
'''
self.lexer = lexer
self.current_token = self.lexer.get_next_token()
self.symbol_table = symbol_table
def eat(self, token_type):
'''
Функция проверяет текущий токен и токен, с которого
мы хотим перейти на другой токен.
То есть у нас не получиться будучи на Token(VAR, "x") перейти на
следущий токен с того, которого мы передаём в функцию:
Текущий токен: VAR, мы передали в функцию токен PRINT -
получаем ошибку, потому что мы находимся на токене VAR, а хотим перейти
на следующий токен с токена PRINT.
'''
if self.current_token.type == token_type:
self.current_token = self.lexer.get_next_token()
else:
raise Exception(f"Error eating {self.current_token.type} token!")
def factor(self):
'''
Функция отвечает за использование встроенных функций языка или других
токенов которые возвращают значения:
... = input()
... = int(x)
... = True
'''
token = self.current_token
if token.type == INT_NUMBER:
self.eat(INT_NUMBER)
return int(token.value)
elif token.type == FLOAT_NUMBER:
self.eat(INT_NUMBER)
return float(token.value)
elif token.type == STRING:
string_value = token.value
self.eat(STRING)
return string_value
elif token.type == VAR:
var_name = token.value
self.eat(VAR)
return self.symbol_table.lookup(var_name)
def term(self):
'''
Обработка терма (произведения или частного).
Возвращает:
- Результат вычисления терма.
'''
result = self.factor()
while self.current_token.type in (MULTIPLY, DIVIDE):
token = self.current_token
if token.type == MULTIPLY:
self.eat(MULTIPLY)
result *= self.factor()
elif token.type == DIVIDE:
self.eat(DIVIDE)
result /= self.factor()
return result
def expr(self):
'''
Обработка выражения (суммы или разности).
Возвращает:
- Результат вычисления выражения.
'''
result = self.term()
while self.current_token.type in (PLUS, MINUS):
token = self.current_token
if token.type == PLUS:
self.eat(PLUS)
result += self.term()
elif token.type == MINUS:
self.eat(MINUS)
result -= self.term()
return result
def statement(self):
'''
Функция отвечает за встроенные функции и конструкции,
которые не возвращают значения:
print ...
var = ...
if ...
'''
if self.current_token.type == VAR:
var_name = self.current_token.value
self.eat(VAR)
if self.current_token.type == ASSIGN:
self.eat(ASSIGN)
value = self.expr()
self.symbol_table.define(var_name, value)
else:
sys.exit()
else:
self.current_token = self.lexer.get_next_token()
def parse(self):
'''
Парсинг входного текста и выполнение выражений.
Эта функция запускает парсинг входного текста и последовательно выполняет
выражения, включая присваивание переменных и вывод значений.
'''
while self.current_token.type != EOF:
self.statement()
```
Raw data
{
"_id": null,
"home_page": null,
"name": "ParseBuilder",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "parsebuilder python parser",
"author": "Alexander554",
"author_email": "gaa.28112008@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/6a/d8/dcb1d0b1d79fcbe3ef8e557e7fd12c0610a8d63945e418b1d79643880b65/parsebuilder-1.0.0.tar.gz",
"platform": null,
"description": "# ParseBuillder\n\n## \u041e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0435\nParseBuilder - \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u043e\u0432. \u041f\u043e\u043a\u0430 \u0447\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u0442\u0440\u043e\u0438\u0442 \u043f\u0430\u0440\u0441\u0435\u0440\u044b \u043b\u0438\u0448\u044c \u043d\u0430 Python, \u043d\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0434\u0434\u0430\u0440\u0436\u043a\u0438 \u0442\u0430\u043a\u0438\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, \u043a\u0430\u043a: C++, Go, Java/Kotlin. \u0414\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 LexBuilder.\n\n## \u041f\u0440\u0438\u043c\u0435\u0440\u044b\n```python\nfrom ParseBuilder.Builder import PyBuilder\n\n\nparser = PyBuilder()\nparser.build()\n```\n\n```python\nfrom Lexer import *\n\n\nclass Parser:\n def __init__(self, lexer, symbol_table):\n '''\n \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 Parser.\n\n \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:\n - lexer: \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 Lexer \u0434\u043b\u044f \u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430.\n - symbol_table: \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 SymbolTable \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.\n\n symbol_table - \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 SymbolTable, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f\n \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438.\n '''\n self.lexer = lexer\n self.current_token = self.lexer.get_next_token()\n self.symbol_table = symbol_table\n\n def eat(self, token_type):\n '''\n \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0438 \u0442\u043e\u043a\u0435\u043d, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e\n \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u043e\u043a\u0435\u043d.\n \u0422\u043e \u0435\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0431\u0443\u0434\u0443\u0447\u0438 \u043d\u0430 Token(VAR, \"x\") \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430\n \u0441\u043b\u0435\u0434\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0441 \u0442\u043e\u0433\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e:\n \u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d: VAR, \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0442\u043e\u043a\u0435\u043d PRINT -\n \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u0435 VAR, \u0430 \u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438\n \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0441 \u0442\u043e\u043a\u0435\u043d\u0430 PRINT.\n '''\n if self.current_token.type == token_type:\n self.current_token = self.lexer.get_next_token()\n else:\n raise Exception(f\"Error eating {self.current_token.type} token!\")\n\n def factor(self):\n '''\n \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u044f\u0437\u044b\u043a\u0430 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445\n \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:\n ... = input()\n ... = int(x)\n ... = True\n '''\n token = self.current_token\n if token.type == INT_NUMBER:\n self.eat(INT_NUMBER)\n return int(token.value)\n elif token.type == FLOAT_NUMBER:\n self.eat(INT_NUMBER)\n return float(token.value)\n elif token.type == STRING:\n string_value = token.value\n self.eat(STRING)\n return string_value\n elif token.type == VAR:\n var_name = token.value\n self.eat(VAR)\n return self.symbol_table.lookup(var_name)\n\n def term(self):\n '''\n \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0435\u0440\u043c\u0430 (\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0447\u0430\u0441\u0442\u043d\u043e\u0433\u043e).\n\n \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442:\n - \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0440\u043c\u0430.\n '''\n result = self.factor()\n\n while self.current_token.type in (MULTIPLY, DIVIDE):\n token = self.current_token\n if token.type == MULTIPLY:\n self.eat(MULTIPLY)\n result *= self.factor()\n elif token.type == DIVIDE:\n self.eat(DIVIDE)\n result /= self.factor()\n\n return result\n\n def expr(self):\n '''\n \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f (\u0441\u0443\u043c\u043c\u044b \u0438\u043b\u0438 \u0440\u0430\u0437\u043d\u043e\u0441\u0442\u0438).\n\n \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442:\n - \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.\n '''\n result = self.term()\n\n while self.current_token.type in (PLUS, MINUS):\n token = self.current_token\n if token.type == PLUS:\n self.eat(PLUS)\n result += self.term()\n elif token.type == MINUS:\n self.eat(MINUS)\n result -= self.term()\n\n return result\n\n def statement(self):\n '''\n \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438,\n \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:\n print ...\n var = ...\n if ...\n\n '''\n if self.current_token.type == VAR:\n var_name = self.current_token.value\n self.eat(VAR)\n if self.current_token.type == ASSIGN:\n self.eat(ASSIGN)\n value = self.expr()\n self.symbol_table.define(var_name, value)\n else:\n sys.exit()\n\n else:\n self.current_token = self.lexer.get_next_token()\n\n def parse(self):\n '''\n \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439.\n\n \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\n \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438 \u0432\u044b\u0432\u043e\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.\n '''\n while self.current_token.type != EOF:\n self.statement()\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "Library for automatic construction of lexers",
"version": "1.0.0",
"project_urls": null,
"split_keywords": [
"parsebuilder",
"python",
"parser"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c099b714815a4827912eed362dc9a55e44d809227946275cffbe873720da25ae",
"md5": "c1d70a57b53a64fbf93068235ab013e8",
"sha256": "fa86098c0badd53b4013de03741386ad9654a95f899d1c37aad586d916c735b0"
},
"downloads": -1,
"filename": "ParseBuilder-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c1d70a57b53a64fbf93068235ab013e8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 5895,
"upload_time": "2024-05-26T09:43:06",
"upload_time_iso_8601": "2024-05-26T09:43:06.562885Z",
"url": "https://files.pythonhosted.org/packages/c0/99/b714815a4827912eed362dc9a55e44d809227946275cffbe873720da25ae/ParseBuilder-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6ad8dcb1d0b1d79fcbe3ef8e557e7fd12c0610a8d63945e418b1d79643880b65",
"md5": "1c7aaca6c0739b0bb75280f538a92fcc",
"sha256": "d23f7dc4fce5531b1fc27bdf4449e2198b70a400070a75ac120448aa3a7dbfc2"
},
"downloads": -1,
"filename": "parsebuilder-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "1c7aaca6c0739b0bb75280f538a92fcc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 4136,
"upload_time": "2024-05-26T09:43:08",
"upload_time_iso_8601": "2024-05-26T09:43:08.683725Z",
"url": "https://files.pythonhosted.org/packages/6a/d8/dcb1d0b1d79fcbe3ef8e557e7fd12c0610a8d63945e418b1d79643880b65/parsebuilder-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-26 09:43:08",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "parsebuilder"
}