208 lines
5.9 KiB
Python
208 lines
5.9 KiB
Python
import os
|
|
import sys
|
|
from antlr4 import *
|
|
|
|
if "." in __name__:
|
|
from .ptmlTranslator import ptmlTranslator
|
|
from .ptmlParser import ptmlParser as Parser
|
|
from .ptmlLexer import ptmlLexer as Lexer
|
|
|
|
else:
|
|
from ptmlTranslator import ptmlTranslator
|
|
from ptmlParser import ptmlParser as Parser
|
|
from ptmlLexer import ptmlLexer as Lexer
|
|
|
|
|
|
def load(scene, ptml_path: str, behaviour_lib_path: str):
|
|
"""_summary_
|
|
|
|
Args:
|
|
ptml_path (str): _description_
|
|
behaviour_lib_path (str): _description_
|
|
|
|
Raises:
|
|
FileNotFoundError: _description_
|
|
FileNotFoundError: _description_
|
|
"""
|
|
# error handle
|
|
if not os.path.exists(ptml_path):
|
|
raise FileNotFoundError("Given a fault ptml path: {}".format(ptml_path))
|
|
if not os.path.exists(behaviour_lib_path):
|
|
raise FileNotFoundError(
|
|
"Given a fault behaviour library path: {}".format(behaviour_lib_path)
|
|
)
|
|
|
|
# noting fault, go next
|
|
ptml_path = format_trans_to_bracket(ptml_path)
|
|
# print(ptml_path)
|
|
input_stream = FileStream(ptml_path, encoding="utf-8")
|
|
|
|
lexer = Lexer(input_stream)
|
|
stream = CommonTokenStream(lexer)
|
|
parser = Parser(stream)
|
|
tree = parser.root()
|
|
|
|
walker = ParseTreeWalker()
|
|
|
|
sys.path.append(os.path.join(behaviour_lib_path, "cond"))
|
|
sys.path.append(os.path.join(behaviour_lib_path, "act"))
|
|
|
|
ptml = ptmlTranslator(scene, behaviour_lib_path) # listener mode
|
|
walker.walk(ptml, tree)
|
|
|
|
return ptml.bt_root
|
|
|
|
def parse_indentation(text):
|
|
tree = {}
|
|
stack = [(-1, tree)] # 使用栈来跟踪节点层级和父节点
|
|
|
|
for line in text.splitlines():
|
|
indent = len(line) - len(line.lstrip())
|
|
content = line.strip()
|
|
|
|
if not content:
|
|
continue # 跳过空行
|
|
|
|
# 找到当前行的父级
|
|
while stack and stack[-1][0] >= indent:
|
|
stack.pop()
|
|
|
|
# 确保栈不为空
|
|
if not stack:
|
|
raise ValueError("缩进错误")
|
|
|
|
# 检查当前行是否已存在于父级中
|
|
parent = stack[-1][1]
|
|
if content not in parent:
|
|
parent[content] = []
|
|
|
|
# 添加新节点
|
|
node = {}
|
|
parent[content].append(node)
|
|
stack.append((indent, node))
|
|
|
|
return tree
|
|
|
|
def format_nested_dict(d, indent=0, outermost=True):
|
|
""" 格式化嵌套字典为特定字符串格式,如果没有子级就不添加大括号 """
|
|
indention = " " * indent # 用空格表示缩进
|
|
formatted_str = ""
|
|
|
|
if (not outermost) and d: # 添加大括号,除非是空字典
|
|
formatted_str += "{\n"
|
|
|
|
for key, value_list in d.items():
|
|
for value in value_list: # 遍历列表中的每个字典
|
|
formatted_str += f"{indention}{' ' if (not outermost) and d else ''}{key}\n"
|
|
|
|
if isinstance(value, dict):
|
|
# 如果值是字典,则递归调用
|
|
formatted_str += format_nested_dict(value, indent + (0 if outermost else 1), False)
|
|
else:
|
|
# 否则,直接添加值
|
|
formatted_str += f"{indention}{' ' * 2}{value}\n"
|
|
|
|
if (not outermost) and d: # 如果不是空字典,才关闭大括号
|
|
formatted_str += indention + "}\n"
|
|
|
|
return formatted_str.strip()
|
|
|
|
def format_trans_to_bracket(file_path: str) -> str:
|
|
"""_summary_
|
|
|
|
Args:
|
|
file_path (str): _description_
|
|
|
|
Raises:
|
|
FileNotFoundError: _description_
|
|
|
|
Returns:
|
|
str: the path tp temp file with '{}' form.
|
|
"""
|
|
import autopep8
|
|
|
|
if not os.path.exists(file_path):
|
|
raise FileNotFoundError("Given a fault ptml path: {}".format(file_path))
|
|
|
|
with open(file_path, 'r') as file:
|
|
f = file.read().strip()
|
|
if "{" in f:
|
|
return file_path
|
|
|
|
parsed_tree = parse_indentation(f)
|
|
|
|
formatted_output = format_nested_dict(parsed_tree)
|
|
|
|
# def counter_(input: str) -> int:
|
|
# length = 0
|
|
# for i in range(len(input)):
|
|
# if input[i] == ' ':
|
|
# length += 1
|
|
# else:
|
|
# if length % 4 != 0:
|
|
# raise TabError('Tab length in ptml file should be 4.')
|
|
# return length
|
|
#
|
|
# with open(file_path, 'r') as file:
|
|
# ptml_new = ''
|
|
# ptml_tab = file.readlines()
|
|
#
|
|
# level = 0
|
|
# for i in ptml_tab:
|
|
#
|
|
# if i.startswith('//'):
|
|
# continue
|
|
#
|
|
# new_level = counter_(i) // 4
|
|
# if new_level == level:
|
|
# ptml_new += i
|
|
# elif new_level > level:
|
|
# ptml_new += '{\n' + i
|
|
# level += 1
|
|
# elif new_level < level:
|
|
# ptml_new += '\n}' + i
|
|
# level -= 1
|
|
# for i in range(level):
|
|
# ptml_new += '}'
|
|
|
|
file_name = os.path.basename(file_path).split(".")[0]
|
|
dir_path = os.path.dirname(file_path)
|
|
# import re
|
|
# new_path = re.sub('\\\[a-zA-Z0-9_]*\.ptml', '/bracket_ptml.ptml', file_path)
|
|
new_path = os.path.join(dir_path,file_name+"_bracket.ptml")
|
|
with open(new_path, 'w') as file:
|
|
file.write(formatted_output)
|
|
return new_path
|
|
|
|
# format_trans_to_bracket('C:\\Users\\Estrella\\Desktop\\RoboWaiter\\robowaiter\\behavior_tree\\ptml\\test\\Default.ptml')
|
|
|
|
if __name__ == '__main__':
|
|
# 示例文本
|
|
text = """
|
|
selector
|
|
sequence
|
|
cond Chatting()
|
|
act DealChat()
|
|
sequence
|
|
cond HasSubTask()
|
|
sequence
|
|
act SubTaskPlaceHolder()
|
|
sequence
|
|
cond FocusingCustomer()
|
|
act ServeCustomer()
|
|
sequence
|
|
cond NewCustomer()
|
|
selector
|
|
cond At(Robot,Bar)
|
|
act MoveTo(Bar)
|
|
act GreetCustomer()
|
|
sequence
|
|
cond AnomalyDetected()
|
|
act ResolveAnomaly()
|
|
"""
|
|
|
|
parsed_tree = parse_indentation(text)
|
|
print(parsed_tree)
|
|
|
|
formatted_output = format_nested_dict(parsed_tree)
|
|
print(formatted_output) |