mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 17:04:42 -04:00
refactoring and added a static context
This commit is contained in:
parent
a5d104076a
commit
11588d270f
@ -42,7 +42,7 @@ public class Context {
|
|||||||
*
|
*
|
||||||
* @param name the name
|
* @param name the name
|
||||||
* @return the value
|
* @return the value
|
||||||
* @throws EvalException {@link EvalException
|
* @throws EvalException EvalException
|
||||||
*/
|
*/
|
||||||
public Object getVar(String name) throws EvalException {
|
public Object getVar(String name) throws EvalException {
|
||||||
Object v = map.get(name);
|
Object v = map.get(name);
|
||||||
|
@ -84,7 +84,7 @@ public interface Expression {
|
|||||||
static Object add(Object a, Object b) throws EvalException {
|
static Object add(Object a, Object b) throws EvalException {
|
||||||
if (a instanceof Number && b instanceof Number)
|
if (a instanceof Number && b instanceof Number)
|
||||||
return ((Number) a).longValue() + ((Number) b).longValue();
|
return ((Number) a).longValue() + ((Number) b).longValue();
|
||||||
if (a instanceof String && b instanceof String)
|
if (a instanceof String || b instanceof String)
|
||||||
return a.toString() + b.toString();
|
return a.toString() + b.toString();
|
||||||
throw new EvalException("arguments must be int or string, not " + a.getClass().getSimpleName() + "+" + b.getClass().getSimpleName());
|
throw new EvalException("arguments must be int or string, not " + a.getClass().getSimpleName() + "+" + b.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ public class Parser {
|
|||||||
|
|
||||||
private final Tokenizer tok;
|
private final Tokenizer tok;
|
||||||
private HashMap<String, Function> functions;
|
private HashMap<String, Function> functions;
|
||||||
|
private Context staticContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance
|
* Create a new instance
|
||||||
@ -47,23 +48,37 @@ public class Parser {
|
|||||||
public Parser(Reader reader) {
|
public Parser(Reader reader) {
|
||||||
tok = new Tokenizer(reader);
|
tok = new Tokenizer(reader);
|
||||||
functions = new HashMap<>();
|
functions = new HashMap<>();
|
||||||
functions.put("format", new FunctionFormat());
|
addFunction("format", new FunctionFormat());
|
||||||
|
|
||||||
functions.put("isset", new FunctionIsSet());
|
addFunction("isset", new FunctionIsSet());
|
||||||
|
|
||||||
functions.put("newList", new Function(0) {
|
addFunction("newList", new Function(0) {
|
||||||
@Override
|
@Override
|
||||||
public Object calcValue(Context c, ArrayList<Expression> args) {
|
public Object calcValue(Context c, ArrayList<Expression> args) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
functions.put("newMap", new Function(0) {
|
addFunction("newMap", new Function(0) {
|
||||||
@Override
|
@Override
|
||||||
public Object calcValue(Context c, ArrayList<Expression> args) {
|
public Object calcValue(Context c, ArrayList<Expression> args) {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
staticContext = new Context();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new function to the parser
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @param function the function
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public Parser addFunction(String name, Function function) {
|
||||||
|
functions.put(name, function);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,12 +93,27 @@ public class Parser {
|
|||||||
String text = tok.readText();
|
String text = tok.readText();
|
||||||
if (text.length() > 0)
|
if (text.length() > 0)
|
||||||
s.add(c -> c.print(text));
|
s.add(c -> c.print(text));
|
||||||
while (!isToken(EOF))
|
while (!isToken(EOF)) {
|
||||||
s.add(parseStatement());
|
if (isToken(STATIC)) {
|
||||||
|
Statement stat = parseStatements();
|
||||||
|
try {
|
||||||
|
stat.execute(staticContext);
|
||||||
|
} catch (EvalException e) {
|
||||||
|
throw newParserException("error evaluating static code: " + e.getMessage());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
s.add(parseStatement());
|
||||||
|
}
|
||||||
return s.optimize();
|
return s.optimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the static context of this template
|
||||||
|
*/
|
||||||
|
public Context getStaticContext() {
|
||||||
|
return staticContext;
|
||||||
|
}
|
||||||
|
|
||||||
private Statement parseStatements() throws IOException, ParserException {
|
private Statement parseStatements() throws IOException, ParserException {
|
||||||
if (isToken(OPENBRACE)) {
|
if (isToken(OPENBRACE)) {
|
||||||
Statements s = new Statements();
|
Statements s = new Statements();
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018 Helmut Neemann.
|
|
||||||
* Use of this source code is governed by the GPL v3 license
|
|
||||||
* that can be found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
package de.neemann.digital.hdl.hgs;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a template
|
|
||||||
*/
|
|
||||||
public class Template {
|
|
||||||
private final Statement s;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new template.
|
|
||||||
*
|
|
||||||
* @param text the text to parse
|
|
||||||
* @throws IOException IOException
|
|
||||||
* @throws ParserException ParserException
|
|
||||||
*/
|
|
||||||
public Template(String text) throws IOException, ParserException {
|
|
||||||
this(new StringReader(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new template.
|
|
||||||
*
|
|
||||||
* @param in the text to parse
|
|
||||||
* @throws IOException IOException
|
|
||||||
* @throws ParserException ParserException
|
|
||||||
*/
|
|
||||||
public Template(InputStream in) throws IOException, ParserException {
|
|
||||||
this(new InputStreamReader(in));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new template.
|
|
||||||
*
|
|
||||||
* @param reader the text to parse
|
|
||||||
* @throws IOException IOException
|
|
||||||
* @throws ParserException ParserException
|
|
||||||
*/
|
|
||||||
public Template(Reader reader) throws IOException, ParserException {
|
|
||||||
try {
|
|
||||||
this.s = new Parser(reader).parse();
|
|
||||||
} finally {
|
|
||||||
reader.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates the template with an empty context
|
|
||||||
*
|
|
||||||
* @return the context
|
|
||||||
* @throws EvalException EvalException
|
|
||||||
*/
|
|
||||||
public Context execute() throws EvalException {
|
|
||||||
return execute(new Context());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates the template with the given context.
|
|
||||||
* Create a new context every time this method is called!
|
|
||||||
*
|
|
||||||
* @param c the context
|
|
||||||
* @return the context
|
|
||||||
* @throws EvalException EvalException
|
|
||||||
*/
|
|
||||||
public Context execute(Context c) throws EvalException {
|
|
||||||
s.execute(c);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -17,7 +17,7 @@ public class Tokenizer {
|
|||||||
enum Token {
|
enum Token {
|
||||||
UNKNOWN, IDENT, AND, OR, XOR, NOT, OPEN, CLOSE, NUMBER, EOL, EOF, SHIFTLEFT, SHIFTRIGHT, COMMA, EQUAL,
|
UNKNOWN, IDENT, AND, OR, XOR, NOT, OPEN, CLOSE, NUMBER, EOL, EOF, SHIFTLEFT, SHIFTRIGHT, COMMA, EQUAL,
|
||||||
ADD, SUB, MUL, GREATER, SMALER, DIV, MOD, END, IF, ELSE, FOR, WHILE, SEMICOLON, NOTEQUAL, STRING,
|
ADD, SUB, MUL, GREATER, SMALER, DIV, MOD, END, IF, ELSE, FOR, WHILE, SEMICOLON, NOTEQUAL, STRING,
|
||||||
OPENBRACE, CLOSEDBRACE, CODEEND, OPENSQUARE, CLOSEDSQUARE, DOT, PRINT, PRINTF
|
OPENBRACE, CLOSEDBRACE, CODEEND, OPENSQUARE, CLOSEDSQUARE, DOT, PRINT, STATIC, PRINTF
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HashMap<String, Token> statementMap = new HashMap<>();
|
private static HashMap<String, Token> statementMap = new HashMap<>();
|
||||||
@ -112,6 +112,9 @@ public class Tokenizer {
|
|||||||
case '.':
|
case '.':
|
||||||
token = Token.DOT;
|
token = Token.DOT;
|
||||||
break;
|
break;
|
||||||
|
case '@':
|
||||||
|
token = Token.STATIC;
|
||||||
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
token = Token.SEMICOLON;
|
token = Token.SEMICOLON;
|
||||||
break;
|
break;
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.hdl.hgs.function;
|
||||||
|
|
||||||
|
import de.neemann.digital.hdl.hgs.Context;
|
||||||
|
import de.neemann.digital.hdl.hgs.EvalException;
|
||||||
|
import de.neemann.digital.hdl.hgs.Expression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple function adapter to implement a function with one argument of type long
|
||||||
|
*/
|
||||||
|
public abstract class FuncAdapter extends Function {
|
||||||
|
/**
|
||||||
|
* Creates a new function
|
||||||
|
*/
|
||||||
|
public FuncAdapter() {
|
||||||
|
super(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object calcValue(Context c, ArrayList<Expression> args) throws EvalException {
|
||||||
|
return f(Expression.toLong(args.get(0).value(c)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function
|
||||||
|
*
|
||||||
|
* @param n the argument
|
||||||
|
* @return the result
|
||||||
|
*/
|
||||||
|
protected abstract Object f(long n);
|
||||||
|
}
|
@ -32,23 +32,29 @@ public class ReferenceToArray implements Reference {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(Context context, Object value) throws EvalException {
|
public void set(Context context, Object value) throws EvalException {
|
||||||
Object ar = parent.get(context);
|
Object listObj = parent.get(context);
|
||||||
if (ar instanceof List) {
|
if (listObj instanceof List) {
|
||||||
final List list = (List) ar;
|
final List list = (List) listObj;
|
||||||
final int index = Expression.toInt(this.index.value(context));
|
final int i = Expression.toInt(index.value(context));
|
||||||
while (list.size() <= index)
|
if (i < 0)
|
||||||
|
throw new EvalException("index out of bounds: " + i);
|
||||||
|
while (list.size() <= i)
|
||||||
list.add(null);
|
list.add(null);
|
||||||
list.set(index, value);
|
list.set(i, value);
|
||||||
} else
|
} else
|
||||||
throw new EvalException("not an array: " + ar);
|
throw new EvalException("not an array: " + listObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get(Context context) throws EvalException {
|
public Object get(Context context) throws EvalException {
|
||||||
Object ar = parent.get(context);
|
Object listObj = parent.get(context);
|
||||||
if (ar instanceof List)
|
if (listObj instanceof List) {
|
||||||
return ((List) ar).get(Expression.toInt(index.value(context)));
|
final List list = (List) listObj;
|
||||||
else
|
final int i = Expression.toInt(index.value(context));
|
||||||
throw new EvalException("not an array: " + ar);
|
if (i >= list.size() || i < 0)
|
||||||
|
throw new EvalException("index out of bounds: " + i);
|
||||||
|
return list.get(i);
|
||||||
|
} else
|
||||||
|
throw new EvalException("not an array: " + listObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public class ReferenceToStruct implements Reference {
|
|||||||
Key key = (Key) k.get(null);
|
Key key = (Key) k.get(null);
|
||||||
KEY_MAP.put(key.getKey(), key);
|
KEY_MAP.put(key.getKey(), key);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new RuntimeException("error ecessing the Keys");
|
throw new RuntimeException("error accessing the Keys");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ public class ReferenceToStruct implements Reference {
|
|||||||
if (m instanceof Map)
|
if (m instanceof Map)
|
||||||
((Map) m).put(name, value);
|
((Map) m).put(name, value);
|
||||||
else
|
else
|
||||||
throw new EvalException("not a map");
|
throw new EvalException("not a map: " + m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,13 +62,13 @@ public class ReferenceToStruct implements Reference {
|
|||||||
Object m = parent.get(context);
|
Object m = parent.get(context);
|
||||||
if (m instanceof Map)
|
if (m instanceof Map)
|
||||||
return ((Map) m).get(name);
|
return ((Map) m).get(name);
|
||||||
if (m instanceof ElementAttributes) {
|
else if (m instanceof ElementAttributes) {
|
||||||
Key key = KEY_MAP.get(name);
|
Key key = KEY_MAP.get(name);
|
||||||
if (key == null)
|
if (key == null)
|
||||||
throw new EvalException("invallid key: " + name);
|
throw new EvalException("invalid key: " + name);
|
||||||
return ((ElementAttributes) m).get(key);
|
return ((ElementAttributes) m).get(key);
|
||||||
} else
|
} else
|
||||||
throw new EvalException("not a map");
|
throw new EvalException("not a map: " + m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,9 +7,10 @@ package de.neemann.digital.hdl.hgs;
|
|||||||
|
|
||||||
import de.neemann.digital.core.element.ElementAttributes;
|
import de.neemann.digital.core.element.ElementAttributes;
|
||||||
import de.neemann.digital.core.element.Keys;
|
import de.neemann.digital.core.element.Keys;
|
||||||
|
import de.neemann.digital.hdl.hgs.function.FuncAdapter;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -36,13 +37,8 @@ public class ParserTest extends TestCase {
|
|||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
assertEquals("Hallo4", new Parser("\"Hallo\" + (2*2)").parseExpression().value(new Context()));
|
||||||
new Parser("1+\"Hallo\"").parseExpression().value(new Context());
|
assertEquals("Hallo_true", new Parser("\"Hallo_\" + (1<2)").parseExpression().value(new Context()));
|
||||||
fail();
|
|
||||||
} catch (EvalException e) {
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseExpressionCompare() throws IOException, ParserException, EvalException {
|
public void testParseExpressionCompare() throws IOException, ParserException, EvalException {
|
||||||
@ -82,73 +78,89 @@ public class ParserTest extends TestCase {
|
|||||||
.value(new Context()
|
.value(new Context()
|
||||||
.setVar("a", true)));
|
.setVar("a", true)));
|
||||||
|
|
||||||
assertEquals("true", new Template("<? if (1) print(\"true\"); ?>").execute().toString());
|
assertEquals("true", exec("<? if (1) print(\"true\"); ?>").toString());
|
||||||
assertEquals("", new Template("<? if (0) print(\"true\"); ?>").execute().toString());
|
assertEquals("", exec("<? if (0) print(\"true\"); ?>").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context exec(String code) throws IOException, ParserException, EvalException {
|
||||||
|
return exec(code, new Context());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context exec(String code, Context c) throws IOException, ParserException, EvalException {
|
||||||
|
new Parser(code).parse().execute(c);
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateSimple() throws IOException, ParserException, EvalException {
|
public void testParseTemplateSimple() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello World!").execute();
|
assertEquals("Hello World!", exec("Hello World!", new Context()).toString());
|
||||||
assertEquals("Hello World!", c.toString());
|
}
|
||||||
|
|
||||||
|
private Context exec(Statement s) throws EvalException {
|
||||||
|
return exec(s, new Context());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context exec(Statement s, Context c) throws EvalException {
|
||||||
|
s.execute(c);
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateVariable() throws IOException, ParserException, EvalException {
|
public void testParseTemplateVariable() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello <? =a ?> World!").execute(new Context().setVar("a", "My"));
|
Context c = exec("Hello <? =a ?> World!", new Context().setVar("a", "My"));
|
||||||
assertEquals("Hello My World!", c.toString());
|
assertEquals("Hello My World!", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateCodeOnly() throws IOException, ParserException, EvalException {
|
public void testParseTemplateCodeOnly() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("<? =a ?>").execute(new Context().setVar("a", "My"));
|
Context c = exec("<? =a ?>", new Context().setVar("a", "My"));
|
||||||
assertEquals("My", c.toString());
|
assertEquals("My", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplatePrint() throws IOException, ParserException, EvalException {
|
public void testParseTemplatePrint() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello <? print(\"My\"); ?> World!").execute();
|
Context c = exec("Hello <? print(\"My\"); ?> World!");
|
||||||
assertEquals("Hello My World!", c.toString());
|
assertEquals("Hello My World!", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateFor() throws IOException, ParserException, EvalException {
|
public void testParseTemplateFor() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello <? for (i=0;i<10;i++) print(i); ?> World!").execute();
|
Context c = exec("Hello <? for (i=0;i<10;i++) print(i); ?> World!");
|
||||||
assertEquals("Hello 0123456789 World!", c.toString());
|
assertEquals("Hello 0123456789 World!", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateForStatements() throws IOException, ParserException, EvalException {
|
public void testParseTemplateForStatements() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("<? for (i=0;i<10;i++) { print(i, 9-i); } ?>").execute();
|
Context c = exec("<? for (i=0;i<10;i++) { print(i, 9-i); } ?>");
|
||||||
assertEquals("09182736455463728190", c.toString());
|
assertEquals("09182736455463728190", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateForNested() throws IOException, ParserException, EvalException {
|
public void testParseTemplateForNested() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello <? for (i=0;i<10;i++) { ?>n<? } ?> World!").execute();
|
Context c = exec("Hello <? for (i=0;i<10;i++) { ?>n<? } ?> World!");
|
||||||
assertEquals("Hello nnnnnnnnnn World!", c.toString());
|
assertEquals("Hello nnnnnnnnnn World!", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateForNested2() throws IOException, ParserException, EvalException {
|
public void testParseTemplateForNested2() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello <? for (i=0;i<3;i++) { ?>(<? for(j=0;j<2;j++) { ?>:<? } ?>)<? } ?> World!").execute();
|
Context c = exec("Hello <? for (i=0;i<3;i++) { ?>(<? for(j=0;j<2;j++) { ?>:<? } ?>)<? } ?> World!");
|
||||||
assertEquals("Hello (::)(::)(::) World!", c.toString());
|
assertEquals("Hello (::)(::)(::) World!", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateForNested3() throws IOException, ParserException, EvalException {
|
public void testParseTemplateForNested3() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("Hello <? for (i=1;i<4;i++) { ?>(<? for(j=1;j<3;j++) { print(i*j); } ?>)<? } ?> World!").execute();
|
Context c = exec("Hello <? for (i=1;i<4;i++) { ?>(<? for(j=1;j<3;j++) { print(i*j); } ?>)<? } ?> World!");
|
||||||
assertEquals("Hello (12)(24)(36) World!", c.toString());
|
assertEquals("Hello (12)(24)(36) World!", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testParseTemplateElementAttibutes() throws IOException, ParserException, EvalException {
|
public void testParseTemplateElementAttibutes() throws IOException, ParserException, EvalException {
|
||||||
ElementAttributes attr = new ElementAttributes().set(Keys.BITS, 5);
|
ElementAttributes attr = new ElementAttributes().set(Keys.BITS, 5);
|
||||||
Context c = new Context().setVar("elem", attr);
|
Context c = exec("bits=<?=elem.Bits?>;", new Context().setVar("elem", attr));
|
||||||
new Template("bits=<?=elem.Bits?>;").execute(c);
|
|
||||||
assertEquals("bits=5;", c.toString());
|
assertEquals("bits=5;", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateFormat() throws IOException, ParserException, EvalException {
|
public void testParseTemplateFormat() throws IOException, ParserException, EvalException {
|
||||||
ElementAttributes attr = new ElementAttributes().set(Keys.BITS, 17);
|
ElementAttributes attr = new ElementAttributes().set(Keys.BITS, 17);
|
||||||
Context c = new Context().setVar("elem", attr);
|
Context c = new Context().setVar("elem", attr);
|
||||||
new Template("<? a=format(\"hex=%x;\",elem.Bits); print(a);?>").execute(c);
|
exec("<? a=format(\"hex=%x;\",elem.Bits); print(a);?>", c);
|
||||||
assertEquals("hex=11;", c.toString());
|
assertEquals("hex=11;", c.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateArray() throws IOException, ParserException, EvalException {
|
public void testParseTemplateArray() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Context().setVar("a", new ArrayList());
|
Context c = new Context().setVar("a", new ArrayList());
|
||||||
new Template("<? a[0]=1; a[1]=7; print(a[1]); ?>;").execute(c);
|
exec("<? a[0]=1; a[1]=7; print(a[1]); ?>;", c);
|
||||||
assertEquals("7;", c.toString());
|
assertEquals("7;", c.toString());
|
||||||
Object lo = c.getVar("a");
|
Object lo = c.getVar("a");
|
||||||
assertTrue(lo instanceof List);
|
assertTrue(lo instanceof List);
|
||||||
@ -159,7 +171,7 @@ public class ParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testParseTemplateMap() throws IOException, ParserException, EvalException {
|
public void testParseTemplateMap() throws IOException, ParserException, EvalException {
|
||||||
Context c = new Template("<? m=newMap(); m.test=newMap(); m.test.val=7; print(m.test.val); ?>;").execute();
|
Context c = exec("<? m=newMap(); m.test=newMap(); m.test.val=7; print(m.test.val); ?>;");
|
||||||
assertEquals("7;", c.toString());
|
assertEquals("7;", c.toString());
|
||||||
Object mo = c.getVar("m");
|
Object mo = c.getVar("m");
|
||||||
assertTrue(mo instanceof Map);
|
assertTrue(mo instanceof Map);
|
||||||
@ -168,15 +180,63 @@ public class ParserTest extends TestCase {
|
|||||||
assertEquals(7L, ((Map) mo).get("val"));
|
assertEquals(7L, ((Map) mo).get("val"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testParseTemplateMapError() throws IOException, ParserException {
|
||||||
|
try {
|
||||||
|
Context c = exec("<? m=1; m.test=2; ?>;");
|
||||||
|
fail();
|
||||||
|
} catch (EvalException e) {
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseTemplateArrayError() throws IOException, ParserException {
|
||||||
|
try {
|
||||||
|
Context c = exec("<? m=1; m[0]=2; ?>;");
|
||||||
|
fail();
|
||||||
|
} catch (EvalException e) {
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testParseTemplateIsSet() throws IOException, ParserException, EvalException {
|
public void testParseTemplateIsSet() throws IOException, ParserException, EvalException {
|
||||||
Template t = new Template("<? if (isset(m)) print(m); else print(\"false\"); ?>;");
|
Statement t = new Parser("<? if (isset(m)) print(m); else print(\"false\"); ?>;").parse();
|
||||||
assertEquals("false;", t.execute().toString());
|
assertEquals("false;", exec(t).toString());
|
||||||
assertEquals("4;", t.execute(new Context().setVar("m", 4)).toString());
|
assertEquals("4;", exec(t, new Context().setVar("m", 4)).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testComment() throws IOException, ParserException, EvalException {
|
public void testComment() throws IOException, ParserException, EvalException {
|
||||||
Template t = new Template("<? // comment\nprint(\"false\"); // zzz\n ?>;");
|
Context c = exec("<? // comment\nprint(\"false\"); // zzz\n ?>;");
|
||||||
assertEquals("false;", t.execute().toString());
|
assertEquals("false;", c.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddFunction() throws IOException, ParserException, EvalException {
|
||||||
|
Statement s = new Parser("a : in <?=type(elem.Bits)?>;")
|
||||||
|
.addFunction("type", new FuncAdapter() {
|
||||||
|
@Override
|
||||||
|
protected Object f(long n) {
|
||||||
|
if (n == 1)
|
||||||
|
return "std_logic";
|
||||||
|
else
|
||||||
|
return "std_logic_vector(" + (n - 1) + " downto 0)";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.parse();
|
||||||
|
assertEquals("a : in std_logic;",
|
||||||
|
exec(s, new Context()
|
||||||
|
.setVar("elem", new ElementAttributes())).toString());
|
||||||
|
assertEquals("a : in std_logic_vector(5 downto 0);",
|
||||||
|
exec(s, new Context()
|
||||||
|
.setVar("elem", new ElementAttributes().setBits(6))).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStatic() throws IOException, ParserException {
|
||||||
|
Parser p = new Parser("generic a; <? @gen[0]=\"a\"; ?>");
|
||||||
|
final ArrayList<Object> generics = new ArrayList<>();
|
||||||
|
p.getStaticContext().setVar("gen", generics);
|
||||||
|
p.parse();
|
||||||
|
|
||||||
|
assertEquals(1, generics.size());
|
||||||
|
assertEquals("a", generics.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user