I am trying to extend ANTLR4 with a new PHP target and have a problem with the StringTemplate file (.stg):
In the StringTemplate file the Parser is defined by the template Parser_. Parser_ contains the following rule :
<funcs; separator="\n">
This rule emits class definitions and functions. The rule is located inside the parser class, but PHP does not support nested classes.
Is there a possibility to divide between class definitions and functions in the StringTemplate file? I want to set the class definitions of the funcs template before the parser class and the functions of the funcs template inside the parser class.
The whole parser-Template :
Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass) ::= <<
// funcs beinhaltet die Klasse und dann die Funktion
class <parser.name> extends <if(superClass)><superClass><else>\antlr4\php7_runtime\Parser<endif> {
public $grammarFileName = "<parser.grammarFileName>";
public $atn = null;
public $decisionsToDFA = array( );
public $sharedContextCache = null;
public $literalNames = [ <parser.literalNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];
public $symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];
<parser.rules:{r | const RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor>
public $ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
public $EOF = <PathRuntime()><TokenLabelType()>::EOF;
<if(parser.tokens)>
<parser.tokens:{k | const <k>=<parser.tokens.(k)>;}; separator="\n", wrap, anchor>
<endif>
<atn>
<parser:(ctor)()>
<namedActions.members>
// funcs -- Start
<funcs; separator="\n">
// funcs -- Ende
} // class <parser.name>
<if(sempredFuncs)>
function sempred( $localctx, int $ruleIndex, int $predIndex){
if ($this->_predicates == null) {
$this->_predicates = py_dict();
}
<parser.sempredFuncs.values:{ f |
$this->predicates[<f.ruleIndex>] = $this-><f.name>_sempred}; separator="\n">
$pred = $this->_predicates->get($ruleIndex, null);
if ( $pred == null) {
throw Exception("No predicate with index:" . (string) $ruleIndex );
} else {
return pred( $localctx, $predIndex)
}
<sempredFuncs.values; separator="\n">
}
<endif>
>>
Thank you for your time!
The solution was to walk the parser.funcs.ruleCtx and to exclude from the RuleFunction template :-)
Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass ) ::= <<
<funcs :{ func | <func.ruleCtx> }; separator="\n"> // here the Comtext classes
class <parser.name> extends <if(superClass)><superClass><else>\antlr4\php7_runtime\Parser<endif> {
public $grammarFileName = "<parser.grammarFileName>";
public $atn = null;
public $decisionsToDFA = array( );
public $sharedContextCache = null;
public $literalNames = [ <parser.literalNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];
public $symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="'\<INVALID>'", separator=", ", wrap, anchor> ];
<parser.rules:{r | const RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor>
public $ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
public $EOF = <PathRuntime()><TokenLabelType()>::EOF;
<if(parser.tokens)>
<parser.tokens:{k | const <k>=<parser.tokens.(k)>;}; separator="\n", wrap, anchor>
<endif>
<atn>
<parser:(ctor)()>
<funcs; separator="\n"> // here RuleFunction is emitted
} // class <parser.name>
<namedActions.members>
<if(sempredFuncs)>
function sempred( $localctx, int $ruleIndex, int $predIndex){
if ($this->_predicates == null) {
$this->_predicates = py_dict();
}
<parser.sempredFuncs.values:{ f |
$this->predicates[<f.ruleIndex>] = $this-><f.name>_sempred}; separator="\n">
$pred = $this->_predicates->get($ruleIndex, null);
if ( $pred == null) {
throw Exception("No predicate with index:" . (string) $ruleIndex );
} else {
return pred( $localctx, $predIndex)
}
<sempredFuncs.values; separator="\n">
}
<endif>
>>
Related
I want to create a programming language that has multiple functions and a single main function. For the interpreter of the language I am using a hash map, but I do not know how to store intermediate values in the hash map. An example of a valid program includes:
DEF MAIN { ADDITION(4) } ;
DEF ADDITION x { x+3 } ;
This is what I have so far:
HashMap<String, Function> Program() : {
HashMap<String, Function> symbolTable = new HashTable<>();
}
{
(FunctionDefinition(symbolTable))*
<EOF>
{return symbolTable;}
}
void FunctionDefinition(SymbolTable table)
{
Function f;
String name;
}
{
<DEF> <SPACE>
(
(name = <MAIN>)
| (name = <FUNC> (<SPACE> <PARAM> ))
<SPACE>
f = FunctionBody()
";"
{
if (table.hashKey(name)) { System.out.println("do something");}
else { table.add(name, f); }
})
}
void FunctionBody() : {}
{
<LEFT> <SPACE>
Expression()
<SPACE> <RIGHT>
}
void Expression() : {}
{
AdditiveExpression()
}
void AdditiveExpression() : {
}
{
MultiplicativeExpression() (<PLUS> MultiplicativeExpression()
{
try {
int a = s.pop();
int b = s.pop();
stack.push(a+b);
}
catch (ClassCastException ex) {
System.out.println("Only numbers can be used for arithmetic operations.");
throw new ParseException();
}
})*
}
void MultiplicativeExpression() : {
}
{
UnaryExpression() (<MUL> UnaryExpression()
{
try {
int a = s.pop();
int b = s.pop();
stack.push(a*b);
}
catch (ClassCastException ex) {
System.out.println("Only numbers can be used for arithmetic operations");
throw new ParseException();
}
})*
}
void UnaryExpression() : {
Token x;
}
{
(x = <NUMBER> | x = <PARAM>)
{s.push(x.image);}
}
Any help will be greatly appreciated.
As #Theodore has said, you can't execute the program while you're parsing it. I thought I'd add my two cents here.
The result of the parsing could be the table of functions though, and you would have a main method that would do something like this:
Parser parser = new Parser(System.in, "UTF-8");
Map<String, Function> table = parser.program();
Function main = table.get("MAIN");
if (main == null) {
System.out.println("Function MAIN doesn't exist");
} else {
int r = main.invoke(table);
System.out.println("Result: " + r);
}
I see a few weird things in your code:
Instead of using a token <SPACE> between each token, you'd be better off using the SKIP instruction:
SKIP : { " " | "\r" | "\n" | "\t" }
You're using three different tokens for the same thing: <MAIN>, <FUNC>, <PARAM>. They're all names, and you could define a token <NAME> as follows:
TOKEN: {
< NAME: <LETTER>(<LETTER>|<DIGIT>)* >
| < #LETTER: ["a"-"z", "A"-"Z", "_"] >
| < #DIGIT: ["0"-"9"] >
}
The rule for a function definition would then become:
<DEF> <NAME> ( <NAME> )* functionBody() ";"
note that a function can have zero or more parameters; function MAIN would have zero.
In your example, function MAIN contains a forward reference to the function ADDITION, meaning that while parsing the body of function MAIN you will find a call to a function ADDITION that is not yet in the symbol table. The ability to use forward reference is a nice feature for a programming language, but it complicates the implementation slightly.
If you're doing an interpreter, you have basically two options to deal with forward references: 1) do a second pass after the parsing to "fix" the forward references, 2) do the name resolution during run time. The second option is simpler but slower.
Note that the parameters of a function are always defined before they are used. They are only accessible within the body of a function. You can build a table for the parameter while parsing the head of the definition, and then pass that table to the method that parses the body of the function.
Example:
void functionDefinition(Map<String, Function> table): {
Expression body;
Function f;
String name;
String param;
int paramCount = 0;
Map<String,Parameter> params = new HashMap<String,Parameter>();
}
{
<DEF> name=<NAME>.image (
param=<NAME>.image {params.put(param, new Parameter(paramCount++));}
)*
body=functionBody(params)
{ f = new Function(paramCount, body); }
";"
{
if (table.containsKey(name)) {
System.out.println("Function " + name + "already exists");
} else {
table.put(name, f);
}
}
}
To evaluate the expression in a function body, you can use the interpreter pattern, where the elements of an expression are all an implementation of an Expression interface:
public interface Expression {
public int evaluate(Map<String,Function> table, int... parms);
}
Here parms are the actual parameters passed to the function being executed.
The following files are the sources of a very simple, functioning implementation of a very simple language based on your question. It can execute your example:
DEF MAIN { ADDITION(4) } ;
DEF ADDITION x { x+3 } ;
and it can also execute something like this:
DEF MAIN { ADDITION3(4) } ;
DEF ADDITION3 x { ADDITION(x,3) } ;
DEF ADDITION x y { x+y } ;
I hope it will help.
JavaCC file, parser.jj:
options {
STATIC = false;
IGNORE_CASE = false;
}
PARSER_BEGIN(Parser)
package org.tastefuljava.minilang;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
public class Parser {
public static void main(String[] args) {
try {
Parser parser = new Parser(System.in, "UTF-8");
Map<String, Function> table = parser.program();
int r = Expression.call("MAIN").evaluate(table);
System.out.println("Result: " + r);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
PARSER_END(Parser)
SKIP : { " " | "\r" | "\n" | "\t" }
TOKEN: {
< DEF: "DEF" >
| < NAME: <LETTER>(<LETTER>|<DIGIT>)* >
| < #LETTER: ["a"-"z", "A"-"Z", "_"] >
| < #DIGIT: ["0"-"9"] >
| < PLUS: "+" >
| < MUL: "*" >
| < LEFT: "{" >
| < RIGHT: "}" >
| < NUMBER: (<DIGIT>)+ >
}
Map<String, Function> program(): {
Map<String, Function> symbolTable = new HashMap<>();
}
{
(functionDefinition(symbolTable))*
{return symbolTable;}
}
void functionDefinition(Map<String, Function> table): {
Expression body;
Function f;
String name;
String param;
int paramCount = 0;
Map<String,Parameter> params = new HashMap<String,Parameter>();
}
{
<DEF> name=<NAME>.image (
param=<NAME>.image {params.put(param, new Parameter(paramCount++));}
)*
body=functionBody(params)
{ f = new Function(paramCount, body); }
";"
{
if (table.containsKey(name)) {
System.out.println("Function " + name + "already exists");
} else {
table.put(name, f);
}
}
}
Expression functionBody(Map<String,Parameter> params): {
Expression e;
}
{
<LEFT>
e=expression(params)
<RIGHT>
{
return e;
}
}
Expression expression(Map<String,Parameter> params): {
Expression e;
}
{
e=additiveExpression(params)
{
return e;
}
}
Expression additiveExpression(Map<String,Parameter> params): {
Expression e, f;
}
{
e=multiplicativeExpression(params)
(<PLUS> f=multiplicativeExpression(params) {
e = Expression.add(e,f);
})*
{
return e;
}
}
Expression multiplicativeExpression(Map<String,Parameter> params): {
Expression e, f;
}
{
e=unaryExpression(params) (<MUL> f=unaryExpression(params) {
e = Expression.mul(e,f);
})*
{
return e;
}
}
Expression unaryExpression(Map<String,Parameter> params): {
Expression e;
String s;
int n;
Expression[] parms;
}
{
(
n=number() {
e = Expression.number(n);
}
| s=<NAME>.image ( parms=parameterList(params) {
e = Expression.call(s, parms);
} | {
Parameter p = params.get(s);
if (p != null) {
e = Expression.param(p.index);
} else {
// no parameter found: assume it's a parameterless function
e = Expression.call(s);
}
})
)
{
return e;
}
}
int number(): {
String s;
}
{
s=<NUMBER>.image
{
return Integer.parseInt(s);
}
}
Expression[] parameterList(Map<String,Parameter> params): {
List<Expression> parms = new ArrayList<Expression>();
Expression p;
}
{
"("
(
p=expression(params) { parms.add(p); }
( "," p=expression(params){ parms.add(p); } )*
)?
")"
{
return parms.toArray(new Expression[parms.size()]);
}
}
Function class, Function.java:
package org.tastefuljava.minilang;
public class Function {
public final int paramCount;
public final Expression body;
public Function(int paramCount, Expression body) {
this.paramCount = paramCount;
this.body = body;
}
}
Parameter class, Parameter.java:
package org.tastefuljava.minilang;
public class Parameter {
public final int index;
public Parameter(int index) {
this.index = index;
}
}
Expression interface, Expression.java:
package org.tastefuljava.minilang;
import java.util.Map;
public interface Expression {
public int evaluate(Map<String,Function> table, int... parms);
public static Expression number(int x) {
return (table, parms) -> x;
}
public static Expression add(Expression a, Expression b) {
return (table, parms) ->
a.evaluate(table, parms) + b.evaluate(table, parms);
}
public static Expression mul(Expression a, Expression b) {
return (table, parms) ->
a.evaluate(table, parms) * b.evaluate(table, parms);
}
public static Expression call(String name, Expression... parms) {
return (table, oldParms) -> {
Function f = table.get(name);
if (f == null) {
System.out.println("Unknown function " + name);
return 0;
} else if (f.paramCount != parms.length) {
System.out.println("Wrong number of parameters for function "
+ name + ": expected " + f.paramCount
+ ", actual " + parms.length);
return 0;
}
int[] newParms = new int[parms.length];
for (int i = 0; i < parms.length; ++i) {
newParms[i] = parms[i].evaluate(table, oldParms);
}
return f.body.evaluate(table, newParms);
};
}
public static Expression param(int index) {
return (table, parms) -> parms[index];
}
}
You need your FunctionBody nonterminal to return the intermediate representation for the function.
The problem is that you don't have an intermediate representation. You are trying to do direct interpretation, i.e. you are executing the program at the same time that it is parsed. That's fine for simple interactive calculators like the one in this ancient tutorial. However, once you start dealing with loops and functions you really need to generate (and later execute) intermediate code. See this FAQ for why.
If you are are taking a course, ask your instructor what he or she or they would recommend for intermediate code.
If you don't have an instructor, my advice is to generate machine code for a stack machine, since you are already using a stack for execution. See, for example, my notes on generating machine code for a stack machine in a recursive descent parser, especially pages 14 to 20; I didn't use a parser generator for this, but that shouldn't matter. (I use ^ for sequence concatenation, so, for example, m := m^div just means add a div instruction to the end of the intermediate representation.)
Any book on compilers will also cover this sort of stuff.
Tom Copeland's book probably has lots more information and is JavaCC specific.
I have a Jenkins pipeline that consists of:
parameters.groovy
static Map<String, String> doMapping() {
[
'a-b-c': '1-2-3',
'd-e-f': '4-5-6',
'g-h-i': '7-8-9'
]
}
return this
Jenkinsfile
Map<String, String> myMap = null
...
pipeline {
parameters {
string(name: 'param1')
}
stages {
stage('Stage 1', {
...
steps {
script {
myMap = load('parameters.groovy').doMapping()
}
}
}
stage('Stage 2', {
...
steps {
script {
String p = ""
String v = ""
if (params.PARAM1?.trim()) {
p = params.PARAM1
v = myMap.get(p)
if (v == null) { // Set v to p if not found in the map
v = p
}
echo "v = ${v}"
v = myMap.get('d-e-f')
if (v == null) {
v = p
}
echo "v = ${v}"
}
}
}
}
}
}
Input:
param1 = d-e-f
Output:
[Pipeline] echo
v = d-e-f
[Pipeline] echo
v = 4-5-6
Why is a map entry not found when variable is used as the key and is found when hardcoded?
I tried to check for empty spaces but there was none, I checked types of map keys, p, params.PARAM1 and v and they are java.lang.String.
import groovy.util.slurpersupport.Node
import groovy.util.slurpersupport.NodeChild
/**
* Created by on 2017-03-25.
*/
File file = new File("/Users/user1/output/1")
XMLLoader xmlLoader = new XMLLoader(file);
HashMap<String, XmlSlurper> temp = xmlLoader.sendNodes()
JunitDataParser junitParser = new JunitDataParser(temp)
junitParser.populateStats()
public class XMLLoader {
HashMap<String, XmlSlurper> rootNodes; // Collection of root nodes for Junit xml files
public XMLLoader(File junitFile) {
rootNodes = new ArrayList<>()
// If file is directory then closure will search directory to find valid xml files
if (junitFile.isDirectory()) {
junitFile.eachFile {
if (validateFile(it)) {
rootNodes.put(it.name, new XmlSlurper().parse(it)) // Load each fine into arraylist of XMLSlurpers
}
}
} else {
if (validateFile(junitFile)) {
rootNodes.put(junitFile.name, new XmlSlurper().parse(it))
// Load single fine into arraylist of XMLSlurpers
}
}
}
boolean validateFile(File checkFile) {
if (checkFile.name.endsWith('.xml')) {
assert checkFile.exists(): "The file entered could not be be read"
assert checkFile.canRead(): "The file entered could not be be read"
return true;
}
return false
}
HashMap<String, XmlSlurper> sendNodes() {
return rootNodes
}
}
public class JunitDataParser extends GeneralDataParser {
def JunitDataParser(HashMap<String, XmlSlurper> rootNodes) {
super(rootNodes)
}
HashMap<String, ArrayList<TestSuites>> getPopulatedData() {
return super.getPopulatedData()
}
void populateStats() {
ArrayList<TestSuite> stats = getTestSuites();
}
ArrayList<TestSuite> getTestSuites() {
ArrayList<TestSuite> testSuites = new ArrayList<>()
rootNodes.get("first.xml").'**'.findAll {
(it.name().equals("testsuite")) && (it.children().getAt(0).name().equals("testcase"))
}.each {
TestSuite temp = new TestSuite(it.attributes().get("name"), it.attributes().get("tests").toInteger(), it.attributes().get("errors").toInteger(), it.attributes().get("time"), it.attributes().get("timestamp"), getTestCases(it))
testSuites.add(temp)
}
return testSuites
}
ArrayList<TestCase> getTestCases(NodeChild testSuiteNode) {
ArrayList<TestCase> testCases = new ArrayList<>()
testSuiteNode.childNodes().each {
String time;
if (time!=null && time.length()>0) {
time = it.attributes().get("time")
} else {
time = "Time Not Found"
}
testCases.add(new TestCase(it.attributes().get("name"), getOutCome(it), time))
}
return testCases
}
TestResult getOutCome(Node testCaseNode) {
String testMessage = "hi"
int testOutcome = 0;
if (testCaseNode.childNodes().size() != 0) {
testCaseNode.childNodes().each {
it.attributes().each {
testMessage = testMessage + "\n $it.key : $it.value"
}
}
testOutcome =1
}
TestResult temp = new TestResult(0,testMessage)
return temp
}
}
// The Base abstract class that all additional parsers should extend and populate
public abstract class GeneralDataParser {
HashMap<String, XmlSlurper> rootNodes
HashMap<String, ArrayList<TestSuites>> populatedData
public GeneralDataParser(HashMap<String, XmlSlurper> rootNodes) {
this.rootNodes = rootNodes
}
abstract void populateStats()
abstract ArrayList<TestSuite> getTestSuites()
abstract ArrayList<TestCase> getTestCases(NodeChild testSuiteNodes)
abstract TestResult getOutCome(Node testCaseNode)
}
public class TestSuites {
ArrayList<TestSuite> testSuites
TestSuites(ArrayList<TestSuite> testSuites) {
this.testSuites = testSuites
}
}
public class TestSuite {
String testSuiteName
int numOfTests
int numOfErrors
int numOfFailures
String timeTaken;
String timeStamp;
ArrayList<TestCase> testCases
TestSuite(String testSuiteName, int numOfTests, int numOfErrors, int numOfFailures, String timeTaken, String timeStamp, ArrayList<TestCase> testCases) {
this.testSuiteName = testSuiteName
this.numOfTests = numOfTests
this.numOfErrors = numOfErrors
this.numOfFailures = numOfFailures
this.timeTaken = timeTaken
this.timeStamp = timeStamp
this.testCases = testCases
}
}
public class TestCase {
String testCasename
TestResult testOutcome
String testCaseTime = ""
TestCase(String testCasename, TestResult testOutcome, String testCaseTime) {
this.testCasename = testCasename
this.testOutcome = testOutcome
this.testCaseTime = testCaseTime
}
}
public class TestResult {
int valOfResult
String textOfResult
TestResult(int valOfResult, String textOfResult) {
this.valOfResult = valOfResult
this.textOfResult = textOfResult
}
}
I keep getting a matching constructor could not be found can anyone see any issues?
Caught: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: TestSuite(java.lang.String, java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.String, java.util.ArrayList)
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: TestSuite(java.lang.String, java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.String, java.util.ArrayList)
at JunitDataParser$_getTestSuites_closure2.doCall(JunitXMLToBeautifulHTML.groovy:70)
at JunitDataParser.getTestSuites(JunitXMLToBeautifulHTML.groovy:67)
at JunitDataParser.populateStats(JunitXMLToBeautifulHTML.groovy:62)
at JunitDataParser$populateStats.call(Unknown Source)
at JunitXMLToBeautifulHTML.run(JunitXMLToBeautifulHTML.groovy:13)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
The error message is correct.
The constructor's signature is:
TestSuite(String testSuiteName, int numOfTests, int numOfErrors, int numOfFailures, String timeTaken, String timeStamp, ArrayList<TestCase> testCases)
And you're trying to use:
new TestSuite(it.attributes().get("name"), it.attributes().get("tests").toInteger(), it.attributes().get("errors").toInteger(), it.attributes().get("time"), it.attributes().get("timestamp"), getTestCases(it))
So you're not passing a numOfFailures.
I have this code, in file that have the name dao.abstract.class.php, but I am getting this error when I surf the site, and admin panel. Strict Standards: Static function DAO::makeItem() should not be abstract in dao.abstract.class.php on line 15
<?php
abstract class DAO
{
protected $m_sql;
protected $m_sqlId = -1;
protected $m_orderBy;
protected $m_orderByField;
protected $m_orderByType;
**abstract public function selectFromId($iditem);
abstract public function delete($iditem);
abstract public function save($object);
abstract static function makeItem($resultRow);
abstract protected function createSql();**
protected function __construct($sql, $sortField, $sortType)
{
$this->m_sql = $sql;
$this->m_orderBy = array($sortField => $sortType);
$this->m_orderByField = $sortField;
$this->m_orderByType = $sortType;
}
public function setOrderBy($order_by, $field, $type)
{
$this->m_orderBy = $order_by;
$this->m_orderByField = $field;
$this->m_orderByType = $type;
}
public function getOrderBy()
{
return $this->m_orderBy;
}
public function getOrderByField()
{
return $this->m_orderByField;
}
public function getOrderByType()
{
return $this->m_orderByType;
}
protected function executeQuery($objectArray = true, $renew = false)
{
if ($result = mysql_query($this->m_sql->getCommand($this->m_sqlId)))
{
if($objectArray == true)
{
$item = array();
while($row = mysql_fetch_assoc($result))
$item[] = $this->makeComplexItem($row);
}
elseif($row = mysql_fetch_assoc($result))
$item = $this->makeComplexItem($row);
else
$item = null;
}
else
Die(mysql_error().'<br/>'.$this->m_sql->getCommand());
mysql_free_result($result);
if($renew == true)
$this->m_sqlId = -1;
return $item;
}
protected function executeOneFieldQuery($array = true)
{
if ($result = mysql_query($this->m_sql->getCommand()))
{
if($array == true)
{
$item = array();
while($row = mysql_fetch_row($result))
$item[] = $row[0];
}
elseif($row = mysql_fetch_row($result))
$item = $row[0];
else
$item = null;
mysql_free_result($result);
return $item;
}
else
Die(mysql_error());
}
protected function executeSave($itemId)
{
if($itemId == -1)
$this->m_sql->setExecMode(Clarity::EXEC_INSERT);
else
$this->m_sql->setExecMode(Clarity::EXEC_UPDATE);
if ($itemId == -1 AND mysql_query($this->m_sql->getCommand()))
return mysql_insert_id();
elseif($itemId > 0 AND mysql_query($this->m_sql->getCommand()))
return $itemId;
else
Die(mysql_error().'<br/>'.$this->m_sql->getCommand());
}
protected function executeDelete()
{
$this->m_sql->setExecMode(Clarity::EXEC_DELETE);
if(mysql_query($this->m_sql->getCommand()))
return mysql_affected_rows();
else
die(mysql_error());
}
}
?>
You can move this declaration to an interface.
Like this:
interface myInterface
{
static function makeItem($resultRow);
}
abstract class DAO implements myInterface
{
[...]
}
I want want to print all the fields in object and if one of the field is object i want to print it fields and on and on (with recursion).
I wrote function but i get this error once i've entering to recursion.
Field '_str1' defined on type 'ConsoleApplication1.StringTest' is not
a field on the target object which is of type
'System.Reflection.RtFieldInfo'.
This is the Code:
static void OutPutObject(dynamic dyn,Type pType)
{
List<string> lFieldsList = new List<string>();
// Get the type of MyClass.
Type lType = pType;
// Get the FieldInfo of MyClass.
FieldInfo[] myFields = lType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
// Display the values of the fields.
for (int i = 0; i < myFields.Length; i++)
{
if (myFields[i].FieldType.IsClass && myFields[i].FieldType.Name != "String")
{
Type tType = myFields[i].FieldType.GetType();
OutPutObject(myFields[i], pType);
}
else
{
Console.WriteLine(string.Format("{0}: {1}", myFields[i].Name, myFields[i].GetValue(dyn)));
}
}
}
public class IntTest
{
private int a = 1;
private int b = 2;
}
public class StringTest
{
private string _str1;
private string _str2;
private IntTest intl;
public StringTest()
{
_str1 = "str1";
_str2 = "str2";
}
}
I've change your code and now it works!
Please notice that the inner classes must have default constructor.
static void OutPutObject(object obj, Type pType, bool isFirst)
{
// Get the FieldInfo of MyClass.
FieldInfo[] myFields = pType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
// Display the values of the fields.
for (int i = 0; i < myFields.Length; i++)
{
if (myFields[i].FieldType.IsPrimitive || myFields[i].FieldType == typeof(Decimal) || myFields[i].FieldType == typeof(String))
{
if (!isFirst)
{
object temp = Activator.CreateInstance(pType);
obj = temp;
}
Console.WriteLine(string.Format("{0}: {1}", myFields[i].Name, myFields[i].GetValue(obj)));
}
else if (myFields[i].FieldType.IsClass)
{
Type tType = myFields[i].FieldType;
OutPutObject(myFields[i], tType, false);
}
}
}
You can use following lines to write object public fields. I tested on .NET 4.0
Type type = obj.GetType();
foreach (var f in type.GetFields().Where(f => f.IsPublic)) {
Console.WriteLine("Name: "+f.Name+" Value: "+ f.GetValue(obj) );
}