Handling optional parser rules in ANTLR Listener - listener

As an exercise I am trying to write a listener that can convert some pascal code into JavaScript. Is it possible to make this listener function behave differently for the program header depending on whether or not identifierList is used?
Listener function:
class PascalListenerImpl extends pascalBaseListener {
STGroup stg = new STGroupFile("./pascal.stg");
String programName;
#Override
public void enterProgram(pascalParser.ProgramContext ctx) {
List<ParseTree> values = ctx.children;
ArrayList<String> valueNames = new ArrayList<String>();
programName = ctx.programHeading().getChild(1).getText();
for (int i = 3; i<ctx.getChildCount(); i+=)
ST st = stg.getInstanceOf("enterProgram")
st.add("v", programName);
}
Grammar rules:
programHeading
: 'PROGRAM' identifier (LPAREN identifierList RPAREN)? SEMI
| 'UNIT' identifier SEMI
;
identifierList
: identifier ( COMMA identifier )*
;
string template:
enterProgram(v, values) ::= "var <v> = function <v>(<values; seperator=", ") {"

Related

Android Room Kotlin: entities with non data classes

Regarding to classes that can/may be used for entities in room whith Kotlin,
Is it mandatory to use data classes? Or could I use 'normal classes', i.e., the ones I use for the 'bussiness logic'
In case data classes are mandatory: can I add functionality to what they have by default? i.e, can I add functions (for whatever taks they may need) to them?
The documentation doesn't say anything about limiting entities to data classes (although each and every code snippet use a data class).
Thanks.
Is it mandatory to use data classes?
No, you can use either including a mix.
data classes are a convenience class
can I add functionality to what they have by default?
Yes.
Perhaps consider the following:-
#Entity
class Table1 {
#PrimaryKey
var id: Long? = null
var name: String = ""
#Ignore
var notAColumnInTheTable = false
constructor(){}
#Ignore
constructor(name: String) {
this.id = null
this.name = name
this.notAColumnInTheTable = true
}
fun getIdAndName(): String {
return id.toString() + ":" + name
}
}
and :-
#Entity
data class Table2(
#PrimaryKey
var id: Long? = null,
var name: String,
#Ignore
var notAColumnInTheTable: Boolean = false
) {
constructor(name: String) : this( id = null,name = name, notAColumnInTheTable = true)
fun getIdAndName(): String {
return id.toString() + ":" + name
}
}
basically they are the same.
Using :-
#Dao
abstract class Table1And2Dao {
#Insert
abstract fun insert(table1: Table1): Long
#Insert
abstract fun insert(table2: Table2): Long
#Query("SELECT * FROM table1")
abstract fun getAllFromTable1(): List<Table1>
#Query("SELECT * FROM table2")
abstract fun getAllFromTable2(): List<Table2>
}
note the use of an abstract class rather than the normally see interface
along with a suitable #Database annotated class, in this case one that has a function that returns an instance of the built database and for convenience/brevity allows running on the main thread.
Then using :-
var db = AppDatabase.getDatabase(this)
var dao = db.getTable1AndTable2Dao()
dao.insert(Table1("TABLE1_1"))
dao.insert(Table2("TABLE2_1"))
for(t1: Table1 in dao.getAllFromTable1()) {
Log.d("DBINFO","Name is ${t1.name} ID is ${t1.id} NotAColumnInTable is ${t1.notAColumnInTheTable} idandname = ${t1.getIdAndName()}")
}
for(t2: Table2 in dao.getAllFromTable2()) {
Log.d("DBINFO","Name is ${t2.name} ID is ${t2.id} NotAColumnInTable is ${t2.notAColumnInTheTable} idandname = ${t2.getIdAndName()}")
}
Results in the log including:-
D/DBINFO: Name is TABLE1_1 ID is 1 NotAColumnInTable is true idandname = 1:TABLE1_1
D/DBINFO: Name is TABLE2_1 ID is 1 NotAColumnInTable is true idandname = 1:TABLE2_1
Via App Inspection :-
and :-

AST MATCHER:How to match un init double param in constructor

I 'm having a question to match uninit double field in constructor.
Given the code below
class un_init_double {
public:
un_init_double() {
init_param_ = 0;
}
bool compare(un_init_double& other) {
if (other.un_init_param_ == un_init_param_) {
return true;
}
return false;
}
private:
double un_init_param_;
double init_param_;
};
I want to match the un_init_param_ field, which didn't call binary operator = in constructor. But I don't find the method to do that.
I type below command in clang-query
clang-query> match cxxRecordDecl(
has(fieldDecl(hasType(asString("double"))).bind("double_field")), has(cxxConstructorDecl(hasDescendant(binaryOperator(hasEitherOperand(memberExpr()))))))
But how to specify memberExpr is related with prew part fieldDecl? In another word, how to specify the connection of fieldDecl and the memberExpr?
I find a method to match init_param_, but how to find no match field?
clang-query> match cxxRecordDecl(has(cxxConstructorDecl(hasDescendant(binaryOperator(hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))))).bind("member")))))))
Match #1:
~/code_test/ast_matcher/test.cc:9:7: note: "member" binds here
init_param_ = 0;
^~~~~~~~~~~
~/code_test/ast_matcher/test.cc:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
1 match.
clang-query>
When debuging, I write a complicated method to perform this check:
// match record
cxxRecordDecl(
has(
// constuctor has init double fieldDecl with binaryoperator = , bind to init_double_field
cxxConstructorDecl(
hasDescendant(
binaryOperator(
hasOperatorName("="),
hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))).bind("init_double_field"))))
)
)
)
),
has(
// match double field which didn't call binaryoperator = in constructor
fieldDecl(hasType(asString("double")), unless(equalsBoundNode("init_double_field"))).bind("un_init_double_field")
)
)
It seems to work, but if I add a sentence: "un_init_param_ = 1;" in the constructor, it still takes un_init_param_ as uninit_field. Find that it's caused by ast matcher will only match the first one rather than match all. So I modify matcher to:
cxxRecordDecl(
has(
cxxConstructorDecl(
forEachDescendant(
binaryOperator(
hasOperatorName("="),
hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))).bind("init_double_field"))))
)
)
)
),
has(
fieldDecl(hasType(asString("double")), unless(equalsBoundNode("init_double_field"))).bind("un_init_double_field")
)
)
I modify original test.cpp to:
int f(int x) {
int result = (x / 42);
return result;
}
class un_init_double {
public:
un_init_double() {
init_param_0_ = 0;
init_param_1_ = 0;
}
bool compare(un_init_double& other) {
if (other.un_init_param_ == un_init_param_) {
return true;
}
return false;
}
private:
double un_init_param_;
double init_param_0_;
double init_param_1_;
};
New ast matcher can match it as follows:
Match #1:
/home/qcraft/code_test/ast_dump/test.cpp:20:5: note: "init_double_field" binds here
double init_param_0_;
^~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:19:5: note: "un_init_double_field" binds here
double un_init_param_;
^~~~~~~~~~~~~~~~~~~~~
Match #2:
/home/qcraft/code_test/ast_dump/test.cpp:21:5: note: "init_double_field" binds here
double init_param_1_;
^~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:19:5: note: "un_init_double_field" binds here
double un_init_param_;
^~~~~~~~~~~~~~~~~~~~~
2 matches.
clang-query>

Groovy use own quote character in CSVWriter from Grails Plugin

I want to use CSVWriter from Grails Plugin, but I don't know how to change the default quote and value seperator. I also want to know to how to avoid a header line.
My code (which is not working)
Writer writer = new StringWriter()
CSVWriter w = new CSVWriter(writer, {
testdata.eachWithIndex { row, index ->
"${row}" {it."${row}"}
}
})
w.quote = "'"
w.valueSeperator = ";"
w.quote is not working
Here is the source code of the Grails CVS Plugin. It seems to me that contrary to CSVReader the CSVWriter doesn't accept in constructor options to override delimiter etc.
CSVWriter(Writer writer, Closure definition)
UPDATE
As hinted in the comment I tried to change the quote character in a subclass. This works, but unfortunately there is a problem with the header line (containg two **null* strings). I'm not able to resolve this.
import org.grails.plugins.csv.CSVWriter
/* Groovy Version: 2.4.4 */
#groovy.transform.InheritConstructors
class MyCSVWriter extends CSVWriter {
private columns = [:]
private cachedQuote
private cachedQuoteEscape
private cachedQuoteReplace
private cachedValueSeperator
private cachedRowSeperator
private producers
private lastProducer
private headingsWritten = false
protected getQuote() {
"'"
}
protected getQuoteEscape() {
"'"
}
protected getValueSeperator() {
","
}
protected getRowSeperator() {
"\n"
}
}
def sw = new StringWriter()
def b = new MyCSVWriter(sw, {
col1 { it.val1 }
col2 { it.val2 }
})
b << [val1: 'a', val2: 'b']
b << [val1: 'c', val2: 'd']
println b.writer.toString()
'col1'null'col2'null
'a','b'
'c','d'
I don't know if you have solve the problem, but I've had the same issue and I've been able to change, for instance, the value of valueSeperator setting the property cachedValueSeperator. So in your example, you can do:
CSVWriter w = new CSVWriter(writer, {
testdata.eachWithIndex { row, index ->
"${row}" {it."${row}"}
}
})
w.cachedQuote = "'"
w.cachedValueSeperator = ";"
I hope this can help.

Does Flash have a method that does the reverse of toString?

When using ObjectUtil there is a method called, toString() that takes an object. If you pass it a class named, "Person" it will return the string "[class Person]".
var person:Person = new Person();
trace(ObjectUtil.toString(person));//UPDATE I'm not using ObjectUtil.toString()
// traces [class Person]
Is there a toObject() method? Something that takes the same format toString outputs and creates an instance like so:
var person:Person = ObjectUtil.toObject("[class Person]");
UPDATE:
Sorry. This is incorrect. I thought I was using ObjectUtil.toString(). I was not. When I use that method it returns something like:
(com.printui.assets.skins::fontList)#0
accessibilityDescription = ""
accessibilityEnabled = true
accessibilityImplementation = (null)
In my code somewhere it is returning "[class Person]" like I was described. This is the line:
var currentValue:* = target[property];
popUpValueInput.text = currentValue;
I thought it was using instance.toString() but toString() is not returning anything close to that:
var f:fontList = new fontList();
var f1:fontList = new fontList();
trace("" + f);
trace("" + f1);
trace(f1.toString());
Results in:
fontList2
fontList5
fontList5
In general you should do this:
In your Person class add this method:
public function toString():String
{
return "Person" ;
}
So to make an instance of the class by name use this code:
var p = new (getDefinitionByName( ObjectUtils.toString(person)))
or it can be used a regex in general for all classes (thanks to 1.21 gigawatts ):
var p = new (getDefinitionByName( ObjectUtil.toString(Person).match(/\((.*)\)/)[1] ) );

how to pass argument to Marionette.CompositeView

how to pass a values dynamically to an Marionette.CompositeView during run time? like in java we create a method like the following
package com.test.poc;
public class SampleMethod {
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
SampleMethod method = new SampleMethod();
int firstValue = 90, secondValue = 90;
System.out.println("add : " + method.add(firstValue, secondValue));
}
}
the above is the simple java code anybody can understand like the above how to create and pass arguments to Marionette.CompositeView and work on them?
Best Regards
at the moment you instanciate a view, you can pass whatever arguments you want. normally you pass the model and the collection to be rendered in the compositeView, but you can pass more data if you need.
var MyCompositeView = Backbone.Mationette.CompositeView.extend({
initialize : function (options){
this.dataValue = options.dataValue1;
this.helperObject = options.helperObject;
this.useValues();
},
useValues: function () {
console.log(this.dataValue);
}
});
var helperObject = {
value3 : "I have a value",
value4 : "I dont!"
}; /// a js object literal
var myModel = new MyModel();
var myCollection = new MyCollection();
var myCompositeView = new MyCompositeView({model:myModel,
collection:myCollection,
helperObject:helperObject,
dataValue1:"Hi there"});
notice that Im passing 4 values in the at the time to intanciate the view, and Im reading just two of them, the model and the collection will be handled by marionette, but the other two you can read them in your initialize function.
hope that helps.