加载模型时内存错误



当我尝试加载模型(输入,而不是元模型(时,它会在执行后大约 30 秒返回一个MemoryError

预期:树列表:[{'type':'func', 'callee':'print', 'args':[['Hello']]}]实际:MemoryError

输出

Traceback (most recent call last):
File "C:/Users/kenxs/PycharmProjects/program/program/parser.py", line 103, in <module>
main()
File "C:/Users/kenxs/PycharmProjects/program/program/parser.py", line 97, in main
program.do_it(True, True, True)
File "C:/Users/kenxs/PycharmProjects/program/program/parser.py", line 80, in do_it
if cont and intp:   cont, err = self.interpret()
File "C:/Users/kenxs/PycharmProjects/program/program/parser.py", line 67, in interpret
self.model = self.mm.model_from_file(os.path.abspath('program.program'))
File "C:Program Files (x86)Python38-32libsite-packagestextxmetamodel.py", line 574, in model_from_file
return self.internal_model_from_file(file_name, encoding, debug)
File "C:Program Files (x86)Python38-32libsite-packagestextxmetamodel.py", line 613, in internal_model_from_file
model = self._parser_blueprint.clone().get_model_from_str(
File "C:Program Files (x86)Python38-32libsite-packagestextxmodel.py", line 262, in get_model_from_str
self.parse(model_str, file_name=file_name)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 1493, in parse
self.parse_tree = self._parse()
File "C:Program Files (x86)Python38-32libsite-packagestextxmodel.py", line 221, in _parse
return self.parser_model.parse(self)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 365, in _parse
result = e.parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 365, in _parse
result = e.parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 481, in _parse
result = p(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 404, in _parse
result = e.parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 365, in _parse
result = e.parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 365, in _parse
result = e.parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 286, in parse
result = self._parse(parser)
File "C:Program Files (x86)Python38-32libsite-packagesarpeggio__init__.py", line 484, in _parse
append(result)
MemoryError

语法

Program:
commands*=Command
;
Command:
Statement | Function | Definition
;
Statement:
callee=ID '(' checker=Checker ')' '=' effect=Collection Ending
;
Checker:
a=Object sign=CheckerSign b=Object
;
CheckerSign:
'==' | '!='
;
Collection:
'[' objs*=PseudoObject ']'
;
PseudoObject:
Object Ending
;
Function:
callee=ID '(' args=Arguments ')' Ending
;
Arguments:
arg*=Argument
;
Argument:
NamedArgument | UnnamedArgument
;
NamedArgument:
a=Object '=' b=Object
;
UnnamedArgument:
a=Object
;
Definition:
a=Object '=' b=Object
;
Object:
a*=ObjectChild
;
ObjectChild:
ObjectChildChild ( '.' | '' )
;
ObjectChildChild:
String | ID | INT | STRICTFLOAT | BOOL | Collection | Function
;
String:
'"' ID '"'
;
Comment:
/#.*/ Ending
;
Ending:
'' *Newline
;
Newline:
( 'n' | ';' )
;

程序

import os
from textx import *
from textx.export import *

class Parser(object):
def __init__(self, meta_model_path='grammar.tx', model_str='print("Hello")'):
self.tree = []
self.meta_model_path = os.path.abspath(meta_model_path)
self.model_str = model_str
self.mm = None
self.model = None
def __str__(self):
return str(self.tree)
def _interpret_function(self, c):
result = {}
result['type'] = 'func'
result['callee'] = c.callee
result['args'] = []
for arg in c.args.arg:
if arg.__class__.__name__ == 'UnnamedArgument':
result['args'].append([arg.a.a])
elif arg.__class__.__name__ == 'NamedArgument':
result['args'].append([arg.a.a, arg.b.a])
return result
def _interpret_definition(self, c):
result = {}
result['type'] = 'defi'
result['a'] = c.a.a
result['b'] = c.b.a
return result
def _interpret_statement(self, c):
result = {}
result['type'] = 'stat'
result['callee'] = c.callee
result['checker_a'] = c.checker.a
result['checker_b'] = c.checker.b
result['checker_sign'] = c.checker.sign
result['effect'] = c.effect.objs
return result
def _interpret(self, model):
for c in model.commands:
if c.__class__.__name__ == 'Statement':
self.tree.append(self._interpret_statement(c))
elif c.__class__.__name__ == 'Function':
self.tree.append(self._interpret_function(c))
elif c.__class__.__name__ == 'Definition':
self.tree.append(self._interpret_definition(c))
def export_meta_model(self, mm):
metamodel_export(self.mm, os.path.abspath('grammar.dot'))
return [True, None]
def export_model(self, model):
model_export(self.model, os.path.abspath('program.dot'))
return [True, None]
def interpret(self):
print(-1)
self.mm = metamodel_from_file(self.meta_model_path, debug=False)
print(0)
try:
self.model = self.mm.model_from_str(self.model_str)
# self.model = self.mm.model_from_file(os.path.abspath('program.prg'))
except TextXSyntaxError as err:
print('Syntax Error @ {}:{}'.format(err.line, err.col))
print('{}'.format(err.message))
return [False, err]
print(1)
self._interpret(model)
print(2)
return [True, None]
def do_it(self, exp_mm=False, exp_m=False, intp=True):  # My naming skills :)
cont = True
err = None
if cont and intp:   cont, err = self.interpret()
if cont and exp_mm: cont, err = self.export_meta_model()
if cont and exp_m:  cont, err = self.export_model()

def main(debug=False):
print('Program')
program = Parser()
print('Inp Done')
program.do_it(True, True, True)
print('Done')
print(program)

if __name__ == "__main__":
main()

规则Ending具有零个或多个空字符串匹配''*这本质上是一个无限循环,构建具有无限数量的空匹配终端的解析树节点。最终,解析树会占用所有内存,您会MemoryError

通常,在可能为空匹配的解析表达式上重复("*"、"+"(可能会导致无限循环。

我建议您为此在问题跟踪器中注册一个问题,因为至少在运行时检测到它应该相当容易,而不会产生太多开销。

最新更新