如何在xtext DSL中嵌入C ++代码?(How to embed C++ code in a xtext DSL?)
在Xtext / ANTLR中处理C ++代码块的正确方法是什么?
我们正在为DSL编写一个基于Xtext的eclipse插件,支持在明确定义的范围(大多数是
serial { /* ... */ }
块)中添加C ++功能级代码,例如:module m { chare c { entry void foo() { serial { // C++ code block } } } }
请参阅此处以获取更全面的示例。 然后将其移交给外部工具以处理进一步的编译/链接步骤,因此我们不会从eclipse生成任何代码。
这里的问题是如何处理这些C ++代码块,特别是考虑到它们可能包含自己的大括号。 这与如何在Xtext DSL中包含Java代码块非常相似? 但是现在我们满足于忽略那个块(即没有内容辅助或语法突出显示不理想但可以接受。)
在我们的基于bison / flex的工具中,这是通过在解析器和词法分析器之间共享一个变量来完成的,该变量在某些语法规则中切换“C ++解析模式”,这使得词法分析器为除了相关分隔符(例如大括号)之外的所有内容返回CPROGRAM标记。 )自然翻译似乎有一个自定义的ANTLR词法分析器,它使用语义谓词来达到同样的效果,例如
RULE_NON_BRACES: {in_braces}? ~('{' | '}')+;
作为第一个lexing规则,但是我找不到如何从Xtext语法中访问该全局变量,因为在bison中似乎没有“规则操作”的概念。 还有其他非“串行”语法上下文,其中需要C ++代码,因此需要在解析器和词法分析器之间进行一些协调。
What is the proper way of handling C++ code blocks in Xtext/ANTLR?
We are writing an Xtext-based eclipse plugin for a DSL that supports adding C++ function-level code within well-defined scopes (mostly
serial { /* ... */ }
blocks) such as this:module m { chare c { entry void foo() { serial { // C++ code block } } } }
See here for a more comprehensive example. This is then handed over to an external tool to handle further compilation/linking steps, so we don't generate any code from eclipse.
The issue here is how to handle these C++ code blocks, especially given that they may contain braces of their own. This is very similar to How to include Java Code Block in Xtext DSL? but for now we are content with just ignoring that block (i.e. not having content assist or syntax highlighting is not ideal but acceptable.)
In our bison/flex-based tool this is done by sharing a variable between the parser and lexer that toggles a "C++ parsing mode" within certain grammar rules that makes the lexer return a CPROGRAM token for everything except the relevant delimiters (e.g. braces.) The natural translation seems to have a custom ANTLR lexer that uses semantic predicates to the same effect, e.g.
RULE_NON_BRACES: {in_braces}? ~('{' | '}')+;
as the first lexing rule, but I cannot find how to access that global variable from the Xtext grammar since there doesn't seem to be a concept of "rule action" as in bison. There are other non-"serial" grammar contexts where C++ code is expected, so there needs to be some coordination between the parser and lexer.
原文:https://stackoverflow.com/questions/35806402
最满意答案
您可以使用角度2的管道 (角度1的过滤器 )来过滤所有空项目:
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({name: 'removeNull', pure: false}) export class RemoveNullPipe implements PipeTransform { transform(items: any[]): any { return items.filter(item => item); } }
然后在HTML中使用它:
<ul> <li *ngFor="let theTask of tasksList.items | removeNull">{{ theTask.name }}</li> </ul>
我将
*ngFor
从<ul>
移到<li>
元素,在<ul>
重复<li>
并不重复ul
s似乎更好plunker: http ://plnkr.co/edit/IQq45kaJqqWRZOqhZdoe?p =preview
You can use angular 2's pipe (angular 1's filter) in order to filter all empty items:
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({name: 'removeNull', pure: false}) export class RemoveNullPipe implements PipeTransform { transform(items: any[]): any { return items.filter(item => item); } }
then use it in HTML:
<ul> <li *ngFor="let theTask of tasksList.items | removeNull">{{ theTask.name }}</li> </ul>
I moved
*ngFor
from<ul>
to<li>
element, it seems better to repeat<li>
s within<ul>
and not repeatul
splunker: http://plnkr.co/edit/IQq45kaJqqWRZOqhZdoe?p=preview
相关问答
更多-
找到了! 解决方案非常简单: 为避免用户登录时用户标识为空,我只是为了避免使用authState.subscribe回调参数中的uid ,而只是使用新创建的变量,而不是直接从AngularFireAuth的注入AngularFireAuth服务存储uid : this.userId = this.auth.auth.currentUser.uid; Found it! The solution is pretty simple: to avoid the user id to be null when t ...
-
假设你有这样的结构: cart: yyy: productId: aaa qty: 2 zzz: productId: bbb qty: 1 products: aaa: name: AAA bbb: name: BBB 然后你可以将它映射到数据库的其他部分,因为你已经拥有了我只是在这里使用valueChanges()的键。 this.cart = this.db.list(`/cart`) .snapshotChanges() .m ...
-
进一步Google搜索后,我发现以下工作: this.db.object('path/to/my/count').query.ref.transaction(count => count ? ++count : 1); 资源 After googling further, I have found that the following works: this.db.object('path/to/my/count').query.ref.transaction(count => count ? ++cou ...
-
调用AngularFire2 auth observable的createUser或login方法时发生的任何错误都是通过返回的promise报告的,而不是通过observable报告的。 例如: import { AngularFire } from 'angularfire2'; ... class MyComponent { constructor(af: AngularFire) { af.auth.createUser({ email: 'someone@somepl ...
-
你需要订阅列表,所以你需要做这样的事情: 所以如果你在你的数据库中有这样的项目列表: -items -item1 -name: 'mycoolitem' -item2 -name: 'mycoolitem2' 然后在你的TS文件中: //Items would have to be a list observable items: FirebaseListObservable
; //create an array for the returned items ... -
angularfire2无法读取null的属性'displayName'(angularfire2 can not read property 'displayName' of null)[2022-04-22]
如Firebase文档中所述,当前用户是firebase.User 或 null 。 我的猜测是没有用户登录,因此当前用户为null 。 尝试在它周围包装一个if语句,如下所示: if (user !== null) { this.userName = user.displayName; console.log(`[constructor]userName : ${this.userName}`); } As stated in the Firebase documentation the cur ... -
带firestore的Angularfire2:删除文档中的特定字段(Angularfire2 with firestore: delete specific fields from a document)[2022-01-20]
你有可能错过进口 import * as firebase from 'firebase/app'; 现在你可以试试 capital: firebase.firestore.FieldValue.delete() Chances are you miss the imports import * as firebase from 'firebase/app'; now you can try capital: firebase.firestore.FieldValue.delete() -
AngularFire2 - 如何在页面刷新后保持登录状态(AngularFire2 - How to maintain logged in state after page refresh)[2023-10-23]
AngularFireAuth是一个可观察的并发出FirebaseAuthState值。 如果用户已登录并刷新页面, AngularFireAuth将发出经过身份验证的FirebaseAuthState ; 否则,它将发出null 。 所以这样的事情应该接近解决你的问题: constructor(private auth: AngularFireAuth, private router:Router) { auth.subscribe((authState) => { if (authStat ... -
在ObjectObservable删除后,AngularFire2避免使用null值(AngularFire2 avoid null value after ObjectObservable remove)[2023-10-25]
您可以使用角度2的管道 (角度1的过滤器 )来过滤所有空项目: import { Pipe, PipeTransform } from '@angular/core'; @Pipe({name: 'removeNull', pure: false}) export class RemoveNullPipe implements PipeTransform { transform(items: any[]): any { return items.filter(item => item); ... -
您应该做的第一件事是等到块被移除后再移除城市: import 'rxjs/add/operator/first'; import 'rxjs/add/operator/toPromise'; // Use the first operator to take the first emitted list and then // complete the observable and use the toPromise operator to // convert it into a promise for ...