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.

105 lines
3.3 KiB

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):
lbrack = Literal("[").suppress()
rbrack = Literal("]").suppress()
comma = Literal(",").suppress()
commentStart = oneOf("; #")
Define = self.Define
valueOp = Literal("=") | Combine(
Literal("+") + Literal("=")) | Combine(
Literal("-") + Literal("="))
comment = commentStart + Optional( restOfLine)
nonrbrack = "".join( [c for c in printables if c != "]" ]) + " \t"
nonvalueop = "".join( [c for c in printables if c not in {"=","-","+"} ]) + " \t"
noncomma = "".join( [c for c in printables if c != "," ])
clearsection = lbrack + Group(empty) + rbrack
sectionDef = Group(OneOrMore(lbrack + Word(nonrbrack) + rbrack)
+ (clearsection | ~lbrack ) + LineEnd().suppress())
unexpected = Group(~sectionDef + SkipTo(LineEnd(), include=True))("error")
unexpected.setParseAction(self._unexpected_token)
keyDef = ~lbrack + Word(nonvalueop) + valueOp + empty + restOfLine + LineEnd().suppress()
def stripKeyValue(tokens):
tokens[0] = tokens[0].strip()
tokens[1] = tokens[1].strip()
keyDef.setParseAction(stripKeyValue)
self.inibnf = sectionDef + Group(ZeroOrMore(Group(keyDef | unexpected))) | unexpected
self.inibnf.ignore( comment )
def _unexpected_token(self, st, locn, tokString):
erline = line(locn,st).strip()
if erline:
self.parseError(erline,
lineno(locn,st),
col(locn,st))
def parse(self, data):
for tokens,start,end in self.inibnf.scanString(data):
if tokens.getName() == "error":
continue
section, defkeys = tokens
sectionList = section.asList()
if sectionList[-1] == []:
self.clearSection(sectionList[:-1])
continue
self.startSection(section.asList())
for defkey in defkeys:
if defkey.getName() == "error":
continue
mapOp = {"=": self.Define.Assign,
"+=": self.Define.Append,
"-=": self.Define.Remove }
self.defineKey(section.asList(),
defkey[0], defkey[2],
mapOp[defkey[1]])
def startSection(self, section):
"""
Начало секции
"""
def clearSection(self, section):
"""
Очистка значений секции
"""
def defineKey(self, section, defkey, defval, deftype):
"""
Определение ключа
['section','block'] 'varname', 'varval', Define.Assign
"""
pass
def parseError(self, line, lineno, col):
"""
Ошибка в формате
line - пример строки
lineno - номер строки
col - номер символа
"""
pass