# Programming error

**URL:** <https://fspm.discourse.group/t/programming-error/350>\
**Category:** GroIMP\
**Created:** [February 20, 2025, 3:14pm UTC](https://fspm.discourse.group/t/programming-error/350 "2025-02-20T15:14:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![wanghanrui](https://avatars.discourse-cdn.com/v4/letter/w/edb3f5/32.png) [@wanghanrui](https://fspm.discourse.group/u/wanghanrui)\
**Post date:** [February 20, 2025, 3:14pm UTC](https://fspm.discourse.group/t/programming-error/350/1 "2025-02-20T15:14:10Z")

</div>

Dear community owner, when I rewrote the functional structural model of poplar tree, I modified the leaf inclination and azimuth in the sample programme to simulate the random growth of poplar tree leaves more realistically, here is my code

/\* preliminary version of the poplar model, based on sm09\_e40.gsz.

Changes:

- The determination of the maturity class (mc) is outsourced into  
a separate function getMaturityClass

- the maturity classes are applied to all objects

- each object gets a pool of assimilates (internal variable pspool)  
which can be supplied from photosynthesis (in leaves) or by transport  
from a neighbour object

- a further rgg file with functions for photosynthesis is linked

- the rule blocks photosynthesis, transport and grow are inserted.  
grow is responsible for that what up to now was done by “run”.  
run is now the superior control function for the simulation.

\*/

// import of the second, new rgg file:  
import static photosynthesis.\*;

// a simple internode with a fixed, very small start size:  
module Internode(int age, int lnfb) extends F(0.01, 0.0005)  
{  
float pspool = 0.0;  
{setShader(GREEN);}  
};

// a meristem as seed for growth:  
module Meristem(int age, int lnfb) extends Sphere(0.0005)  
{{ setShader(RED); }};

// the petiole:  
module Petiole(int age, int lnfb) extends F(0.001, 0.0001)  
{  
float pspool = 0.0;  
{setShader(GREEN);}  
};

// the blade of the leaf:  
module Blade(int age, int lnfb) extends Parallelogram(1.0, 1.0/1.3)  
{  
float pspool = 0.0;   
};

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* constants and global variables \*\*\*\*\*\*\*\*\*\*\*\*\*/

const Shader leafmat = shader(“Leaf1”);

public int time = 0; // time unit = 1 hour  
public const float PART\_OF\_A\_DAY = 1/24;  
public int nbleaves = 0;  
const int PLASTOCHRON = 48; // number of time units between the emergence  
// of two leaves

const int MAX\_GROWTHTIME\_INTERNODE = 600;  
const int MAX\_GROWTHTIME\_PETIOLE = 30;  
const int MAX\_GROWTHTIME\_LEAF = 96;

const float GROWTH\_RATE\_INTERNODE\_LENGTH = 0.001;  
const float GROWTH\_RATE\_INTERNODE\_DIAMETER = 0.000004;  
const float GROWTH\_RATE\_PETIOLE\_LENGTH = 0.00117;  
const float GROWTH\_RATE\_PETIOLE\_DIAMETER = 0.000031;  
const float GROWTH\_RATE\_LEAF\_SCALE = 0.0016;

const int NEWLEAF = 0;  
const int MATURELEAF = 1;  
const int OVERMATURELEAF = 2;

const float MAX\_GWROWTH\_INTERNODE = {0.01, 0.03, 0.02};  
const float MAX\_GWROWTH\_PETIOLE = {0.01, 0.07, 0.02};  
const float MAX\_GWROWTH\_LEAF\_SCALE = {0.04, 0.09, 0.03};

const float LEAFFORMFACTOR = 0.6;

/\*\*\*\*\*\*\*\*\*\*\* rule blocks \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

protected void init()  
{  
time = 0;  
nbleaves = 0;  
[  
Axiom ==\> Meristem(0, 0);  
]  
}

public void run()  
{  
for (apply(1)) photosynthesis(PART\_OF\_A\_DAY);  
for (apply(10)) transport(); // each time 10 transport steps  
for (apply(1)) grow();  
}

// method for the calculation of photosynthesis in the leaves  
public void photosynthesis(float part\_of\_a\_day)  
[   
s:Blade ::\>  
{  
int maturityclass = getMaturityClass(nbleaves, s[lnfb]);  
float leafarea = s[scale] \* s[scale] / 1.3 \* LEAFFORMFACTOR;  
s[pspool] += calculatePS(leafarea, maturityclass+1);  
}  
]

public void grow()  
{  
time ++;  
println(“Hour:” + time);

/\* rule block for the meristem: \*/  
[  
// 原有年龄递增规则保持不变…

```
  // 修改后的分支生成规则
  m:Meristem, (m[age] == PLASTOCHRON || m[lnfb] == 0) ==> 
     Internode(0, m[lnfb]+1) 
     [
        // 随机方位角（0-360度）和倾角（30±15度）
        RU(random(0, 360)) // 方位角随机化
        RL(30 + random(-15, 15)) // 基础倾角+随机偏移
        
        // 叶柄生成（添加小范围随机旋转）
        Petiole(0, m[lnfb]+1) 
        RH(5 + random(-2, 2)) // 微调水平角度
        RL(10 + random(-5, 5)) // 微调垂直角度
        
        // 叶片生成（添加个体随机性）
        [ 
           Blade(0, m[lnfb]+1)
           .(setShader(leafmat), setScale(0.001))
           {
              nbleaves++; 
              // 添加叶片自身随机旋转
              RU(random(-20, 20)) // 叶片方位角微调
              RL(random(-10, 10)) // 叶片倾角微调
           }
        ]
     ]
     // 分支间角度增加随机性
     RH(120 + random(-30, 30)) // 原140改为动态范围
     RU(random(-15, 15)) // 增加额外随机旋转
     Meristem(0, m[lnfb]+1);
  ]

```

/\* rule block for extension growth of the internodes: _/  
[  
i:Internode ::\>  
{  
int maturityclass = getMaturityClass(nbleaves, i[lnfb]);  
if( i[age] \< MAX\_GROWTHTIME\_INTERNODE &&  
i[length] \<= MAX\_GWROWTH\_INTERNODE[maturityclass])  
{ // length growth during the first 30 days  
i[length] += GROWTH\_RATE\_INTERNODE\_LENGTH;  
}  
i[diameter] += GROWTH\_RATE\_INTERNODE\_DIAMETER; // diam. growth always  
i[age]++; // age incrementation  
}  
]  
/_ rule block for extension of the petioles: _/  
[  
p:Petiole, (p[age] \< MAX\_GROWTHTIME\_PETIOLE) ::\>  
{  
int maturityclass = getMaturityClass(nbleaves, p[lnfb]);  
p[length] += GROWTH\_RATE\_PETIOLE\_LENGTH; // length growth  
p[diameter] += GROWTH\_RATE\_PETIOLE\_DIAMETER; // diameter growth  
p[age]++; // age incrementation  
}  
]  
/_ rule block for leaf growth: \*/  
[  
s:Blade, (s[age] \< MAX\_GROWTHTIME\_LEAF) ::\>  
{  
int maturityclass = getMaturityClass(nbleaves, s[lnfb]);  
s.setScale(s[scale] + GROWTH\_RATE\_LEAF\_SCALE);  
s[age]++;  
}  
]  
}

// 新增随机数生成函数（如果环境不支持）  
public float random(float min, float max) {  
return #rand()\*(max-min)+min; // 假设#rand()返回0-1的随机数  
}

public void transport()  
[  
b:Blade -ancestor-\> i:Internode ::\>  
{  
int lpi = nbleaves - b[lnfb] - 1;  
if (lpi \>= 4)  
{  
float r = 0.01 \* (b[pspool] - i[pspool]);  
println("basipetal photosynthate transport: " + r);  
b[pspool] :-= r;  
i[pspool] :+= r;  
}  
}  
]

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* functions for calculations \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

private int getMaturityClass(int maxleaf, int lnfb)  
{  
int maturityclass = 0;  
int lpi = maxleaf - lnfb - 1;  
if (lpi \< 5)  
maturityclass = NEWLEAF;  
else  
{  
if (lnfb \> 5)  
maturityclass = MATURELEAF;  
else  
maturityclass = OVERMATURELEAF;  
}  
return maturityclass;  
}

An error is displayed when the programme is saved.  
pfs:sm09\_e44.rgg不能打开。 发现 一个错误. pfs:sm09\_e44.rgg 139:19 - 139:21 :  
139. RL(random(-10, 10)) //  
^^  
\*\*\* 句法错误: 非期望符号  
May I ask what causes this? Is it that the program editor doesn’t integrate the random built-in function, or is it something else, thanks for the reply, forgive me as a beginner!Looking forward to your reply！

---

<div class="post-metadata">

**Author:** ![gaetanH](https://avatars.discourse-cdn.com/v4/letter/g/edb3f5/32.png) [@gaetanH](https://fspm.discourse.group/u/gaetanH)\
**Post date:** [February 21, 2025, 9:04am UTC](https://fspm.discourse.group/t/programming-error/350/2 "2025-02-21T09:04:26Z")

</div>

Hi,

It would be easier to provides support if you:

- Share only the part of the code that is leading to the error
- Translate the error message? (^^ \*\*\* 句法错误: 非期望符号 in this case)

But from what I can see your issue is that you use XL syntax in a Java block:

> [@wanghanrui](#):
>
> ```auto
> // 叶片生成（添加个体随机性）
> [ 
> Blade(0, m[lnfb]+1)
> .(setShader(leafmat), setScale(0.001))
> {
> nbleaves++; 
> // 添加叶片自身随机旋转
> RU(random(-20, 20)) // 叶片方位角微调
> RL(random(-10, 10)) // 叶片倾角微调
> }
> ]
> 
> ```

I guess that RU(random…) is the line 139.

XL blocks are defined by square brackets [and], while java blocks are defined between curly brackets { and }. The RU and RL should be out of the {} block.

So this should compile:

```auto
[ 
           Blade(0, m[lnfb]+1)
           .(setShader(leafmat), setScale(0.001))
           {
              nbleaves++; 
           }
              // 添加叶片自身随机旋转
              RU(random(-20, 20)) // 叶片方位角微调
              RL(random(-10, 10)) // 叶片倾角微调
           
        ]

```

But then, having two rotations nodes (RU and RL) without any successor doesn’t sound very useful. Their rotation will not be applied to the Blade object (if that what you wanted), nor to any following node, because they are at the end of the branch.

I would advise you to have a look at:

- [tutorials:rgg-code-structure [GroIMP wiki]](https://wiki.grogra.de/doku.php?id=tutorials:rgg-code-structure) to have a better understanding of the java/xl blocks (what you can code and where).
- [tutorials:xl-turtle-geometry [GroIMP wiki]](https://wiki.grogra.de/doku.php?id=tutorials:xl-turtle-geometry) to better understand how the turtle commands (RU, RL, …) are used in GroIMP to create 3d geometry.

---

<div class="post-metadata">

**Author:** ![wanghanrui](https://avatars.discourse-cdn.com/v4/letter/w/edb3f5/32.png) [@wanghanrui](https://fspm.discourse.group/u/wanghanrui)\
**Post date:** [February 24, 2025, 2:13pm UTC](https://fspm.discourse.group/t/programming-error/350/3 "2025-02-24T14:13:06Z")

</div>

Thank you for your reply and good luck!
