AW: [stringtemplate-interest] Problems with List and Hashes revisited
Dreyer Ulf (CR/APA3)
Ulf.Dreyer at de.bosch.com
Tue May 30 06:10:48 PDT 2006
Hello Kunle
> From: stringtemplate-interest-bounces at antlr.org
> From: Kunle Odutola
> Betreff: Re: [stringtemplate-interest] Problems with List and
> Hashes revisited
>
> As Ter mentioned in Jeremy's thread on the list, ST# (and ST)
> enumerates any
> enumerable attributes by default.
Yeah I read that - now I have made some tests to see what meets
my requirements.
Some simple Questions:
(1)
Am I right in thinking that templates without formal arguments
SomeTemplate() ::= << Output=$it.something$ >>
can only be invoked as $SomeData:SomeTemplate()$
never as $SomeTemplate(SomeData)$
(I get: "template anotherOutput must have exactly one formal
arg in template context [..Context..]")
(2) Should this template work? (It always crashes on me because
of stack-overflow)
RecursiveOut(Daten) ::= << $Daten:RecursiveOut();separator=","$ >>
As both classes in my data-structure (AttributeHash and AttributeList)
are IEnumerable it should strip away one layer at a time, shouldn't it?
> > What do I have to do so that ST# can deal with
> > <DataStruct>:subtemplate()
> > whether DataStruct is a single value (or aggregate)
> > or a List?
>
> Nothing. If an attribute is enumerable it will be treated as
> such. Else it
> won't be.
Ok I got it!
> If you don't want an enumerable attribute to be treated as enumerable,
> define a formal parameter and use the alternate syntax:
> subtemplate(<parameterName>=<DataStruct>)
I can't do that because I don't necessarily know in advance if an
attribute will be single or multi-valued.
Therefore it has to be the Data:Template() Syntax.
[Very clear comparison application include/application
thank you very much Kunle!! ]
> > Sample xml-file:
> >
> > <?xml version="1.0"?>
> > <root>
> > <DataBlock1>
> > <DataA>1_DataA</DataA>
> > <DataB>1_DataB</DataB>
> > <DataC>
> > <SubC1>1_SubC1Content1</SubC1>
> > <SubC1>1_SubC1Content2</SubC1>
> > <SubC2>1_SubC2Content</SubC2>
> > </DataC>
> > </DataBlock1>
> > <DataBlock1>
> > <DataA>2_DataA</DataA>
> > <DataB>2_DataB</DataB>
> > <DataC>
> > <SubC1>2_SubC1Content1</SubC1>
> > <SubC1>2_SubC1Content2</SubC1>
> > <SubC2>2_SubC2Content</SubC2>
> > </DataC>
> > </DataBlock1>
> > <DataBlock2>
> > <ItemB>ItemBContent</ItemB>
> > </DataBlock2>
> > </root>
>
> So you have a toplevel Hashtable that contains ("key,
> [elem1,...elemN]"
> means entry has key "key" and is a list of elem1...elemN):
> DataBlock1, [DataA, DataB, DataC]
> DataBlock2, ItemB
> where ItemB is not a list right?
First: the "Is ItemB a list (of one element) or not" changes
very often during my experiments.
CURRENTLY: If (ItemB is a String) there is NO list
If (ItemB is a Hash) there is a list of one element
The above XML yields the following structure (not complete)
{} = empty hash, {(),()} Hash with two elements
("Key",ANYTHING) = Hash key-value pair
[] = empty list
Top Level Hash (nameless) =
{ ("DataBlock1",[ NamelessHash{ ("DataA", String:1_DataA )
("DataB", String:1_DataB )
("DataC", NamelessHash*SNIP
too long* )},
NamelessHash{ ("DataA", String:2_DataA )
("DataB", String:2_DataB )
("DataC", NamelessHash*SNIP
too long* )}
])
("DataBlock2",[ NamelessHash{("ItemB",String:ItemBContent)} ])
}
> I presume that the extra DataBlock1 entry is a typo
> right?. If not, then
> DataBlock1 is as below:
> DataBlock1, [DataA, DataB, DataC, DataA, DataB, DataC]
> }}
>
> Looking at DataBlock1's value
> DataA is [1_DataA] (or [1_DataA, 2_DataA] if both
> DataBlock1 entries are
> valid - same for others)
> DataB is [1_DataB]
> DataC is [SubC1, SubC1, SubC3] where each SubC is a
> Hashtable right (or is
> it *could be* a hashtable)?
>
> > Sample TemplateGroup:
> >
> > group behaviourDemo;
> >
> > subsubTemplate(Data) ::= <<
> > Input is : $Data$
> > SubC1 is '$Data.SubC1$'
> > SubC2 is '$Data.SubC2$'
> >
> > >>
> >
> > subsubTemplateB() ::= <<
> > Input is : $it$
> > SubC1 is '$it.SubC1$'
> > SubC2 is '$it.SubC2$'
> >
> > >>
> >
> > subTemplate() ::= <<
> > ------------------------------------------------------
> > A=$it.DataA$
> > B=$it.DataB$
> >
> > // both blocks SHOULD return the same:
> >
> > subsubTemplate(it.DataC):
> > $subsubTemplate(it.DataC)$
> > ----------------------------
> > it.DataC:subsubTemplate():
> > $it.DataC:subsubTemplate()$
> > ------------------------------------------------------
> >
> > >>
>
> Nope. As I mentioned above, they have different semantics.
>
> $subsubTemplate(it.DataC)$ ==> invokes 'subsubTemplate'
> setting it's only
> parameter to '$it.DataC$'
>
> $it.DataC:subsubTemplate()$ ==>
> IF '$it.DataC$' IS enumerable
> FOREACH element in '$it.DataC$'
> invokes
> 'subsubTemplate' setting it's
> only parameter to '$element$'
> ELSE
> invokes 'subsubTemplate'
> setting it's
> only parameter to '$it.DataC$'
>
> >
> > rootTemplate(DataBlock1,DataBlock2) ::= <<
> > BEGIN (rootTemplate)
> > Applying the subtemplate to DataBlock1:
> >
> > $DataBlock1:subTemplate()$
> > ======================================================
> > Accessing part of DataBlock1 directly (multi-valued):
> > DataBlock1.DataA = $DataBlock1.DataA$
> >
> > Accessing part of DataBlock2 directly (single-valued):
> > DataBlock2.ItemB = $DataBlock2.ItemB$
> > END (rootTemplate)
> > >>
> >
> > To archive my goal I have written a data-structure consisting
> > of ArrayLists and Hashmaps (alternating).
> > A hash being the root and containing Lists(of hashes) for
> multi-valued
> > attributes or attributes (Strings) for single-values.
> >
> > DataBlock2.ItemB = $DataBlock2.ItemB$ from the rootTemplate
> always works.
> (good!)
> >
> > DataBlock1.DataA = $DataBlock1.DataA$ does not normally
> work because the
> "answer"
> > would be multi-valued.
> > I got this to work too by writing a List which implements a
> this[string]
> accessor that
> > iterates over the list and constructs a new list from the matching
> attributes of the
> > hashmaps in the list. (Essentially skipping one "layer" of the data
> structure)
> > @Kunle: This is how I solved the last problem I mailed you about.
> > In the example my list implementation returns
> [1_DataA,2_DataA] if called
> as
> > myList_DataBlock1["DataA"] (Not necessarily stings but
> whatever the hashes
> contain at key "DataA").
>
> Since they are indexed by (and accessed by) a string key (not
> uniquely I now
> understand), why not just use an IDictionary?. The separate
> entries for keys
> like "DataA" can then held in a list.
> If preserving insertion order is important, you can develop a
> specialized
> IDictionary. ST#'s HashList may provide pointers there.
>
> > One last problem which I feel is related to the " question regarding
> specialcasingof IList"
> > previously on the mailinlist.
> > The call to the subsubTemplate!
> >
> > As you see from the code I have given two implementations.
> > The one with the named parameter works IF (and only if) I call it
> > $subsubTemplate(it.DataC)$
> > My preferred version of
> > $it.DataC:subsubTemplate()$
> > does NOT work.
>
> It does work as advertised. If the attribute is multi-valued (i.e.
> enumerable), it will be treated as such. Using explicit
> formal parameters
> affords you some control over the process. You may choose to
> never enumerate
> by only accessing properties directly for instance.
>
> Incidentally special-casing of IList simply means that IList
> is *always*
> regarded as enumerable.
>
> Given two IList instances list1 = {1,2,3} and list2 = {"a", "b", "c"}:
>
> st.SetAttribute("data", list1);
> st.SetAttribute("data", list2);
>
> would result in:
> $data$ -> [1, 2, 3, "a", "b", "c"]
>
> If list1 and list2 were not ILists, you would get:
> $data$ -> [list1, list2].
>
>
> > Neither does the subsubTemplateB in any version
>
> It can't. The template application logic controls the
> enumeration in this
> case not the template.
>
> > From the output below one can see that $it.DataC:subsubTemplate()$
> > gives a list to subsubTemplate() when it SHOULD be a Hash containing
> > a list (of 2 items) and a single value.
> > Any idea why this is the case?
>
> IDictionary objects are enumerable so that is the expected
> behaviour. You
> should pass your hashtable as a formal parameter if you don't want it
> enumerated by the template application logic.
>
>
> Good luck.
>
>
> Kunle
> _______________________________________________
> stringtemplate-interest mailing list
> stringtemplate-interest at antlr.org
> http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest
>
>
More information about the stringtemplate-interest
mailing list