JFlex parametrized token - jflex

I want to parse expressions of the following structure:
compositeKey ::= key (separator key)*
Here is the flex code fragment:
KEY_CHARACTER=[^:\s]
KEY_SEPARATOR=[:]
%state WAITING_KEY
...
<WAITING_KEY> {KEY_CHARACTER}+ { yybegin(WAITING_KEY); return MyTypes.KEY; }
<WAITING_KEY> {KEY_SEPARATOR} { yybegin(WAITING_KEY); return MyTypes.KEY_SEPARATOR; }
Code generated by given flex fragment works fine, but what if I want to get key separator at "runtime"?
It actually may be any character, specified by user.
How to do it with jflex?

Related

Eclipse formatter: How to move comment between method name and open brace to always have open brace on same line as method declaration

I have code that looks like this, that I'm trying to format
Original code:
public int doThing(int a) // -incredibly useful comment here
{
int ab = a+1;
return ab;
}
I want it to look like this
public int doThing() { // -incredibly useful comment here
int ab = a+1;
return ab;
}
If I try to turn on the Brace position -> Method Declaration -> Same line option and run the formatter, any code with a comment in the position "breaks" the formatter, and I get an output for my example that looks the same as the original code, but methods without a comment have the correct formatting (meaning the results are inconsistent).
Is it possible with the eclipse formatter to get the style I want? I'm trying to run it against a large amount of code, and would prefer not to have to fix these all manually to get a consistent brace position.
The problem here is that is not formatting but rewriting. Using File Search + regular expression + Replace could do that in bulk.
Try this regex
^(\s*(?:public|private|protected)\s+[^(]+\([^)]*\))(\s*\/\/[^/]+)\R\s*\{
On File Search ( Ctrl + H)
Hit Replace and use $1 { $2\n as replacement
Code should compile after the refactoring.
UPDATE:
Fixed regex part that represents function arguments
\([^)]*\)
Full Regex matches these cases
public int doSmthg() // coment here
{
return 1;
}
private String doSmthgElse(String arg) // coment here
{
return arg;
}

Why is there an "." In the option in the lit sample?

lit introduces an example of "Change detection" at the following URL.
https://lit.dev/playground/#sample=examples/properties-has-changed
Why is there a "." at the beginning of "date" when specifying the "date-display" option in line 16 of my-element.ts?
import { LitElement, html} from "lit";
import {customElement, property} from 'lit/decorators.js';
import {localDateFromUTC} from './date-utils.js';
import './date-display.js';
#customElement('my-element')
class MyElement extends LitElement {
#property() date?: Date;
render() {
return html`
<p>Choose a date:
<input type="date" #change=${this._dateChanged}></p>
<p><button #click=${this._chooseToday}>Choose Today</button></p>
<p>Date chosen: <date-display .date=${this.date}></date-display></p>
`;
}
_dateChanged(e: Event) {
const utcDate = (e.target as HTMLInputElement).valueAsDate;
if (utcDate) {
this.date = localDateFromUTC(utcDate);
}
}
_chooseToday() {
this.date = new Date();
}
}
Lit uses prefixes to indicate the type of expression in a component's template. The . prefix denotes a property expression; without the prefix it would be an attribute expression. Using a property expression makes it very easy and convenient to pass any JS object to a child element (in this case a Date object).
When using HTML attributes you need to be aware that they are always strings. JS data must be converted to a string on the parent element, and then possibly converted back to the corresponding JS type on the child element.
No such conversion is performed with property expressions, because the data stays in "JS land".
So, why not always use property expressions? Two examples come to my mind right away:
For a property expression to work you need to know an implementation detail of the child element, i.e. that it has a corresponding JS property. (If you're dealing with your own Lit based elements inside a single project that is not a problem.)
If you want to apply selectors based on attributes (e.g. for styling my-button[disabled] { /* CSS ... /* } or using querySelector).

Flutter 1.22 Internationalization with variable as key

I implemented the new (official) localization for Flutter (https://pascalw.me/blog/2020/10/02/flutter-1.22-internationalization.html) and everything is working fine, except that I don't know how to get the translation for a variable key.
The translation is in the ARB file, but how can I access it?
Normally I access translations using Translations.of(context).formsBack, but now I would like to get the translation of value["labels"]["label"].
Something like Translations.of(context).(value["labels"]["label"]) does not work of course.
I don't think this is possible with gen_l10n. The code that is generated by gen_l10n looks like this (somewhat abbreviated):
/// The translations for English (`en`).
class TranslationsEn extends Translations {
TranslationsEn([String locale = 'en']) : super(locale);
#override
String get confirmDialogBtnOk => 'Yes';
#override
String get confirmDialogBtnCancel => 'No';
}
As you can see it doesn't generate any code to perform a dynamic lookup.
For most cases code generation like this is a nice advantage since you get auto completion and type safety, but it does mean it's more difficult to accommodate these kinds of dynamic use cases.
The only thing you can do is manually write a lookup table, or choose another i18n solution that does support dynamic lookups.
A lookup table could look something like this. Just make sure you always pass in the current build context, so the l10n code can lookup the current locale.
class DynamicTranslations {
String get(BuildContext context, String messageId) {
switch(messageId) {
case 'confirmDialogBtnOk':
return Translations.of(context).confirmDialogBtnOk;
case 'confirmDialogBtnCancel':
return Translations.of(context).confirmDialogBtnCancel;
default:
throw Exception('Unknown message: $messageId');
}
}
}
To provide an example for https://stackoverflow.com/users/5638943/kristi-jorgji 's answer (which works fine):
app_en.arb ->
{
"languages": "{\"en\": \"English\", \"ro\": \"Romanian\"}"
}
localization_controller.dart ->
String getLocaleName(BuildContext ctx, String languageCode) {
return jsonDecode(AppLocalizations.of(ctx)!.languages)[languageCode];
}
getLocaleName(context, 'ro') -> "Romanian"
You can store a key in translation as json string.
Then you read it, parse it to Map<string,string> and access dynamically what you need.
Been using this approach with great success

fragment cannot be spread here as objects of type "Query"

Trying out relay with react and ran into this today. Here is what I've done so far.
Root Query:
query {
tasks {
id
taskName
taskStatus
userId
}
}
React component hierarchy
App
↳--TaskList (props: tasks)
↳--TaskListItem (props: task)
Now due to the principle of colocation I know I have to write fragments in each component to describe their data needs.
TaskListItem.js
const TaskListItemContainer = createFragmentContainer(
TaskListItem,
graphql`
fragment TaskListItem_task on task {
id
taskName
taskDone
authorId
}
`
);
TaskList.js
const TaskListContainer = createFragmentContainer(
TaskList,
graphql`
fragment TaskList_tasks on task {
tasks {
...TaskListItem_task
}
}
`
);
App.js
<QueryRenderer
environment={relayEnvironment}
query={graphql`
query AppQuery {
...TaskList_tasks
}
`
}
When I run the relay compiler I get the following error.
Fragment "TaskList_tasks" cannot be spread here as objects of type "Query" can never be of type "task".
App.js (3:15)
2: query AppQuery {
3: ...TaskList_tasks
^
4: }
Not able to figure out how to organize the structure because of this problem. Should I modify the schema just to facilitate the structure and reuse of fragments on the client side?
A basic Fragment consists of five things:
the fragment keyword
the name of the Fragment
the on keyword
the type the Fragment applies to
the selection set wrapped in a set of curly brackets
The selection set is one or more fields of the type you specify that you want to request when you use the Fragment. Think of the Fragment as a drop in replacement for a single selection set. If I have a query like this:
query {
foo
bar
}
then { foo bar } is the selection set I'm requesting, in this case on the Query type (or whatever your query root operation type is called in your schema). So if I want to use a fragment, I would write:
query {
...QueryFields
}
fragment QueryFields on Query {
foo
bar
}
In your code, you're trying to write a query like:
query {
...TaskList_tasks
}
However, as the error indicates, the type associated with the TaskList_tasks fragment is task. But you're not replacing a selection set for a task type here, you're replacing a selection set for the Query type. So your request is not valid.
TLDR; You need to change the type on your Fragment to Query:
fragment TaskList_tasks on Query {
tasks {
...TaskListItem_task
}
}

Are digits allowed in a knockout.js custom binding name?

I have an application with a custom binding declared like
ko.bindingHandlers.slideContent2 = {
init: ...,
update: ...
}
and I use that in my html with (among other things)
<div data-bind="slideContent2: true"></div>
It works and produces no errors. Today I discover that the new knockout.js syntax checker in Netbeans 7.4 thinks that <div data-bind="slideContent2: true"> is in error. It objects to the digit 2. If I remove that, it thinks the name is fine. Looking around web examples, I haven't found an example of a digit used in the name of a custom binding.
Are digits legal in custom binding names? Is the Netbeans checker being overenthusiastic?
From the Knockout point of view every valid JavaScript identifier name is a valid custom binding handler name.
So you can have digits in custom binding handlers. For the full identifier name reference you can check: Valid identifier names
However from the Netbeans syntax checker point of view only letters are allowed in custom binding names.
For reference check out the source of KODataBindLexer (I've added some comments)
case IN_KEY:
if (!Character.isLetter(c)) { // the character 2 is not a letter
if (c == ':') {
state = State.AFTER_KEY;
input.backup(1); //backup the colon
return tokenFactory.createToken(KODataBindTokenId.KEY);
} else if (Character.isWhitespace(c)) {
state = State.WS_AFTER_KEY;
input.backup(1); //backup the ws
return tokenFactory.createToken(KODataBindTokenId.KEY);
} else { // 2 is not a the colon and not a whitespace so it returns Error:
state = State.INIT;
return tokenFactory.createToken(KODataBindTokenId.ERROR);
}
}
//stay in IN_KEY
break;