I'm in the process of testing my Python openscad_parser library (https://github.com/BelfrySCAD/openscad_parser), and comparing it to how OpenSCAD itself parses the language. I've found a few oddities in what OpenSCAD allows syntactically, that I find amusing.
You can do a C-style for loop in a list comprehension like x = [for (i = 0; i < 10; i=i+1) i];, but you CANNOT do a C-style for() in modular form. Also, intersection_for() will not take C-style syntax.
You do NOT need to specify initializer or incrementer in a C-style list comprehension for loop like i=0; x = [for (;i<10;) i];. However, if you don't have an incrementer, it will ALWAYS error out with loop counter exceeded.
Modular for() echo(42); will do nothing. It's a No-Op. Same for intersection_for() echo(42);.
For some reason, i=42; echo([for() i]); echoes 42 to the console. I expected an empty list.
The let() in x = let() 42; acts like a No-op. x just gets set to 42.
I'm sure there are more oddities in there. In any case, the parser is live, with Abstract Syntax Tree generation, a command-line code reformatter, and 850+ unit tests. It's probably usable now.
Bizarre syntax is old news. ;)
A couple notes on the --format option, from what little I've tried:
Maybe this could be used to translate OpenSCAD to PythonSCAD? (Or, maybe
a translation to PythonSCAD could be integrated into OpenSCAD itself, as
it has its own AST.)
Regards,
-Curt
On 5/17/2026 7:03 PM, Revar Desmera via Discuss wrote:
I'm in the process of testing my Python openscad_parser library
(https://github.com/BelfrySCAD/openscad_parser), and comparing it to
how OpenSCAD itself parses the language. I've found a few oddities in
what OpenSCAD allows syntactically, that I find amusing.
You can do a C-style for loop in a list comprehension like x = [for (i = 0; i < 10; i=i+1) i];, but you CANNOT do a C-style for() in
modular form. Also, intersection_for() will not take C-style syntax.
You do NOT need to specify initializer or incrementer in a C-style
list comprehension for loop like i=0; x = [for (;i<10;) i];.
However, if you don't have an incrementer, it will ALWAYS error out
with loop counter exceeded.
Modular for() echo(42); will do nothing. It's a No-Op. Same for
intersection_for() echo(42);.
For some reason, |i=42; echo([for() i]); echoes 42 to the console. I
expected an empty list.|
||
The let() in x = let() 42; acts like a No-op. x just gets set
to 42.
I'm sure there are more oddities in there. In any case, the parser is
live, with Abstract Syntax Tree generation, a command-line code
reformatter, and 850+ unit tests. It's probably usable now.
I've found a few oddities in what OpenSCAD allows syntactically, that I find amusing.
Yep. Some degenerate cases, and in my opinion one missing feature, one bug.
You can do a C-style for loop in a list comprehension like x = [for (i = 0; i < 10; i=i+1) i];, but you CANNOT do a C-style for() in modular form. Also, intersection_for() will not take C-style syntax.
Missing feature.
You do NOT need to specify initializer or incrementer in a C-style list comprehension for loop like i=0; x = [for (;i<10;) i];. However, if you don't have an incrementer, it will ALWAYS error out with loop counter exceeded.
Totally useless degenerate case, probably should require an incrementer. (If the condition fails then it doesn’t error out.)
Modular for() echo(42); will do nothing. It's a No-Op. Same for intersection_for() echo(42);.
For some reason, i=42; echo([for() i]); echoes 42 to the console. I expected an empty list.
Bug. For some reason the two module variants specifically check for an empty list and do nothing; the LC variant does not. That one runs the child once, times the number of cases in the first assignment, times the number in the se on assignment, et cetera. I don’t really care which it does, or if an empty list is considered an error, but it seems wrong that they are different.
The let() in x = let() 42; acts like a No-op. x just gets set to 42.
Degenerate case: the let() does every assignment listed. If that’s none, it’s none. That might actually be useful; it would let you comment out all of the assignments in the list without commenting out the let() itself.
I'm sure there are more oddities in there.
Absolutely.
No Need for that.
One of the PythonSCAD goals is to stay 100% compatible with SCAD code.
And once you successfully parsed SCAD code, there is a small helper in the
Design Menu.
When you choose "Display Python Conversion" , it actually uses the AST Tree
to display the Model in Python Format.
It's not perfect, but it can aid as a great step ahead.
On Mon, May 18, 2026 at 6:48 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:
Bizarre syntax is old news. ;)
A couple notes on the --format option, from what little I've tried:
- It doesn't add parenthesis or take operator precedence into account.
Input (3+5)/2 gets formatted as 3+5/2.
- It uses *True *and *False *for booleans instead of *true *and *false*
.
Maybe this could be used to translate OpenSCAD to PythonSCAD? (Or, maybe a
translation to PythonSCAD could be integrated into OpenSCAD itself, as it
has its own AST.)
Regards,
-Curt
On 5/17/2026 7:03 PM, Revar Desmera via Discuss wrote:
I'm in the process of testing my Python openscad_parser library (
https://github.com/BelfrySCAD/openscad_parser), and comparing it to how
OpenSCAD itself parses the language. I've found a few oddities in what
OpenSCAD allows syntactically, that I find amusing.
You can do a C-style for loop in a list comprehension like x = [for (i = 0; i < 10; i=i+1) i];, but you CANNOT do a C-style for() in modular
form. Also, intersection_for() will not take C-style syntax.
You do NOT need to specify initializer or incrementer in a C-style list
comprehension for loop like i=0; x = [for (;i<10;) i];. However, if you
don't have an incrementer, it will ALWAYS error out with loop counter
exceeded.
Modular for() echo(42); will do nothing. It's a No-Op. Same for
intersection_for() echo(42);.
For some reason, i=42; echo([for() i]); echoes 42 to the console. I
expected an empty list.
The let() in x = let() 42; acts like a No-op. x just gets set to 42.
I'm sure there are more oddities in there. In any case, the parser is
live, with Abstract Syntax Tree generation, a command-line code
reformatter, and 850+ unit tests. It's probably usable now.
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
The command-line openscad-parser command is a recent low effort low-hanging fruit feature. I am not surprised that the --format pretty-printer has bugs. Luckily, the YAML and JSON outputs should correctly have precedence handled, as they present the full AST structure. I'll poke at the code to fix the --format precedence and booleans output. Thanks for the catch.
On May 18, 2026, at 9:47 AM, Curt McDowell via Discuss discuss@lists.openscad.org wrote:
Bizarre syntax is old news. ;)
A couple notes on the --format option, from what little I've tried:
It doesn't add parenthesis or take operator precedence into account. Input (3+5)/2 gets formatted as 3+5/2.
It uses True and False for booleans instead of true and false.
Maybe this could be used to translate OpenSCAD to PythonSCAD? (Or, maybe a translation to PythonSCAD could be integrated into OpenSCAD itself, as it has its own AST.)
Regards,
-Curt
On 5/17/2026 7:03 PM, Revar Desmera via Discuss wrote:
I'm in the process of testing my Python openscad_parser library (https://github.com/BelfrySCAD/openscad_parser), and comparing it to how OpenSCAD itself parses the language. I've found a few oddities in what OpenSCAD allows syntactically, that I find amusing.
You can do a C-style for loop in a list comprehension like x = [for (i = 0; i < 10; i=i+1) i];, but you CANNOT do a C-style for() in modular form. Also, intersection_for() will not take C-style syntax.
You do NOT need to specify initializer or incrementer in a C-style list comprehension for loop like i=0; x = [for (;i<10;) i];. However, if you don't have an incrementer, it will ALWAYS error out with loop counter exceeded.
Modular for() echo(42); will do nothing. It's a No-Op. Same for intersection_for() echo(42);.
For some reason, i=42; echo([for() i]); echoes 42 to the console. I expected an empty list.
The let() in x = let() 42; acts like a No-op. x just gets set to 42.
I'm sure there are more oddities in there. In any case, the parser is live, with Abstract Syntax Tree generation, a command-line code reformatter, and 850+ unit tests. It's probably usable now.
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org