我正在实施一个简单的DSL。我有以下输入字符串:
std::vector<int> a;
..
a.resize(t);
..
cin >> a[i]
我有以下数据:
txt = 'Hi, my name is <<name>>. I was born in <<city>>.'
我需要实现以下功能:
{
'name': 'John',
'city': 'Paris',
'more': 'xxx',
'data': 'yyy',
...
}
我得到的地方:
def tokenize(txt):
...
return fmt, vars
也就是说,fmt = 'Hi, my name is {name}. I was born in {city}.'
vars = ['name', 'city']
可以传递给str.format()函数,而fmt
是检测到的标记的列表(这样我就可以在数据中执行查找,这可以是比我描述的更复杂,因为它可以分成几个名称空间)
在此之后,处理格式很简单:
vars
def expand(fmt, vars, data):
params = get_params(vars, data)
return fmt.format(params)
正在执行简单的数据查找,并返回类似的内容:
get_params
我的问题是:
如何实现tokenize?如果知道delitimers是params = {
'name': 'John',
'city': 'Paris',
}
和<<
,我怎样才能检测到令牌?我应该去正规用途,还是有更容易的路径?
这类似于>>
,甚至pystache
本身正在做的事情,但我想要一个轻量级的实现。在这个阶段,稳健性并不是非常关键。
答案 0 :(得分:2)
是的,这是regexp的完美目标。找到开始/结束引号,用大括号替换它们,并将符号名称提取到列表中。您对法律符号有完整的描述吗?您需要进行搜索,例如
/\<\<([a-zA-Z]+[a-zA-Z0-9_]*)\>\>/
对于经典变量名称(请注意,这不包括前导下划线)。你是否熟悉regexp从这里接受它?
答案 1 :(得分:1)
import re
def tokenize(text):
found_variables = []
def replace_and_capture(match):
found_variables.append(match.group(1))
return "{{{}}}".format(match.group(1))
return re.sub(r'<<([^>]+)>>', replace_and_capture, text), found_variables
fmt, vars = tokenize('Hi, my name is <<name>>. I was born in <<city>>.')
print(fmt)
print(vars)
# Output:
# Hi, my name is {name}. I was born in {city}.
# ['name', 'city']