Check if entered text is valid in Xtext - xtext

lets say we have some grammar like this.
Model:
greeting+=Greeting*;
Greeting:
'Hello' name=ID '!';
I would like to check whether the text written text in name is a valid text.
All the valid words are saved in an array.
Also the array should be filled with words from a given file.
So is it possible to check this at runtime and maybe also use this words as suggestions.
Thanks

For this purpose you can use a validator.
A simple video tutorial about it can be found here
In your case the function in the validator could look like this:
public static val INVALID_NAME = "greeting_InvalidName"
#Check
def nameIsValid(Greeting grt) {
val name = grt.getName() //or just grt.Name
val validNames = NewArrayList
//add all valid names to this list
if (!validNames.contains(name)) {
val errorMsg = "Name is not valid"
error(errorMsg, GreetingsPackage.eINSTANCE.Greeting_name, INVALID_NAME)
}
}
You might have to replace the "GreetingsPackage" if your DSL isn't named Greetings.
The static String passed to the error-method serves for identification of the error. This gets important when you want to implement Quickfixes which is the second thing you have asked for as they provide the possibility to give the programmer a few ideas how to actually fix this particular problem.
Because I don't have any experience with implementing quickfixes myself I can just give you this as a reference.

Related

Which settings should be used for TokensregexNER

When I try regexner it works as expected with the following settings and data;
props.setProperty("annotators", "tokenize, cleanxml, ssplit, pos, lemma, regexner");
Bachelor of Laws DEGREE
Bachelor of (Arts|Laws|Science|Engineering|Divinity) DEGREE
What I would like to do is that using TokenRegex. For example
Bachelor of Laws DEGREE
Bachelor of ([{tag:NNS}] [{tag:NNP}]) DEGREE
I read that to do this, I should use TokensregexNERAnnotator.
I tried to use it as follows, but it did not work.
Pipeline.addAnnotator(new TokensRegexNERAnnotator("expressions.txt", true));
Or I tried setting annotator in another way,
props.setProperty("annotators", "tokenize, cleanxml, ssplit, pos, lemma, tokenregexner");
props.setProperty("customAnnotatorClass.tokenregexner", "edu.stanford.nlp.pipeline.TokensRegexNERAnnotator");
I tried to different TokenRegex formats but either annotator could not find the expression or I got SyntaxException.
What is the proper way to use TokenRegex (query on tokens with tags) on NER data file ?
BTW I just see a comment in TokensRegexNERAnnotator.java file. Not sure if it is related pos tags does not work with RegexNerAnnotator.
if (entry.tokensRegex != null) {
// TODO: posTagPatterns...
pattern = TokenSequencePattern.compile(env, entry.tokensRegex);
}
First you need to make a TokensRegex rule file (sample_degree.rules). Here is an example:
ner = { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$NamedEntityTagAnnotation" }
{ pattern: (/Bachelor/ /of/ [{tag:NNP}]), action: Annotate($0, ner, "DEGREE") }
To explain the rule a bit, the pattern field is specifying what type of pattern to match. The action field is saying to annotate every token in the overall match (that is what $0 represents), annotate the ner field (note that we specified ner = ... in the rule file as well, and the third parameter is saying set the field to the String "DEGREE").
Then make this .props file (degree_example.props) for the command:
customAnnotatorClass.tokensregex = edu.stanford.nlp.pipeline.TokensRegexAnnotator
tokensregex.rules = sample_degree.rules
annotators = tokenize,ssplit,pos,lemma,ner,tokensregex
Then run this command:
java -Xmx8g edu.stanford.nlp.pipeline.StanfordCoreNLP -props degree_example.props -file sample-degree-sentence.txt -outputFormat text
You should see that the three tokens you wanted tagged as "DEGREE" will be tagged.
I think I will push a change to the code to make tokensregex link to the TokensRegexAnnotator so you won't have to specify it as a custom annotator.
But for now you need to add that line in the .props file.
This example should help in implementing this. Here are some more resources if you want to learn more:
http://nlp.stanford.edu/software/tokensregex.shtml#TokensRegexRules
http://nlp.stanford.edu/nlp/javadoc/javanlp/edu/stanford/nlp/ling/tokensregex/SequenceMatchRules.html
http://nlp.stanford.edu/nlp/javadoc/javanlp/edu/stanford/nlp/ling/tokensregex/types/Expressions.html

Helping getting beginning TryFSharp "Records and option types" Tutorial to work

I just started studying F# today and have begun working my way through the F# tutorials at http://www.tryfsharp.org/Learn/getting-started#data-structures
In the section above three snippets of code are provided to explain records and option types:
type Book =
{ Name: string;
AuthorName: string;
Rating: int option;
ISBN: string }
let unratedEdition =
{ Name = "Expert F#";
AuthorName = "Don Syme, Adam Granicz, Antonio Cisternino";
Rating = None;
ISBN = "1590598504" }
let printRating book =
match book.Rating with
| Some rating ->
printfn "I give this book %d star(s) out of 5!" rating
| None -> printfn "I didn't review this book"
I thought that I would be able to apply the printRating like so
printRating unratedEdition
but I get the following error
stdin(63,13): error FS0001: This expression was expected to have type
FSI_0005.Book
but here has type
FSI_0009.Book
I'm kinda stuck as to what I am doing wrong here. Any obvious reason that I am totally missing?
Glad that you figured out how to solve the problem and continue with the tutorials!
I think the automatic loading and evaluation of code snippets in Try F# is a bit confusing. The problem is that you first evaluate first snippet, which defined Book and unratedEdition. Then, you evaluate second snippet which re-defines Book - now, to F# interactive, this is a different type hiding the previous definition - together with printRating which is a function working on the new version of Book. When you call:
printRating unratedEdition
You are calling printRating which is a function that takes the new Book with a value of the old Book type as an argument (because unratedEdition is defined from an earlier interaction; it does not automatically get updated to the new Book type and the two types are not compatible).
You can understand this if you evaluate the following three snippets one by one:
// Snippet #1: Define first version of the 'Book' type and a value of
// this type named 'unratedEdition'
type Book =
{ Name: string; AuthorName: string; Rating: int option; ISBN: string }
let unratedEdition =
{ Name = "Expert F#"; Rating = None; ISBN = "1590598504";
AuthorName = "Don Syme, Adam Granicz, Antonio Cisternino"; }
// Snippet #2: Now, we re-define the 'Book' type (we could also add/remove
// fields to make it actually different, but even without that, this still
// defines a new type hiding the original one). We also define a function that
// operates on the new 'Book' type
type Book =
{ Name: string; AuthorName: string; Rating: int option; ISBN: string }
let printRating book =
match book.Rating with
| Some rating ->
printfn "I give this book %d star(s) out of 5!" rating
| None -> printfn "I didn't review this book"
// Snippet #3: This will not work, because we are calling function taking new
// 'Book' with old 'Book' as an argument. To make this work, you need to evaluate
// one (or the other) definition of Book, then evaluate 'unratedEdition' and then
// 'printRating' (so that the value and function operate on the same 'Book' type)
printRating unratedEdition
Note that the editor will complain that the above code is not valid, because it defines Book twice, so you can really only get this problem (easily) in Try F# which erases the content of the editor when loading a new snippet
Well I solved my own problem by running all the above code in one shot. i.e. Posting all 3 snippets plus my
printRating unratedEdition
into the REPL together and then hitting RUN. Previously I was using the "load and run" for each individual snippet. I guess it must be some issue with the REPL, or my limited understanding of how a REPL works.
EDIT**
I found myself running into this problem a number of times throughout the tutorial. So, if you have an error, and don't know why, try inserting all the relevant code into the REPL, THEN hit run. This has solved every issue I have run into so far.

Override Grails Error Messages to format Dates and Numbers

I have created a domain with a Double field. When the validation occurs it throws the error message with size value showing the number with commas. Following are the detials
Groovy Class
class Quote {
String content;
Double size;
static constraints = {
content(maxSize:1000, blank:false)
size(min: 0.00D, max:999.99D)
}
}
Value entered "11111", error obtained "Size 11,111 is exceeded the limit". I have added the property key/value pair in messages.properties.
Here, I would like to get the message back without the commas. My main aim is to take the key and format the message returned based on my requirements. I require this as I have other fields that need conversion. For example, a date is validated but when showing the error the Gregorian date needs to be converted to an Islamic date and shown to user.
Does anyone know if I can do something to make this work.
I have tried the solution provided in http://ishanf.tumblr.com/post/434379583/custom-property-editor-for-grails but this did not work.
I have also tried modifying the messages values, but this is not flexible in case of my date issue. Example, for a key value pair, instead of using {2} as a place holder I could use {2, date, mm/dd/yyyy}, but for Islamic dates I want to format and show things differently.
Also, please note I have created a separate key for default date formatting for my application.
Would appreciate the help.
In grails, the return of a constrain is an already translated string.
You can create a taglib to format that, or enhance the
Another option would be custom validators. A custom validator can return false or a key when failing.
For example in your domain class, to vaildate a field:
myDateField validator: {val, obj -> obj.myShinyDateValidatorMethod(val) }
private myShinyDateValidatorMethod() {
if (isNotValidDate(val) {
return [the_message_key, val.formatedAsYouWand]
}
}
and, in your properties file you have to have defined the key:
the_message_key=This date: {3} is not valid
The trick here is that in the return from the validator, first string is the key and the rest are parameters for that key, but grails already uses {0}, {1}, {2} placeholders for className, fieldName and value, and the first parameter that you pass will be used as {3} placeholder.
Hope this helps

How to create a parser which tokenizes a list of words taken from a file?

I am trying to do a syntax text corrector for my compilers' class. The idea is: I have some rules, which are inherent to the language (in my case, Portuguese), like "A valid phrase is SUBJECT VERB ADJECTIVE", as in "Ruby is great".
Ok, so first I have to tokenize the input "Ruby is great". So I have a text file "verbs", with a lot of verbs, one by line. Then I have one text "adjectives", one "pronouns", etc.
I am trying to use Ragel to create a parser, but I don't know how I could do something like:
%%{
machine test;
subject = <open-the-subjects-file-and-accept-each-one-of-them>;
verb = <open-the-verbs-file-and-accept-each-one-of-them>;
adjective = <open-the-adjective-file-and-accept-each-one-of-them>;
main = subject verb adjective # { print "Valid phrase!" } ;
}%%
I looked at ANTLR, Lex/Yacc, Ragel, etc. But couldn't find one that seemed to solve this problem. The only way to do this that I could think of was to preprocess Ragel's input file, so that my program reads the file and writes its contents at the right place. But I don't like this solution either.
Does anyone knows how I could do this? There's no problem if it isn't with Ragel, I just want to solve this problem. I would like to use Ruby or Python, but that's not really necessary either.
Thanks.
If you want to read the files at compile time .. make them be of the format:
subject = \
ruby|\
python|\
c++
then use ragel's 'include' or 'import' statement (I forget which .. must check the manual) to import it.
If you want to check the list of subjects at run time, maybe just make ragel read 3 words, then have an action associated with each word. The action can read the file and lookup if the word is good or not at runtime.
The action reads the text file and compares the word's contents.
%%{
machine test
action startWord {
lastWordStart = p;
}
action checkSubject {
word = input[lastWordStart:p+1]
for possible in open('subjects.txt'):
if possible == word:
fgoto verb
# If we get here do whatever ragel does to go to an error or just raise a python exception
raise Exception("Invalid subject '%s'" % word)
}
action checkVerb { .. exercise for reader .. ;) }
action checkAdjective { .. put adjective checking code here .. }
subject = ws*.(alnum*)>startWord%checkSubject
verb := : ws*.(alnum*)>startWord%checkVerb
adjective := ws*.)alnum*)>startWord%checkAdjective
main := subject;
}%%
With bison I would write the lexer by hand, which lookup the words in the predefined dictionary.

Best way of storing an "array of records" at design-time

I have a set of data that I need to store at design-time to construct the contents of a group of components at run-time.
Something like this:
type
TVulnerabilityData = record
Vulnerability: TVulnerability;
Name: string;
Description: string;
ErrorMessage: string;
end;
What's the best way of storing this data at design-time for later retrieval at run-time? I'll have about 20 records for which I know all the contents of each "record" but I'm stuck on what's the best way of storing the data.
The only semi-elegant idea I've come up with is "construct" each record on the unit's initialization like this:
var
VulnerabilityData: array[Low(TVulnerability)..High(TVulnerability)] of TVulnerabilityData;
....
initialization
VulnerabilityData[0].Vulnerability := vVulnerability1;
VulnerabilityData[0].Name := 'Name of Vulnerability1';
VulnerabilityData[0].Description := 'Description of Vulnerability1';
VulnerabilityData[0].ErrorMessage := 'Error Message of Vulnerability1';
VulnerabilityData[1]......
.....
VulnerabilityData[20]......
Is there a better and/or more elegant solution than this?
Thanks for reading and for any insights you might provide.
You can also declare your array as consts and initialize it...
const
VulnerabilityData: array[Low(TVulnerability)..High(TVulnerability)] of TVulnerabilityData =
(
(Vulnerability : vVulnerability1; Name : Name1; Description : Description1; ErrorMessage : ErrorMessage1),
(Vulnerability : vVulnerability2; Name : Name2; Description : Description2; ErrorMessage : ErrorMessage2),
[...]
(Vulnerability : vVulnerabilityX; Name : NameX; Description : DescriptionX; ErrorMessage : ErrorMessageX)
)
);
I don't have an IDE on this computer to double check the syntax... might be a comma or two missing. But this is how you should do it I think.
not an answer but may be a clue: design-time controls can have images and other binary data associated with it, why not write your data to a resource file and read from there? iterating of course, to make it simpler, extensible and more elegant
The typical way would be a file, either properties style (a=b\n on each line) cdf, xml, yaml (preferred if you have a parser for it) or a database.
If you must specify it in code as in your example, you should start by putting it in something you can parse into a simple format then iterate over it. For instance, in Java I'd instantiate an array:
String[] vals=new String[]{
"Name of Vulnerability1", "Description of Vulnerability1", "Error Message of Vulnerability1",
"Name of Vulnerability2", ...
}
This puts all your data into one place and the loop that reads it can easily be changed to read it from a file.
I use this pattern all the time to create menus and for other string-intensive initialization.
Don't forget that you can throw some logic in there too! For instance, with menus I will sometimes create them using data like this:
"^File", "Open", "Close", "^Edit", "Copy", "Paste"
As I'm reading this in I scan for the ^ which tells the code to make this entry a top level item. I also use "+Item" to create a sub-group and "-Item" to go back up to the previous group.
Since you are completely specifying the format you can add power later. For instance, if you coded menus using the above system, you might decide at first that you could use the first letter of each item as an accelerator key. Later you find out that File/Close conflicts with another "C" item, you can just change the protocol to allow "Close*e" to specify that E should be the accelerator. You could even include ctrl-x with a different character. (If you do shorthand data entry tricks like this, document it with comments!)
Don't be afraid to write little tools like this, in the long run they will help you immensely, and I can turn out a parser like this and copy/paste the values into my code faster than you can mold a text file to fit your example.

Resources