Create replacer's pattern tutorial:
For this example term "diff_2vv1" will be created with wolfram input and cpp output like so: Input |
Output |
"2vv1(3, U(t-1.1))" |
"N/3*(source[delay][idx + 2 * Block0StrideX * Block%dCELLSIZE + 0]*source[delay][idx + 1 * Block0StrideX * Block0CELLSIZE + 0]-source[delay][idx - 1 * Block0StrideX * Block0CELLSIZE + 0]*source[delay][idx - 2 * Block0StrideX * Block0CELLSIZE + 0])" at central, "0" at border |
where blockNumber, var_index is params and can be chenged (with set_* methods of Equation.replacer.cpp.editor)
Adding lex pattern:
1) In order to create new term open lex editor page:

pic 0
2) In loaded page click "dialect table" button. Table with default dialect (wolfram) will be shown. Click "Add" button for adding new pattern. If You only need to edit old pattern it can be done directily with click at according row field (don't forget about "save" button or changes will be lost). If You don't need add new term go to step 5.

pic 1
3) In the opened subtable some default entry will appear. Next attributes must be chenged:
- Id -- must be unique so change it default value. Used for storage in db.
- term_name - unique, it used trough all translator's parse steps from lexical to
replacer levels. If this name contain "diff" word, some data will be available in node
during replacer (like dim , blockNumber , var_idx , diffType see more below).
- template -- this is re or txt template (depending on pattern_type value). For current example "2vv1\((?P
You can see that this patterns themself is complex, consisting of other patterns. The lex alalyzer will replace all of them recursively to finally get:
re_pattern = "2vv1\((?P\d+),(?P [A-Z](\([t](-(?P (?:\d+\.\d+|\d+)))?\))?)\)"
If You put it into re.search like:
res = re.search(re_pattern, "2vv1(3,U(t-1.1))")
then .SRE_Match object will be returned with res.group("number") == 3 , res.group("val") == U , ``res.group("delay") == 1.1.
- grammar_type -- this is "('a',)" and this means that lex template represent whole pattern (not part of it, like "('br',)" ).
4) After this done, add new term by clicking "add" button again, then save by "save" ones.
Adding cpp replacer:
5) Click at newly creaded row and move to the codemirror div. This can give You ability to write node replacer i.e. class, whose instance will be used for fill cpp data of node in parsed tree which represent found lex pattern in sentense. For example if sentence looks like "U'=2vv1(3, U(t-1.1))" this will be transformed to tree, whose node has id="diff_2vv1".NOTE: if other objects exist, this class must be last in codemirror editor.
I copy node replacer from other term (source), then rename it to "Diff_2v11" and rename it id attribute same as pattern id (required!):

pic 2
Actual replaced value is that, what will be returned by "print_out" method.
def print_out(self):
return(self.value)
Before that "get_node_data" method will be used in order to extract some data.
First it get all data from data from term itself (which in Our example is "number"):
...
# get found re pattern:
re_pattern = self.net.get_term_pattern(node)
# extract pattern data:
N = re_pattern.group("number")
Next it convert some data from re_pattern to cpp, using standart methods from Base class (in Our case transform U to 0 ):
self.set_var_index(node)
Then, because diff word exist in our term_id (which is diff_2vv1 ), it have access to some params, that user was specified in methods like ( Equation.replacer.cpp.editor.set_dim ) (they was specified in some particular part of hybriddomain ).
So, We can use that data for Our output:
# extract data taken with set_ methods:
dim = self.params["dim"]
blockNumber = self.params["blockNumber"]
var_idx = self.params["unknownVarIndex"]
diffMethod = self.params["diffMethod"]
Delays is special matter. It take delay data from node, and save it for posprocessor with self.set_delay method (store it into node.output.cpp.global_data ). Then in out string word delay must be included, where it needed. For example source[delay] will be transformed to source[n] where n is calculated by env.equation.data.terms.output.cpp.postproc.delay_postproc for all term in sentence (or even in system):
# FOR delays:
delay_data = self.set_delay(node)
# add delays data for postproc:
if delay_data is not None:
# node.output.cpp.global_data = data
self.net.set_output_data(node, 'delay_data', delay_data)
# END FOR
The last part is out value itself:
if diffMethod == "common":
bn = blockNumber
vi = var_idx
value = "(source[delay][idx + 2 * Block%dStrideX * Block%dCELLSIZE + %d]" %(bn, bn, vi)
value += "*source[delay][idx + 1 * Block%dStrideX * Block%dCELLSIZE + %d]" %(bn, bn, vi)
value += "-source[delay][idx - 1 * Block%dStrideX * Block%dCELLSIZE + %d]" %(bn, bn, vi)
value += "*source[delay][idx - 2 * Block%dStrideX * Block%dCELLSIZE + %d])" %(bn, bn, vi)
value = str(int(N)/3) + "*"+value
else:
value = "0"
# get found string:
self.value = value
Now We ready for testing. Go to net page:

pic 3
Write test sent in editor window:

pic 4
And click "parse" button. But this do nothing. In order to understend reason of this switch to terminal window and find lex_out:

pic 5
That list represent pre-syntax parse sent, that is output of lexical analyzer. Because Our entry has "('a',)" as "grammar_type" value, We expect it to be as output of lex analyzer. But instead We have several other terms, that apparently went from other terms. Reason for that behavior is that order of Our term is less then order of it containments, that is terms, that included in our term template (probably "var" term, as it part of our template (which is "2vv1\((?P
You can see that our pattern priority is much less then ...
To fix that go back to lex table and change pattern type from "('re',)" to "('re', 0.1)" (don't forget restart server after that):

pic 6
Now all work with order is ok and lex_out value is what expected:
