Commit cd23e5d3 authored by dylan grafmyre's avatar dylan grafmyre
Browse files

fix overun in parse, added cfg parser

parent 4621ff1f
#!/usr/bin/env python3
import argparse
import fnmatch
import os
import json
import logging
import tarfile
import hashlib
import collections
import sys
import subprocess
LOGGER = logging.getLogger(os.path.basename(__file__))
HAS_PYVMF = False
try:
import pyvmf
HAS_PYVMF = True
except ImportError as err:
LOGGER.error(err)
ARGP = argparse.ArgumentParser()
#ARGP.add_argument('--mount-name', '-n', required=True)
#ARGP.add_argument('--mount-path', '-p', required=True)
ARGP.add_argument('--mod-dir', '-m', required=True)
def main_mount(argp):
with open(os.path.join(argp.mod_dir, 'cfg/mount.cfg')) as fh:
cfg = pyvmf.Cfg.load(fh)
for key, value in cfg.attributes.items():
print('{} {}'.format(key, value))
def main(argp=None, argv=None):
if argp is None:
argp = ARGP.parse_args(argv)
logging.basicConfig(level=logging.INFO)
if not HAS_PYVMF:
raise RuntimeError('missing pyvmf')
return main_mount(argp)
if __name__ == '__main__':
exit(main())
......@@ -2,5 +2,6 @@
from pyvmf.vmf import Vmf
from pyvmf.vmt import Vmt
from pyvmf.cfg import Cfg
from pyvmf.exceptions import *
from pyvmf.mdl import mdl_materials
#!/usr/bin/env python3
import collections
import logging
import io
import pyvmf.objects
import pyvmf.objects as o
import pyvmf.re as r
import pyvmf.exceptions as e
CFG_TOKENS = {
'all': o.ReTokens('all', [
#r.RE_DECIMAL,
r.RE_START_BLOCK,
r.RE_END_BLOCK,
r.RE_DQUOTLITERAL,
#r.RE_TYPE,
r.RE_LINEWHITESPACE,
r.RE_NEWLINE,
r.RE_LINECOMMENT,
]),
'start': o.ReTokens('start', [
r.RE_DQUOTLITERAL,
r.RE_LINEWHITESPACE,
r.RE_NEWLINE,
r.RE_LINECOMMENT,
]),
'start_block': o.ReTokens('start_block', [
r.RE_START_BLOCK,
r.RE_LINEWHITESPACE,
r.RE_NEWLINE,
r.RE_LINECOMMENT,
]),
#'literal': o.ReTokens('literal', [
# r.RE_DQUOTLITERAL,
# r.RE_WHITESPACE,
#]),
'block': o.ReTokens('block', [
r.RE_START_BLOCK,
r.RE_DQUOTLITERAL,
r.RE_END_BLOCK,
r.RE_TYPE,
r.RE_LINEWHITESPACE,
r.RE_NEWLINE,
r.RE_LINECOMMENT,
]),
'literal_value': o.ReTokens('literal_value', [
r.RE_DQUOTLITERAL,
r.RE_LINEWHITESPACE,
r.RE_NEWLINE,
r.RE_LINECOMMENT,
]),
'whitespace': o.ReTokens('whitespace', [
r.RE_LINEWHITESPACE,
r.RE_NEWLINE,
r.RE_LINECOMMENT,
]),
}
class CfgToken(pyvmf.objects.Token):
pass
class CfgItem(pyvmf.objects.Leaf):
pass
class Cfg:
def __init__(self, root_vmtitem):
self.data = root_vmtitem
def __getitem__(self, *args, **kwargs):
return self.data.__getitem__(*args, **kwargs)
def walk(self):
yield from self.data.walk()
@property
def attributes(self):
return self.data.attributes
def __repr__(self):
return '<{s.__class__.__name__} {s.data.attributes}>'.format(s=self)
#
@classmethod
def load(cls, file_):
return cls.new_from_file(file_)
@classmethod
def loads(cls, str_):
return cls.load(io.StringIO(str_))
@classmethod
def new_from_file(cls, file_):
return cls(cls._load_tokenstream(cls._tokenize_stream(file_)))
@staticmethod
def _tokenize_stream(stream, chunksize=4096):
vmt_tokens = CFG_TOKENS['all']
eof = False
chunk = ''
line = 0
while True:
if not eof and len(chunk) < chunksize:
nextchunk = stream.read(chunksize)
if not nextchunk:
eof = True
chunk += nextchunk
if not chunk:
break
token_match = None
re_expr = None
for re_expr in vmt_tokens.tokens:
try:
token_match = next(re_expr.re.finditer(chunk))
except StopIteration as err:
token_match = None
continue
if token_match.start() != 0:
token_match = None
continue
if token_match:
break
if token_match is None:
raise e.PyvmfTokenizeError('none of expected tokens {!r} found in\n\n\t{!r}...'.format(
vmt_tokens,
chunk[:100],
))
chunk = chunk[token_match.end():]
value = token_match.group(0)
yield CfgToken(re_expr, line, value)
line += value.count('\n')
@staticmethod
def _load_tokenstream(tokenstream):
data = CfgItem([], 'root', dict(), list())
stack = [data]
tokens = CFG_TOKENS['start']
ctx = data
keyval = None
for token in tokenstream:
if token.re not in tokens.tokens:
raise e.PyvmfUnexpectedToken('none of expected tokens {!r} found, got token\n\n\t{!r} on line {}'.format(
tokens,
token,
token.lineno,
))
if token.re is r.RE_WHITESPACE:
continue
if token.re is r.RE_LINEWHITESPACE:
continue
if token.re is r.RE_NEWLINE:
continue
if token.re is r.RE_LINECOMMENT:
continue
if token.re is r.RE_DQUOTLITERAL:
if tokens is CFG_TOKENS['start']:
data.name = token.value
tokens = CFG_TOKENS['start_block']
continue
if tokens is CFG_TOKENS['block']:
if keyval is None:
keyval = token.value[1:-1]
tokens = CFG_TOKENS['literal_value']
continue
if token.re is r.RE_DQUOTLITERAL:
# or token.re is r.RE_DECIMAL:
if tokens is CFG_TOKENS['literal_value']:
ctx.attributes[keyval] = token.value[1:-1]
keyval = None
tokens = CFG_TOKENS['block']
continue
if token.re is r.RE_START_BLOCK:
assert data is ctx
tokens = CFG_TOKENS['block']
continue
if token.re is r.RE_END_BLOCK:
tokens = CFG_TOKENS['whitespace']
continue
raise NotImplementedError('unhandled token {!r}'.format(token))
return data
......@@ -8,8 +8,11 @@ except ImportError as err:
import re
RE_WHITESPACE = ReToken('whitespace', re.compile(r'\s\s*'))
RE_LINEWHITESPACE = ReToken('inline_whitespace', re.compile(r'[^\S\r\n][^\S\r\n]*'))
RE_NEWLINE = ReToken('newline_whitespace', re.compile(r'\n(\r)?'))
RE_START_BLOCK = ReToken('start_block', re.compile(r'{'))
RE_DQUOTLITERAL = ReToken('doublequote-literal', re.compile(r'"[^"]*"'))
RE_END_BLOCK = ReToken('end_block', re.compile(r'}'))
RE_TYPE = ReToken('type', re.compile(r'\b(\w\w*)\b'))
RE_DECIMAL = ReToken('decimal', re.compile(r'\b\d\d*\b'))
RE_LINECOMMENT = ReToken('line_comment', re.compile(r'//[^\n]*'))
......@@ -119,6 +119,7 @@ class Vmf:
token_match = re_expr.re.match(chunk)
if token_match:
break
token_match = None
if token_match is None:
raise e.PyvmfTokenizeError('none of expected tokens {!r} found in\n\n\t{!r}...'.format(
......
......@@ -127,8 +127,10 @@ class Vmt:
try:
token_match = next(re_expr.re.finditer(chunk))
except StopIteration as err:
token_match = None
continue
if token_match.start() != 0:
token_match = None
continue
if token_match:
break
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment