Given the map of objects that contains a list of repeating strings:
variable "input_var" = {
type = object(map(
name = string
tags = optional(list(string))
)),
default = {
"one" = {
name = "nameone"
tags = ["tag1", "tag2"]
}
"two" = {
name = "nametwo"
tags = ["tag1", "tag3"]
}
"three" = {
name = "namethree"
tags = ["tag2"]
}
"four" = {
name = "namefour"
}
}
}
I want to create a map with keys being the tags from all elements of var.input_var.
Taking the above defaults, a sample of output is:
{
"tag1": [
{
name = "nameone"
key = "one"
},
{
name = "nametwo"
key = "two"
},
],
"tag2": [
{
name = "namethree"
key = "three"
}
],
"tag3": [
{
name = "nametwo"
key = "two"
}
]
}
I was able to achieve this in a two step steps.
First is to create a unique set of tags:
locals{
tags_set = distinct(flatten([
for k, v in var.input_var: coalesce(v.tags, [])
]))
}
followed by creating the (local) map out of local.tags_set:
tags_map = { for key_tag in local.tags_set:
key_tag => flatten([for k, v in var.input_var: [
for tag in coalesce(v.tags, []) : {
key = k
name = v.name
} if tag == key_tag
]]) }
Is there a better implementation for this, in a single step and/or more efficient?
I am struggling to take the output from a Terraform function (a list block) and convert it into a list of maps, I am trying to convert
The following:
mylist = [
{
key = "mykey1"
property1 = "mykey1property1"
property2 = "mykey1property2"
},
{
key = "mykey2"
property1 = "mykey2property1"
property2 = "mykey2property2"
}
]
into:
mylistmap = {
mykey1 = {
property1 = "mykey1property1"
property2 = "mykey1property2"
}
mykey2 = {
property1 = "mykey2property1"
property2 = "mykey2property2"
}
}
I think zipmap is what I need but I cant find any decent examples to do this.
Not sure if this is the best way possible, but with some manipulation with keys and values I was able to achieve what you want:
locals {
mylist = [
{
key = "mykey1"
property1 = "mykey1property1"
property2 = "mykey1property2"
},
{
key = "mykey2"
property1 = "mykey2property1"
property2 = "mykey2property2"
}
]
mylistmap = { for i in local.mylist: i.key => {
for k,v in i: k => v if k != "key"
}
}
}
Using terraform console, this yields the following values:
> local.mylistmap
{
"mykey1" = {
"property1" = "mykey1property1"
"property2" = "mykey1property2"
}
"mykey2" = {
"property1" = "mykey2property1"
"property2" = "mykey2property2"
}
}
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 map passed as variable
dummy = {
1 = {
instances = {
"ip1" = {
a = "earth"
b = "hi"
c = 1
}
"ip2" = {
a = "world"
b = "hello"
c = 2
}
"ip3" = {
a = "planet"
b = "hey"
c = 3
}
}
}
}
Now I want construct a map as follows
value = {
"ip1" = {
b = "hi"
c = 1
}
"ip2" = {
b = "hello"
c = 2
}
"ip3" = {
b = "hey"
c = 3
}
}
I tried using for loops but nothing seems to work out
The following is what I have tried since
_meta = {
for instance in var.dummy.1.instances:
(instance.key) = {
b = instance.value.b
c = instance.value.c
}
}
But it says I cant access the key with for iteration variable
_meta = {
for key, instance in var.dummy.1.instances:
key => {
b = instance.b
c = instance.c
}
}
A for expression is a bit different from a for_each. You don't get key or value variables in a for expression and you can explicitly pull whole entries from the map as I've shown above using key, value in map as the expression form.
You also need to use a fat arrow => operator between the key and value of the generated map entries.
Provided a string like "y = 1, x = 2, w = x + y +1"
How to make .net or any language convert it into a math expression and calculate it?
Now I am more concerned regarding the logic behind it not a framework.
My logic would be the following, but it's still incomplete is there anything faster or better and also help complete the logic if it's ok???
Pseudo-code:
symbols[] = { "=","+" ... "-"}
string a = "y = 1, x = 2, w = x + y +1";
a = a.replace(" ","");
highlevelsplit = a.split("=");
for expr e in highlevelsplit
{
if(e.containts(=))
{
highlevelsplit[highlevelsplit.indexof(e)] = calc(highlevelsplit[highlevelsplit.indexof(e)+1]
}
}
function calc(string expr)
{
array[] = expr.toCharArray();
variables[][];
var c;
var currentVariable;
for int i=0; i<array.length-1; i++
{
c = array[i];
if( symbols.containts(c) )
{
if( c.equals("+"))
{
}
....
}
else if ( c.notNumber && variables.containtsKey(c))
{
}
else if ( Float.TryParse(c))
{
}
else //probably a letter?
{
variables.push(c,0);
currentVariable = c;
}
}
}