You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from pyparsing import Literal, Word, ZeroOrMore, Group, Dict, Optional,\
restOfLine, empty, printables, OneOrMore, oneOf, nums,\
lineno, line, col, Keyword, SkipTo, LineEnd, Combine
from enum import Enum
class CalculateIniParser:
'''Класс парсера calculate.ini файлов.'''
class Define(Enum):
assign = 0
append = 1
remove = 2
def __init__(self):
self.operations = {"=": self.Define.assign,
"+=": self.Define.append,
"-=": self.Define.remove}
lbrack = Literal("[")
rbrack = Literal("]")
# comma = Literal(",").suppress()
comment_symbol = Literal(';') | Literal('#')
# Define = self.Define
value_operation = (Literal("=") | Combine(Literal("+") + Literal("="))
| Combine(Literal("-") + Literal("=")))
comment = comment_symbol + Optional(restOfLine)
section_name = Word(printables+'\t', excludeChars='[]')
value_name = Word(printables+'\t', excludeChars='=-+')
# non_comma = Word(printables+'\t', excludeChars=',')
clear_section = lbrack.suppress() + Group(empty) + rbrack.suppress()
section_start = Group(OneOrMore(lbrack.suppress() + section_name
+ rbrack.suppress())
+ (clear_section | ~lbrack())
+ LineEnd().suppress())
# Если содержимое ini-файла не предваряется заголовком секции,
# значит эта строка ошибочна.
unexpected = Group(~section_start + SkipTo(LineEnd(),
include=True))("error")
unexpected.setParseAction(self._unexpected_token)
key_value = (~lbrack + value_name
+ value_operation + empty
+ restOfLine + LineEnd().suppress())
def strip_key_value(tokens):
tokens[0] = tokens[0].strip()
tokens[1] = tokens[1].strip()
key_value.setParseAction(strip_key_value)
self.ini_section_parser = (section_start
+ Group(ZeroOrMore(
Group(key_value | unexpected)))
| unexpected)
self.ini_section_parser.ignore(comment)
def _unexpected_token(self, string, location, tokens):
'''Метод вызываемый парсером, если обнаружена некорректная строка,
предназначен для получения некорректной строки и ее дальнейшего
разбора.'''
error_line = line(location, string).strip()
if error_line:
return (error_line, lineno(location, string),
col(location, string))
def parse(self, data):
for tokens, start, end in self.ini_section_parser.scanString(data):
if tokens.getName() == "error":
print('error tokens: {}'.format(tokens))
yield {'error': tokens}
section, defkeys = tokens
section_list = section.asList()
if section_list[-1] == []:
self.clear_section(section_list[:-1])
yield {'clear_section': (section_list[:-1], )}
self.start_section(section.asList())
for defkey in defkeys:
yield {'define_key': (section.asList(), defkey[0], defkey[2],
self.operations[defkey[1]])}