How can I / Is it possible to warn the user for unused variables within a logic rule in a Prolog-like DSL developer through Xtext? - validation

I'm new here but I hope someone can help me.
I'm developing a Prolog-like DSL for an university project.
This is a simplified grammar that I use to expertiment stuff:
grammar it.unibo.gciatto.Garbage hidden (SL_COMMENT, ML_COMMENT, WS, ANY_OTHER)
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate garbage "http://www.unibo.it/gciatto/Garbage"
PTheory returns Theory
: (kb+=PExpression '.')*
;
PExpression returns Expression
: PRule
;
PRule returns Expression
: PConjunction ({ Expression.left=current } name=':-' right=PConjunction)?
;
PConjunction returns Expression
: PExpression0 ({ Expression.left=current } name=',' right=PConjunction)?
;
PExpression0 returns Expression
: PTerm
| '(' PExpression ')'
;
PTerm returns Term
: PStruct
| PVariable
| PNumber
;
PVariable returns Variable
: { AnonymousVariable } name='_'
| name=VARIABLE
;
PNumber returns Number
: value=INT
;
PStruct returns Struct
: name=ATOM '(' arg+=PExpression0 (',' arg+=PExpression0)* ')'
| PAtom
;
PAtom returns Atom
: name=ATOM
| { AtomString } name=STRING
;
terminal fragment CHARSEQ : ('a'..'z' | 'A' .. 'Z' | '0'..'9' | '_')*;
terminal ATOM : ('a'..'z') CHARSEQ;
terminal VARIABLE : ('A'..'Z') CHARSEQ;
terminal INT returns ecore::EInt: ('0'..'9')+;
terminal STRING :
'"' ( '\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\'|'"') )* '"' |
"'" ( '\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\'|"'") )* "'"
;
terminal ML_COMMENT : '/*' -> '*/';
terminal SL_COMMENT : '//' !('\n'|'\r')* ('\r'? '\n')?;
terminal WS : (' '|'\t'|'\r'|'\n')+;
terminal ANY_OTHER: .;
When validating I'd love to search for unused variables in rules definition and suggest the user to use anonymous variable instead. Once I've understood the mechanism I may consider similar validation rules.
I know Xtext has a built-in scoping mechanism and I've been able to use it in different situations, but as you know, any IScopeProvider provides a scope for a given EReference (am I right?) and, as you can see, my grammar has no cross-references. The reason for that is simple: in Prolog a variable "definition" and its "references" are syntactically the same, so no context-free parser able to distinguish the two contexts can be generated (I'm pretty sure, even without a formal proof).
However, I think the validation algorithm is quite simple:
"while navigating the AST, collect any variable within an ad-hoc data structure and the count occurrences" or something smarter than that
Now the real question is: can I someway (re)use any part of the Xtext scoping framework, and if yes how? Or should I build a simple scoping library by my self?
Sorry for the long question and bad english, I hope I was exhaustive.
Thank you for reading.

The Xtext validation framework can reuse your scope provider instance easily, and can write validation rules. A sample for the validator is already generated for the Xtext grammar, you have to extend it with your specific validation case like follows:
public class GarbageLanguageJavaValidator extends AbstractGarbageLanguageJavaValidator {
#Inject
GarbageLanguageScopeProvider scopeProvider;
//Validation rule for theories. For any other element, change the input parameter
#Check
public void checkTheory(Theory theory) {
//here, you can simply reuse the injected scope provider
scopeProvider.getAllReferencesInTheory();
//in case of problems, report errors using the inherited error/warning methods
}
}
The created validation rules are automatically registered and executed (see also the Xtext documentation for details about validation).

I actually solved the problem a few days after I posted the question and then I was too busy to post the solution. Here it comes (for a more detailed description of both the problem and the solution, you are free to read the essay I wrote: RespectX - section 4.5 ).
I created my own IQualifiedNameProvider, called IPrologSimpleNameProvider, which simply returns the 'name' feature.
Then I created my own IContextualScopeProvider, which doesn't extend IScopeProvider. It exposes the following methods:
getContext given any AST node, it returns the root of the current context, i.e.
the EObject whose eContainer is instance of Theory and containing the
input node within its sub-tree.
getScope returns an IScope for the context of the input node.
getFilteredScope applies a type-filter to a getScope invocation (e.g. it makes
it easy to create a scope containing only Variables).
getFilteredScope filters a getScope invocation using a predicate.
Of course, the IContextualScopeProvider implementation uses an IPrologSimpleNameProvider implementation so, now, the validation rule quite simple to realize:
Given a variable, it uses the getScope method which returns an IScope containing all the variables within that context
It counts how many variables within the IScope are named after the current one
If they are lesser than 2 a warning is found.
I really hope I explained ^^"

Related

How to embed a syntax object in another in TextMate language definitions, tmLanguage

I am trying to support Clojure's ignore text form, #_, (a sort of comment) in VS Code, which uses tmLanguage for its grammar definitions. Since it is common to disable a block of code using #_, I want the disabled block of code to retain its syntax highlighting and just italicize it, indicating its status.
But my lack of skills using tmLanguage seems to stop me. This is one of the failing attempts (a snippet of the cson):
'comment-constants':
'begin': '#_\\s*(?=\'?#?[^\\s\',"\\(\\)\\[\\]\\{\\}]+)'
'beginCaptures':
'0':
'name': 'punctuation.definition.comment.begin.clojure'
'end': '(?=[\\s\',"\\(\\)\\[\\]\\{\\}])'
'name': 'meta.comment-expression.clojure'
'patterns':
[
{
'include': '#constants'
}
]
With constants defining some Clojure constants objects, like keyword:
'keyword':
'match': '(?<=(\\s|\\(|\\[|\\{)):[\\w\\#\\.\\-\\_\\:\\+\\=\\>\\<\\/\\!\\?\\*]+(?=(\\s|\\)|\\]|\\}|\\,))'
'name': 'constant.keyword.clojure'
What I want to happen is that the constants definitions will be used ”inside” the comment. For keywords I have this (failing) spec:
it "tokenizes keywords", ->
tests =
"meta.expression.clojure": ["(:foo)"]
"meta.map.clojure": ["{:foo}"]
"meta.vector.clojure": ["[:foo]"]
"meta.quoted-expression.clojure": ["'(:foo)", "`(:foo)"]
"meta.comment-expression.clojure": ["#_:foo"]
for metaScope, lines of tests
for line in lines
{tokens} = grammar.tokenizeLine line
expect(tokens[1]).toEqual value: ":foo", scopes: ["source.clojure", metaScope, "constant.keyword.clojure"]
(The last test in that list). It fails with this message:
Expected
{ value : ':foo',
scopes : [ 'source.clojure', 'meta.comment-expression.clojure' ] }
to equal
{ value : ':foo',
scopes : [ 'source.clojure', 'meta.comment-expression.clojure', 'constant.keyword.clojure' ] }.
Meaning I am not getting the constant.keyword.clojure scope in place and thus no keyword-colorization for me. 😢
Anyone knows how to do this?
Your keyword regex starts with a lookbehind that requires that there must be a single whitespace, (, [ or { character before keywords. The _ from #_ doesn't meet that requirement.
(?<=(\\s|\\(|\\[|\\{))
You could simply add _ to the list of allowed characters:
(?<=(\\s|\\(|\\[|\\{|_))
Note that this still wouldn't work as-is for your "#_:foo" test case because of the similar lookahead at the end. You could possibly allow $ there, make the match optional, or change the test case.

How do you define propertychain in owlready

Recently, I started to study owlready, and faced with much problem.
I defined a PropertyChain as follows.
class friend(Person >> Person, SymmetricProperty):
pass
class potentialFriend(Person >> Person):
# potentialFriend := friend o friend
equivalent_to = PropertyChain([friend, friend])
I tried to get person.potentialFriend.indirect(), but failed. I read the source codes, since the doc on web is too simple, and found that PropertyChain works like a list, I thought it returned a Property. How do I compliment what I want?
How do you use PropertyChain? Is there some concrete examples.
PS: The source codes(.py files) indent with only two whitespaces, :o!
You can use:
P.property_chain.append(PropertyChain([P1, P2]))
...where P1 and P2 are already created ObjectProperties. In your case, P is potentialFriend. P1 and P2 are both friend.
For the reasoner to infer the property chain, don't forget to set its parameter infer_property_values to True :
sync_reasoner(infer_property_values = True)
After that, the reasoner manages to infer the property and you can get it with person.potentialFriend.indirect().

Sitecore item multilistfield XPATH builder

I'm trying to count with XPATH Builder in Sitecore, the number of items which have more than 5 values in a multilist field.
I cannot count the number of "|" from raw values, so I can say I am stuck.
Any info will be helpful.
Thank you.
It's been a long time since I used XPath in Sitecore - so I may have forgotten something important - but:
Sadly, I don't think this is possible. XPath Builder doesn't really run proper XPath. It understands a subset of things that would evaluate correctly in a full XPath parser.
One of the things it can't do (on the v8-initial-release instance I have to hand) is be able to process XPath that returns things that are not Sitecore Items. A query like count(/sitecore/content/*) should return a number - but if you try to run that using either the Sitecore Query syntax, or the XPath syntax options you get an error:
If you could run such a query, then your answer would be based on an expression like this, to perform the count of GUIDs referenced by a specific field:
string-length( translate(/yourNodePath/#yourFieldName, "abcdefg1234567890{}-", "") ) + 1
(Typed from memory, as I can't run a test - so may not be entirely correct)
The translate() function replaces any character in the first string with the relevant character in the second. Hence (if I've typed it correctly) that expression should remove all your GUIDs and just leave the pipe-separator characters. Hence one plus the length of the remaining string is your answer for each Item you need to process.
But, as I say, I don't think you can actually run that from Query Builder...
These days, people tend to use Sitecore PowerShell Extensions to write ad-hoc queries like this. It's much more flexible and powerful - so if you can use that, I'd recommend it.
Edited to add: This question got a bit stuck in my head - so if you are able to use PowerShell, here's how you might do it:
Assuming you have declared where you're searching, what MultiList field you're querying, and what number of selections Items must exceed:
$root = "/sitecore/content/Root"
$field = "MultiListField"
$targetNumber = 3
then the "easy to read" code might look like this:
foreach($item in Get-ChildItem $root)
{
$currentField = Get-ItemField $item -ReturnType Field -Name $field
if($currentField)
{
$count = $currentField.Value.Split('|').Count
if($count -gt $targetNumber)
{
$item.Paths.Path
}
}
}
It iterates the children of the root item you specified, and gets the contents of your field. If that field name had a value, it then splits that into GUIDs and counts them. If the result of that count is greater than your threshold it returns the item's URI.
You can get the same answer out of a (harder to read) one-liner, which would look something like:
Get-ChildItem $root | Select-Object Paths, #{ Name="FieldCount"; Expression={ Get-ItemField $_ -ReturnType Field -Name $field | % { $_.Value.Split('|').Count } } } | Where-Object { $_.FieldCount -gt $targetNumber } | % { $_.Paths.Path }
(Not sure if that's the best way to write that - I'm no expert at PowerShell syntax - but it gives the same results as far as I can see)

urlrewriting tuckey using Tuckey

My project (we have Spring 3) needs to rewrite URLs from the form
localhost:8888/testing/test.htm?param1=val1&paramN=valN
to
localhost:8888/nottestinganymore/test.htm?param1=val1&paramN=valN
My current rule looks like:
<from>^/testing/(.*/)?([a-z0-9]*.htm.*)$</from>
<to type="passthrough">/nottestinganymore/$2</to>
But my query parameters are being doubled, so I am getting param1=val1,val1 and paramN=valN,valN...please help! This stuff is a huge pain.
To edit/add, we have use-query-string=true on the project and I doubt I can change that.
The regular expression needs some tweaking. Tuckey uses the java regular expression engine unless specified otherwise. Hence the best way to deal with this is to write a small test case that will confirm if your regular expression is correct. For e.g. a slightly tweaked example of your regular expression with a test case is below.
#Test public void testRegularExpression()
{
String regexp = "/testing/(.*)([a-z0-9]*.htm.*)$";
String url = "localhost:8888/testing/test.htm?param1=val1&paramN=valN";
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(url);
if (matcher.find())
{
System.out.println("$1 : " + matcher.group(1) );
System.out.println("$2 : " + matcher.group(2) );
}
}
The above will print the output as follows :
$1 : test
$2 : .htm?param1=val1&paramN=valN
You can modify the expression now to see what "groups" you want to extract from URL and then form the target URL.

Generate HTML documentation for a FreeMarker FTL library

I've a FreeMarker library that I want to ship with my product, and I'm looking for a way to generate a HTML documentation for it based on the comments in the FTL file (in a Javadoc fashion).
For example, a typical function in my library is written like:
<#--
MyMacro: Does stuff with param1 and param2.
- param1: The first param, mandatory.
- param2: The second param, 42 if not specified.
-->
<#macro MyMacro param1 param2=42>
...
</#macro>
I didn't find anything on that subject, probably because there is no standard way of writing comments in FreeMarker (Such as #param or #returns in Javadoc).
I don't mind rolling my own solution for that, but I'm keen on using an existing system like Doxia (since I'm using Maven to build the project) or Doxygen maybe, instead of writing something from scratch.
Ideally I'd like to write the comment parsing code only, and rely on something else to detect the macros and generate the doc structure.
I'm open to changing the format of my comments if that helps.
In case you decide to write your own doc generator or to write a FTL-specific front-end for an existing document generator, you can reuse some of FreeMarker's parsing infrastructure:
You can use Template.getRootTreeNode() in order to retrieve the template's top level AST node. Because macros and the responding comments should be direct children of the this top level node (IIRC), iterating over its children and casting them to the right AST node subclass should give you almost everything you need with respect to FTL syntax. To illustrate the approach I hacked together a little "demo" (cfg is a normal FreeMarker Configuration object):
Template t = cfg.getTemplate("foo.ftl");
TemplateElement te = t.getRootTreeNode();
Enumeration e = te.children();
while(e.hasMoreElements()) {
Object child = e.nextElement();
if(child instanceof Comment) {
Comment comment = (Comment)child;
System.out.println("COMMENT: " + comment.getText());
} else if(child instanceof Macro) {
Macro macro = (Macro)child;
System.out.println("MACRO: " + macro.getName());
for(String argumentName : macro.getArgumentNames()) {
System.out.println("- PARAM: " + argumentName);
}
}
}
produces for your given example macro:
COMMENT:
MyMacro: Does stuff with param1 and param2.
- param1: The first param, mandatory.
- param2: The second param, 42 if not specified.
MACRO: MyMacro
- PARAM: param1
- PARAM: param2
How you parse the comment is then up to you ;-)
Update: Found something called ftldoc in my backups and uploaded it to GitHub. Maybe this is what you are looking for...

Resources