brittainscript 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {brittainscript-0.2.0 → brittainscript-0.3.0}/Documentation/README.md +112 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/PKG-INFO +113 -1
- {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/PKG-INFO +113 -1
- {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/SOURCES.txt +3 -1
- {brittainscript-0.2.0 → brittainscript-0.3.0}/core/lexer.py +11 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/core/parser.py +48 -3
- brittainscript-0.3.0/core/parsetab.py +73 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/pyproject.toml +1 -1
- brittainscript-0.3.0/tests/test_operator_precedence.py +59 -0
- brittainscript-0.3.0/tests/test_python_bridge.py +192 -0
- brittainscript-0.2.0/core/parsetab.py +0 -71
- {brittainscript-0.2.0 → brittainscript-0.3.0}/LICENSE +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/dependency_links.txt +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/entry_points.txt +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/requires.txt +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/top_level.txt +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/core/__init__.py +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/core/gui_backend.py +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/core/main.py +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/__init__.py +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/convert.bs +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/datetime.bs +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/gui.bs +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/io.bs +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/math.bs +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/terminal.bs +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/setup.cfg +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/tests/test_datetime_builtin.py +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/tests/test_gui_builtins.py +0 -0
- {brittainscript-0.2.0 → brittainscript-0.3.0}/tests/test_parser_builtins.py +0 -0
|
@@ -180,6 +180,118 @@ push(len(nums))
|
|
|
180
180
|
|
|
181
181
|
---
|
|
182
182
|
|
|
183
|
+
## Python Interop
|
|
184
|
+
|
|
185
|
+
BrittainScript can call into any Python library installed in the same Python
|
|
186
|
+
environment — `numpy`, `requests`, `torch`, anything. There is nothing to
|
|
187
|
+
install beyond the library itself; the interpreter's only dependency is `ply`.
|
|
188
|
+
|
|
189
|
+
### `pyimport(name)`
|
|
190
|
+
|
|
191
|
+
Imports a Python module and hands it back as an ordinary BrittainScript value.
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
np = pyimport("numpy")
|
|
195
|
+
json = pyimport("json")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
If the module cannot be imported, `pyimport` prints an error and returns
|
|
199
|
+
nothing:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
missing = pyimport("not_a_real_module")
|
|
203
|
+
=> Error: cannot import 'not_a_real_module': No module named 'not_a_real_module'
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Calling Python methods
|
|
207
|
+
|
|
208
|
+
Method-call syntax falls through to Python whenever the name is not one of
|
|
209
|
+
BrittainScript's own methods (`upper`, `lower`, `trim`, `contains`, `locate`,
|
|
210
|
+
`add`, `remove`, `pop`, `has`). Those built-ins always win, so existing scripts
|
|
211
|
+
are unaffected.
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
np = pyimport("numpy")
|
|
215
|
+
matrix = np.array([[1, 2], [3, 4]])
|
|
216
|
+
|
|
217
|
+
push(matrix.sum()) => 10
|
|
218
|
+
push(matrix.transpose())
|
|
219
|
+
push("a,b,c".split(",")) => ['a', 'b', 'c']
|
|
220
|
+
push("hello".replace("l", "L"))
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Note that arguments are positional only — BrittainScript has no keyword
|
|
224
|
+
argument syntax. Where a Python API needs a keyword, look for a method form of
|
|
225
|
+
it (`tensor.requires_grad_()` rather than `requires_grad=true`).
|
|
226
|
+
|
|
227
|
+
### Attribute access
|
|
228
|
+
|
|
229
|
+
A dotted name with no call reads the attribute directly.
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
np = pyimport("numpy")
|
|
233
|
+
matrix = np.array([[1, 2], [3, 4]])
|
|
234
|
+
|
|
235
|
+
push(matrix.shape) => (2, 2)
|
|
236
|
+
push(matrix.T)
|
|
237
|
+
push(pyimport("math").pi) => 3.141592653589793
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Reserved words such as `pi`, `sin`, `cos` and `tan` are treated as ordinary
|
|
241
|
+
names when they follow a `.`, so `math.pi` and `np.sin(x)` both work.
|
|
242
|
+
|
|
243
|
+
### The `@` operator
|
|
244
|
+
|
|
245
|
+
`@` is matrix multiplication, passed straight through to Python's `__matmul__`.
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
np = pyimport("numpy")
|
|
249
|
+
a = np.array([[1, 2], [3, 4]])
|
|
250
|
+
push(a @ a) => [[ 7 10]
|
|
251
|
+
[15 22]]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
It binds at the same level as `*`, so `x @ w + b` multiplies before it adds.
|
|
255
|
+
|
|
256
|
+
### Why this works everywhere else too
|
|
257
|
+
|
|
258
|
+
BrittainScript values are native Python objects, so once a Python object is in
|
|
259
|
+
a variable, the rest of the language already applies to it — arithmetic,
|
|
260
|
+
indexing, slicing, comparison and `for` loops all use Python's own behaviour:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
np = pyimport("numpy")
|
|
264
|
+
values = np.array([10, 20, 30, 40])
|
|
265
|
+
|
|
266
|
+
push(values * 2)
|
|
267
|
+
push(values[1])
|
|
268
|
+
push(values[1:3])
|
|
269
|
+
for value in values:
|
|
270
|
+
push(value)
|
|
271
|
+
end
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### A worked example
|
|
275
|
+
|
|
276
|
+
`examples/torch_demo.bs` trains a small linear model with PyTorch, including a
|
|
277
|
+
hand-written SGD loop driven by autograd. Run it with:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
python3 run.py examples/torch_demo.bs
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
It prints a message and stops if `torch` is not installed.
|
|
284
|
+
|
|
285
|
+
### A note on scope
|
|
286
|
+
|
|
287
|
+
`pyimport` gives a script the whole Python environment — including `os`,
|
|
288
|
+
`subprocess` and `shutil`. That is the expected trade-off for a scripting
|
|
289
|
+
language FFI and is the same power a Python script has, but it does mean a
|
|
290
|
+
`.bs` file can do anything the Python interpreter running it can do. Treat
|
|
291
|
+
untrusted BrittainScript the way you would treat untrusted Python.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
183
295
|
## Test Files
|
|
184
296
|
|
|
185
297
|
There are two standalone test suites in `TestFiles/`. These are self-contained and independent from the main interpreter — they were used to prototype the lexer and parser separately.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: brittainscript
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: The BrittainScript programming language interpreter
|
|
5
5
|
Author-email: Luke Brittain <luke.brittain@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -218,6 +218,118 @@ push(len(nums))
|
|
|
218
218
|
|
|
219
219
|
---
|
|
220
220
|
|
|
221
|
+
## Python Interop
|
|
222
|
+
|
|
223
|
+
BrittainScript can call into any Python library installed in the same Python
|
|
224
|
+
environment — `numpy`, `requests`, `torch`, anything. There is nothing to
|
|
225
|
+
install beyond the library itself; the interpreter's only dependency is `ply`.
|
|
226
|
+
|
|
227
|
+
### `pyimport(name)`
|
|
228
|
+
|
|
229
|
+
Imports a Python module and hands it back as an ordinary BrittainScript value.
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
np = pyimport("numpy")
|
|
233
|
+
json = pyimport("json")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
If the module cannot be imported, `pyimport` prints an error and returns
|
|
237
|
+
nothing:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
missing = pyimport("not_a_real_module")
|
|
241
|
+
=> Error: cannot import 'not_a_real_module': No module named 'not_a_real_module'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Calling Python methods
|
|
245
|
+
|
|
246
|
+
Method-call syntax falls through to Python whenever the name is not one of
|
|
247
|
+
BrittainScript's own methods (`upper`, `lower`, `trim`, `contains`, `locate`,
|
|
248
|
+
`add`, `remove`, `pop`, `has`). Those built-ins always win, so existing scripts
|
|
249
|
+
are unaffected.
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
np = pyimport("numpy")
|
|
253
|
+
matrix = np.array([[1, 2], [3, 4]])
|
|
254
|
+
|
|
255
|
+
push(matrix.sum()) => 10
|
|
256
|
+
push(matrix.transpose())
|
|
257
|
+
push("a,b,c".split(",")) => ['a', 'b', 'c']
|
|
258
|
+
push("hello".replace("l", "L"))
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Note that arguments are positional only — BrittainScript has no keyword
|
|
262
|
+
argument syntax. Where a Python API needs a keyword, look for a method form of
|
|
263
|
+
it (`tensor.requires_grad_()` rather than `requires_grad=true`).
|
|
264
|
+
|
|
265
|
+
### Attribute access
|
|
266
|
+
|
|
267
|
+
A dotted name with no call reads the attribute directly.
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
np = pyimport("numpy")
|
|
271
|
+
matrix = np.array([[1, 2], [3, 4]])
|
|
272
|
+
|
|
273
|
+
push(matrix.shape) => (2, 2)
|
|
274
|
+
push(matrix.T)
|
|
275
|
+
push(pyimport("math").pi) => 3.141592653589793
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Reserved words such as `pi`, `sin`, `cos` and `tan` are treated as ordinary
|
|
279
|
+
names when they follow a `.`, so `math.pi` and `np.sin(x)` both work.
|
|
280
|
+
|
|
281
|
+
### The `@` operator
|
|
282
|
+
|
|
283
|
+
`@` is matrix multiplication, passed straight through to Python's `__matmul__`.
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
np = pyimport("numpy")
|
|
287
|
+
a = np.array([[1, 2], [3, 4]])
|
|
288
|
+
push(a @ a) => [[ 7 10]
|
|
289
|
+
[15 22]]
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
It binds at the same level as `*`, so `x @ w + b` multiplies before it adds.
|
|
293
|
+
|
|
294
|
+
### Why this works everywhere else too
|
|
295
|
+
|
|
296
|
+
BrittainScript values are native Python objects, so once a Python object is in
|
|
297
|
+
a variable, the rest of the language already applies to it — arithmetic,
|
|
298
|
+
indexing, slicing, comparison and `for` loops all use Python's own behaviour:
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
np = pyimport("numpy")
|
|
302
|
+
values = np.array([10, 20, 30, 40])
|
|
303
|
+
|
|
304
|
+
push(values * 2)
|
|
305
|
+
push(values[1])
|
|
306
|
+
push(values[1:3])
|
|
307
|
+
for value in values:
|
|
308
|
+
push(value)
|
|
309
|
+
end
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### A worked example
|
|
313
|
+
|
|
314
|
+
`examples/torch_demo.bs` trains a small linear model with PyTorch, including a
|
|
315
|
+
hand-written SGD loop driven by autograd. Run it with:
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
python3 run.py examples/torch_demo.bs
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
It prints a message and stops if `torch` is not installed.
|
|
322
|
+
|
|
323
|
+
### A note on scope
|
|
324
|
+
|
|
325
|
+
`pyimport` gives a script the whole Python environment — including `os`,
|
|
326
|
+
`subprocess` and `shutil`. That is the expected trade-off for a scripting
|
|
327
|
+
language FFI and is the same power a Python script has, but it does mean a
|
|
328
|
+
`.bs` file can do anything the Python interpreter running it can do. Treat
|
|
329
|
+
untrusted BrittainScript the way you would treat untrusted Python.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
221
333
|
## Test Files
|
|
222
334
|
|
|
223
335
|
There are two standalone test suites in `TestFiles/`. These are self-contained and independent from the main interpreter — they were used to prototype the lexer and parser separately.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: brittainscript
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: The BrittainScript programming language interpreter
|
|
5
5
|
Author-email: Luke Brittain <luke.brittain@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -218,6 +218,118 @@ push(len(nums))
|
|
|
218
218
|
|
|
219
219
|
---
|
|
220
220
|
|
|
221
|
+
## Python Interop
|
|
222
|
+
|
|
223
|
+
BrittainScript can call into any Python library installed in the same Python
|
|
224
|
+
environment — `numpy`, `requests`, `torch`, anything. There is nothing to
|
|
225
|
+
install beyond the library itself; the interpreter's only dependency is `ply`.
|
|
226
|
+
|
|
227
|
+
### `pyimport(name)`
|
|
228
|
+
|
|
229
|
+
Imports a Python module and hands it back as an ordinary BrittainScript value.
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
np = pyimport("numpy")
|
|
233
|
+
json = pyimport("json")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
If the module cannot be imported, `pyimport` prints an error and returns
|
|
237
|
+
nothing:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
missing = pyimport("not_a_real_module")
|
|
241
|
+
=> Error: cannot import 'not_a_real_module': No module named 'not_a_real_module'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Calling Python methods
|
|
245
|
+
|
|
246
|
+
Method-call syntax falls through to Python whenever the name is not one of
|
|
247
|
+
BrittainScript's own methods (`upper`, `lower`, `trim`, `contains`, `locate`,
|
|
248
|
+
`add`, `remove`, `pop`, `has`). Those built-ins always win, so existing scripts
|
|
249
|
+
are unaffected.
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
np = pyimport("numpy")
|
|
253
|
+
matrix = np.array([[1, 2], [3, 4]])
|
|
254
|
+
|
|
255
|
+
push(matrix.sum()) => 10
|
|
256
|
+
push(matrix.transpose())
|
|
257
|
+
push("a,b,c".split(",")) => ['a', 'b', 'c']
|
|
258
|
+
push("hello".replace("l", "L"))
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Note that arguments are positional only — BrittainScript has no keyword
|
|
262
|
+
argument syntax. Where a Python API needs a keyword, look for a method form of
|
|
263
|
+
it (`tensor.requires_grad_()` rather than `requires_grad=true`).
|
|
264
|
+
|
|
265
|
+
### Attribute access
|
|
266
|
+
|
|
267
|
+
A dotted name with no call reads the attribute directly.
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
np = pyimport("numpy")
|
|
271
|
+
matrix = np.array([[1, 2], [3, 4]])
|
|
272
|
+
|
|
273
|
+
push(matrix.shape) => (2, 2)
|
|
274
|
+
push(matrix.T)
|
|
275
|
+
push(pyimport("math").pi) => 3.141592653589793
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Reserved words such as `pi`, `sin`, `cos` and `tan` are treated as ordinary
|
|
279
|
+
names when they follow a `.`, so `math.pi` and `np.sin(x)` both work.
|
|
280
|
+
|
|
281
|
+
### The `@` operator
|
|
282
|
+
|
|
283
|
+
`@` is matrix multiplication, passed straight through to Python's `__matmul__`.
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
np = pyimport("numpy")
|
|
287
|
+
a = np.array([[1, 2], [3, 4]])
|
|
288
|
+
push(a @ a) => [[ 7 10]
|
|
289
|
+
[15 22]]
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
It binds at the same level as `*`, so `x @ w + b` multiplies before it adds.
|
|
293
|
+
|
|
294
|
+
### Why this works everywhere else too
|
|
295
|
+
|
|
296
|
+
BrittainScript values are native Python objects, so once a Python object is in
|
|
297
|
+
a variable, the rest of the language already applies to it — arithmetic,
|
|
298
|
+
indexing, slicing, comparison and `for` loops all use Python's own behaviour:
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
np = pyimport("numpy")
|
|
302
|
+
values = np.array([10, 20, 30, 40])
|
|
303
|
+
|
|
304
|
+
push(values * 2)
|
|
305
|
+
push(values[1])
|
|
306
|
+
push(values[1:3])
|
|
307
|
+
for value in values:
|
|
308
|
+
push(value)
|
|
309
|
+
end
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### A worked example
|
|
313
|
+
|
|
314
|
+
`examples/torch_demo.bs` trains a small linear model with PyTorch, including a
|
|
315
|
+
hand-written SGD loop driven by autograd. Run it with:
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
python3 run.py examples/torch_demo.bs
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
It prints a message and stops if `torch` is not installed.
|
|
322
|
+
|
|
323
|
+
### A note on scope
|
|
324
|
+
|
|
325
|
+
`pyimport` gives a script the whole Python environment — including `os`,
|
|
326
|
+
`subprocess` and `shutil`. That is the expected trade-off for a scripting
|
|
327
|
+
language FFI and is the same power a Python script has, but it does mean a
|
|
328
|
+
`.bs` file can do anything the Python interpreter running it can do. Treat
|
|
329
|
+
untrusted BrittainScript the way you would treat untrusted Python.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
221
333
|
## Test Files
|
|
222
334
|
|
|
223
335
|
There are two standalone test suites in `TestFiles/`. These are self-contained and independent from the main interpreter — they were used to prototype the lexer and parser separately.
|
|
@@ -6,6 +6,7 @@ tokens = (
|
|
|
6
6
|
'MINUS',
|
|
7
7
|
'DIVIDE',
|
|
8
8
|
'MULTIPLY',
|
|
9
|
+
'AT',
|
|
9
10
|
'POWER',
|
|
10
11
|
'MODULO',
|
|
11
12
|
'LPAREN',
|
|
@@ -65,6 +66,7 @@ t_PLUS = r'\+'
|
|
|
65
66
|
t_MINUS = r'\-'
|
|
66
67
|
t_DIVIDE = r'\/'
|
|
67
68
|
t_MULTIPLY = r'\*'
|
|
69
|
+
t_AT = r'@'
|
|
68
70
|
t_POWER = r'\^'
|
|
69
71
|
t_MODULO = r'\%'
|
|
70
72
|
t_LPAREN = r'\('
|
|
@@ -105,8 +107,17 @@ def t_NUMBER(t):
|
|
|
105
107
|
t.value = float(t.value) if '.' in t.value else int(t.value)
|
|
106
108
|
return t
|
|
107
109
|
|
|
110
|
+
def follows_dot(t):
|
|
111
|
+
# after a '.', a word is always a member name -- 'pi', 'sin', 'cos' and the
|
|
112
|
+
# other reserved words are ordinary attributes on Python objects
|
|
113
|
+
preceding = t.lexer.lexdata[:t.lexpos].rstrip(' \t')
|
|
114
|
+
return preceding.endswith('.')
|
|
115
|
+
|
|
108
116
|
def t_NAME(t):
|
|
109
117
|
r'[a-zA-Z_][a-zA-Z0-9_]*'
|
|
118
|
+
if follows_dot(t):
|
|
119
|
+
t.type = 'NAME'
|
|
120
|
+
return t
|
|
110
121
|
t.type = reserved.get(t.value, 'NAME')
|
|
111
122
|
return t
|
|
112
123
|
|
|
@@ -20,7 +20,7 @@ precedence = (
|
|
|
20
20
|
('left', 'EQUALTO', 'NOTEQUALTO'),
|
|
21
21
|
('left', 'LESSTHAN', 'GREATERTHAN', 'LESSTHANEQUALTO', 'GREATERTHANEQUALTO'),
|
|
22
22
|
('left', 'PLUS', 'MINUS'),
|
|
23
|
-
('left', 'MULTIPLY', 'DIVIDE'),
|
|
23
|
+
('left', 'MULTIPLY', 'DIVIDE', 'MODULO', 'AT'),
|
|
24
24
|
('right', 'POWER'),
|
|
25
25
|
('left', 'LBRACKET'),
|
|
26
26
|
('left', 'DOT'),
|
|
@@ -113,8 +113,20 @@ def p_expression_times(p):
|
|
|
113
113
|
print(f"Error: cannot multiply {type(p[1]).__name__} and {type(p[3]).__name__}")
|
|
114
114
|
p[0] = None
|
|
115
115
|
|
|
116
|
+
def p_expression_matmul(p):
|
|
117
|
+
'expression : expression AT expression'
|
|
118
|
+
try:
|
|
119
|
+
p[0] = p[1] @ p[3]
|
|
120
|
+
except TypeError as exc:
|
|
121
|
+
print(f"Error: cannot matrix-multiply: {exc}")
|
|
122
|
+
p[0] = None
|
|
123
|
+
|
|
116
124
|
def p_expression_modulo(p):
|
|
117
125
|
'expression : expression MODULO expression'
|
|
126
|
+
if p[3] == 0:
|
|
127
|
+
print("Error: modulo by zero")
|
|
128
|
+
p[0] = None
|
|
129
|
+
return
|
|
118
130
|
p[0] = p[1] % p[3]
|
|
119
131
|
|
|
120
132
|
def p_expression_power(p):
|
|
@@ -219,7 +231,30 @@ def p_expression_method_call(p):
|
|
|
219
231
|
'expression : expression DOT NAME LPAREN optional_arguments RPAREN'
|
|
220
232
|
p[0] = call_method(p[1], p[3], p[5])
|
|
221
233
|
|
|
234
|
+
def p_expression_attribute(p):
|
|
235
|
+
'expression : expression DOT NAME'
|
|
236
|
+
receiver, attr = p[1], p[3]
|
|
237
|
+
if isinstance(receiver, dict) and receiver.get('__bs_module__'):
|
|
238
|
+
print(f"Error: '{receiver['name']}' members must be called")
|
|
239
|
+
p[0] = None
|
|
240
|
+
return
|
|
241
|
+
try:
|
|
242
|
+
p[0] = getattr(receiver, attr)
|
|
243
|
+
except AttributeError:
|
|
244
|
+
print(f"Error: no attribute '{attr}' on {type(receiver).__name__}")
|
|
245
|
+
p[0] = None
|
|
246
|
+
|
|
222
247
|
def call_function(name, args):
|
|
248
|
+
if name == 'pyimport':
|
|
249
|
+
if len(args) != 1 or not isinstance(args[0], str):
|
|
250
|
+
print("Error: pyimport() expects one string argument")
|
|
251
|
+
return None
|
|
252
|
+
import importlib
|
|
253
|
+
try:
|
|
254
|
+
return importlib.import_module(args[0])
|
|
255
|
+
except ImportError as exc:
|
|
256
|
+
print(f"Error: cannot import '{args[0]}': {exc}")
|
|
257
|
+
return None
|
|
223
258
|
if name == 'len':
|
|
224
259
|
if len(args) != 1:
|
|
225
260
|
print("Error: len() expects 1 argument")
|
|
@@ -435,8 +470,18 @@ def call_method(receiver, name, args):
|
|
|
435
470
|
return True
|
|
436
471
|
else:
|
|
437
472
|
return False
|
|
438
|
-
|
|
439
|
-
|
|
473
|
+
try:
|
|
474
|
+
attribute = getattr(receiver, name)
|
|
475
|
+
except AttributeError:
|
|
476
|
+
print(f"Error: no method '{name}' on {type(receiver).__name__}")
|
|
477
|
+
return None
|
|
478
|
+
if callable(attribute):
|
|
479
|
+
try:
|
|
480
|
+
return attribute(*args)
|
|
481
|
+
except Exception as exc:
|
|
482
|
+
print(f"Error calling '{name}': {exc}")
|
|
483
|
+
return None
|
|
484
|
+
return attribute
|
|
440
485
|
|
|
441
486
|
def p_expression_and(p):
|
|
442
487
|
'expression : expression AND expression'
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
|
|
2
|
+
# parsetab.py
|
|
3
|
+
# This file is automatically generated. Do not edit.
|
|
4
|
+
# pylint: disable=W,C,R
|
|
5
|
+
_tabversion = '3.10'
|
|
6
|
+
|
|
7
|
+
_lr_method = 'LALR'
|
|
8
|
+
|
|
9
|
+
_lr_signature = 'leftORleftANDrightNOTleftEQUALTONOTEQUALTOleftLESSTHANGREATERTHANLESSTHANEQUALTOGREATERTHANEQUALTOleftPLUSMINUSleftMULTIPLYDIVIDEMODULOATrightPOWERleftLBRACKETleftDOTADD AND AT COLON COMMA COND COSINE DIVIDE DOT EQ EQUALTO FALSE GREATERTHAN GREATERTHANEQUALTO LBRACKET LESSTHAN LESSTHANEQUALTO LPAREN MINUS MODULO MULTIPLY NAME NOT NOTEQUALTO NUMBER OR PI PLUS POWER PRINT RANGE RBRACKET RPAREN SINE SQUAREROOT STRING TANGENT TRUEexpression : NUMBERexpression : LPAREN expression RPARENexpression : expression PLUS expressionexpression : expression MINUS expressionexpression : expression DIVIDE expressionexpression : expression MULTIPLY expressionexpression : expression AT expressionexpression : expression MODULO expressionexpression : expression POWER expressionexpression : SQUAREROOT LPAREN expression RPARENexpression : SINE LPAREN expression RPARENexpression : COSINE LPAREN expression RPARENexpression : TANGENT LPAREN expression RPARENexpression : PIexpression : PRINT LPAREN expression RPARENexpression : STRINGexpression : NAME EQ expressionexpression : NAMEexpression : LBRACKET optional_arguments RBRACKETexpression : expression LBRACKET expression RBRACKETexpression : expression LBRACKET optional_expression COLON optional_expression RBRACKEToptional_expression :optional_expression : expressionoptional_arguments :optional_arguments : argumentsarguments : expressionarguments : arguments COMMA expressionexpression : NAME LPAREN optional_arguments RPARENexpression : RANGE LPAREN optional_arguments RPARENexpression : expression DOT NAME LPAREN optional_arguments RPARENexpression : expression DOT NAMEexpression : expression AND expressionexpression : expression OR expressionexpression : NOT expressionexpression : expression EQUALTO expressionexpression : expression NOTEQUALTO expressionexpression : expression GREATERTHAN expressionexpression : expression LESSTHAN expressionexpression : expression GREATERTHANEQUALTO expressionexpression : expression LESSTHANEQUALTO expressionexpression : TRUEexpression : FALSEexpression : COND LPAREN expression RPAREN'
|
|
10
|
+
|
|
11
|
+
_lr_action_items = {'NUMBER':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,]),'LPAREN':([0,3,4,5,6,7,9,11,12,13,14,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,58,76,80,81,],[3,3,36,37,38,39,40,42,3,46,3,48,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,81,3,3,3,]),'SQUAREROOT':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,]),'SINE':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'COSINE':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'TANGENT':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'PI':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,]),'PRINT':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,]),'STRING':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,]),'NAME':([0,3,12,14,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[11,11,11,11,11,11,11,11,11,11,11,11,58,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,]),'LBRACKET':([0,1,2,3,8,10,11,12,14,15,16,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,45,46,47,48,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,91,94,95,],[12,25,-1,12,-14,-16,-18,12,12,-41,-42,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,25,12,12,12,12,12,12,12,25,12,25,12,25,25,25,25,25,25,25,25,-31,25,25,25,25,25,25,25,25,-2,25,25,25,25,25,25,-19,12,25,-20,12,12,-10,-11,-12,-13,-15,-28,25,-29,-43,25,-21,-30,]),'RANGE':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,]),'NOT':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,]),'TRUE':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,]),'FALSE':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,]),'COND':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,]),'$end':([1,2,8,10,11,15,16,47,49,50,51,52,53,54,55,58,59,60,61,62,63,64,65,66,67,73,75,79,82,83,84,85,86,87,89,90,94,95,],[0,-1,-14,-16,-18,-41,-42,-34,-3,-4,-5,-6,-7,-8,-9,-31,-32,-33,-35,-36,-37,-38,-39,-40,-2,-17,-19,-20,-10,-11,-12,-13,-15,-28,-29,-43,-21,-30,]),'PLUS':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[18,-1,-14,-16,-18,-41,-42,18,18,18,-3,-4,-5,-6,-7,-8,-9,18,-31,18,18,18,18,18,18,18,18,-2,18,18,18,18,18,18,-19,18,-20,-10,-11,-12,-13,-15,-28,18,-29,-43,18,-21,-30,]),'MINUS':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[19,-1,-14,-16,-18,-41,-42,19,19,19,-3,-4,-5,-6,-7,-8,-9,19,-31,19,19,19,19,19,19,19,19,-2,19,19,19,19,19,19,-19,19,-20,-10,-11,-12,-13,-15,-28,19,-29,-43,19,-21,-30,]),'DIVIDE':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[20,-1,-14,-16,-18,-41,-42,20,20,20,20,20,-5,-6,-7,-8,-9,20,-31,20,20,20,20,20,20,20,20,-2,20,20,20,20,20,20,-19,20,-20,-10,-11,-12,-13,-15,-28,20,-29,-43,20,-21,-30,]),'MULTIPLY':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[21,-1,-14,-16,-18,-41,-42,21,21,21,21,21,-5,-6,-7,-8,-9,21,-31,21,21,21,21,21,21,21,21,-2,21,21,21,21,21,21,-19,21,-20,-10,-11,-12,-13,-15,-28,21,-29,-43,21,-21,-30,]),'AT':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[22,-1,-14,-16,-18,-41,-42,22,22,22,22,22,-5,-6,-7,-8,-9,22,-31,22,22,22,22,22,22,22,22,-2,22,22,22,22,22,22,-19,22,-20,-10,-11,-12,-13,-15,-28,22,-29,-43,22,-21,-30,]),'MODULO':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[23,-1,-14,-16,-18,-41,-42,23,23,23,23,23,-5,-6,-7,-8,-9,23,-31,23,23,23,23,23,23,23,23,-2,23,23,23,23,23,23,-19,23,-20,-10,-11,-12,-13,-15,-28,23,-29,-43,23,-21,-30,]),'POWER':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[24,-1,-14,-16,-18,-41,-42,24,24,24,24,24,24,24,24,24,24,24,-31,24,24,24,24,24,24,24,24,-2,24,24,24,24,24,24,-19,24,-20,-10,-11,-12,-13,-15,-28,24,-29,-43,24,-21,-30,]),'DOT':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[26,-1,-14,-16,-18,-41,-42,26,26,26,26,26,26,26,26,26,26,26,-31,26,26,26,26,26,26,26,26,-2,26,26,26,26,26,26,-19,26,-20,-10,-11,-12,-13,-15,-28,26,-29,-43,26,-21,-30,]),'AND':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[27,-1,-14,-16,-18,-41,-42,27,27,-34,-3,-4,-5,-6,-7,-8,-9,27,-31,-32,27,-35,-36,-37,-38,-39,-40,-2,27,27,27,27,27,27,-19,27,-20,-10,-11,-12,-13,-15,-28,27,-29,-43,27,-21,-30,]),'OR':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[28,-1,-14,-16,-18,-41,-42,28,28,-34,-3,-4,-5,-6,-7,-8,-9,28,-31,-32,-33,-35,-36,-37,-38,-39,-40,-2,28,28,28,28,28,28,-19,28,-20,-10,-11,-12,-13,-15,-28,28,-29,-43,28,-21,-30,]),'EQUALTO':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[29,-1,-14,-16,-18,-41,-42,29,29,29,-3,-4,-5,-6,-7,-8,-9,29,-31,29,29,-35,-36,-37,-38,-39,-40,-2,29,29,29,29,29,29,-19,29,-20,-10,-11,-12,-13,-15,-28,29,-29,-43,29,-21,-30,]),'NOTEQUALTO':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[30,-1,-14,-16,-18,-41,-42,30,30,30,-3,-4,-5,-6,-7,-8,-9,30,-31,30,30,-35,-36,-37,-38,-39,-40,-2,30,30,30,30,30,30,-19,30,-20,-10,-11,-12,-13,-15,-28,30,-29,-43,30,-21,-30,]),'GREATERTHAN':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[31,-1,-14,-16,-18,-41,-42,31,31,31,-3,-4,-5,-6,-7,-8,-9,31,-31,31,31,31,31,-37,-38,-39,-40,-2,31,31,31,31,31,31,-19,31,-20,-10,-11,-12,-13,-15,-28,31,-29,-43,31,-21,-30,]),'LESSTHAN':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[32,-1,-14,-16,-18,-41,-42,32,32,32,-3,-4,-5,-6,-7,-8,-9,32,-31,32,32,32,32,-37,-38,-39,-40,-2,32,32,32,32,32,32,-19,32,-20,-10,-11,-12,-13,-15,-28,32,-29,-43,32,-21,-30,]),'GREATERTHANEQUALTO':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[33,-1,-14,-16,-18,-41,-42,33,33,33,-3,-4,-5,-6,-7,-8,-9,33,-31,33,33,33,33,-37,-38,-39,-40,-2,33,33,33,33,33,33,-19,33,-20,-10,-11,-12,-13,-15,-28,33,-29,-43,33,-21,-30,]),'LESSTHANEQUALTO':([1,2,8,10,11,15,16,35,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,78,79,82,83,84,85,86,87,88,89,90,91,94,95,],[34,-1,-14,-16,-18,-41,-42,34,34,34,-3,-4,-5,-6,-7,-8,-9,34,-31,34,34,34,34,-37,-38,-39,-40,-2,34,34,34,34,34,34,-19,34,-20,-10,-11,-12,-13,-15,-28,34,-29,-43,34,-21,-30,]),'RPAREN':([2,8,10,11,15,16,35,42,44,45,46,47,49,50,51,52,53,54,55,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,77,78,79,81,82,83,84,85,86,87,88,89,90,93,94,95,],[-1,-14,-16,-18,-41,-42,67,-24,-25,-26,-24,-34,-3,-4,-5,-6,-7,-8,-9,-31,-32,-33,-35,-36,-37,-38,-39,-40,-2,82,83,84,85,86,-17,87,-19,89,90,-20,-24,-10,-11,-12,-13,-15,-28,-27,-29,-43,95,-21,-30,]),'COMMA':([2,8,10,11,15,16,44,45,47,49,50,51,52,53,54,55,58,59,60,61,62,63,64,65,66,67,73,75,79,82,83,84,85,86,87,88,89,90,94,95,],[-1,-14,-16,-18,-41,-42,76,-26,-34,-3,-4,-5,-6,-7,-8,-9,-31,-32,-33,-35,-36,-37,-38,-39,-40,-2,-17,-19,-20,-10,-11,-12,-13,-15,-28,-27,-29,-43,-21,-30,]),'RBRACKET':([2,8,10,11,12,15,16,43,44,45,47,49,50,51,52,53,54,55,56,58,59,60,61,62,63,64,65,66,67,73,75,79,80,82,83,84,85,86,87,88,89,90,91,92,94,95,],[-1,-14,-16,-18,-24,-41,-42,75,-25,-26,-34,-3,-4,-5,-6,-7,-8,-9,79,-31,-32,-33,-35,-36,-37,-38,-39,-40,-2,-17,-19,-20,-22,-10,-11,-12,-13,-15,-28,-27,-29,-43,-23,94,-21,-30,]),'COLON':([2,8,10,11,15,16,25,47,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,73,75,79,82,83,84,85,86,87,89,90,94,95,],[-1,-14,-16,-18,-41,-42,-22,-34,-3,-4,-5,-6,-7,-8,-9,-23,80,-31,-32,-33,-35,-36,-37,-38,-39,-40,-2,-17,-19,-20,-10,-11,-12,-13,-15,-28,-29,-43,-21,-30,]),'EQ':([11,],[41,]),}
|
|
12
|
+
|
|
13
|
+
_lr_action = {}
|
|
14
|
+
for _k, _v in _lr_action_items.items():
|
|
15
|
+
for _x,_y in zip(_v[0],_v[1]):
|
|
16
|
+
if not _x in _lr_action: _lr_action[_x] = {}
|
|
17
|
+
_lr_action[_x][_k] = _y
|
|
18
|
+
del _lr_action_items
|
|
19
|
+
|
|
20
|
+
_lr_goto_items = {'expression':([0,3,12,14,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,46,48,76,80,81,],[1,35,45,47,49,50,51,52,53,54,55,56,59,60,61,62,63,64,65,66,68,69,70,71,72,73,45,45,78,88,91,45,]),'optional_arguments':([12,42,46,81,],[43,74,77,93,]),'arguments':([12,42,46,81,],[44,44,44,44,]),'optional_expression':([25,80,],[57,92,]),}
|
|
21
|
+
|
|
22
|
+
_lr_goto = {}
|
|
23
|
+
for _k, _v in _lr_goto_items.items():
|
|
24
|
+
for _x, _y in zip(_v[0], _v[1]):
|
|
25
|
+
if not _x in _lr_goto: _lr_goto[_x] = {}
|
|
26
|
+
_lr_goto[_x][_k] = _y
|
|
27
|
+
del _lr_goto_items
|
|
28
|
+
_lr_productions = [
|
|
29
|
+
("S' -> expression","S'",1,None,None,None),
|
|
30
|
+
('expression -> NUMBER','expression',1,'p_expression_number','parser.py',81),
|
|
31
|
+
('expression -> LPAREN expression RPAREN','expression',3,'p_expression_group','parser.py',85),
|
|
32
|
+
('expression -> expression PLUS expression','expression',3,'p_expression_plus','parser.py',89),
|
|
33
|
+
('expression -> expression MINUS expression','expression',3,'p_expression_minus','parser.py',97),
|
|
34
|
+
('expression -> expression DIVIDE expression','expression',3,'p_expression_divide','parser.py',101),
|
|
35
|
+
('expression -> expression MULTIPLY expression','expression',3,'p_expression_times','parser.py',109),
|
|
36
|
+
('expression -> expression AT expression','expression',3,'p_expression_matmul','parser.py',117),
|
|
37
|
+
('expression -> expression MODULO expression','expression',3,'p_expression_modulo','parser.py',125),
|
|
38
|
+
('expression -> expression POWER expression','expression',3,'p_expression_power','parser.py',133),
|
|
39
|
+
('expression -> SQUAREROOT LPAREN expression RPAREN','expression',4,'p_expression_squareroot','parser.py',137),
|
|
40
|
+
('expression -> SINE LPAREN expression RPAREN','expression',4,'p_expression_sine','parser.py',141),
|
|
41
|
+
('expression -> COSINE LPAREN expression RPAREN','expression',4,'p_expression_cosine','parser.py',145),
|
|
42
|
+
('expression -> TANGENT LPAREN expression RPAREN','expression',4,'p_expression_tangent','parser.py',149),
|
|
43
|
+
('expression -> PI','expression',1,'p_expression_pi','parser.py',153),
|
|
44
|
+
('expression -> PRINT LPAREN expression RPAREN','expression',4,'p_expression_print','parser.py',157),
|
|
45
|
+
('expression -> STRING','expression',1,'p_expression_string','parser.py',162),
|
|
46
|
+
('expression -> NAME EQ expression','expression',3,'p_statement_assign','parser.py',166),
|
|
47
|
+
('expression -> NAME','expression',1,'p_expression_name','parser.py',171),
|
|
48
|
+
('expression -> LBRACKET optional_arguments RBRACKET','expression',3,'p_expression_list','parser.py',179),
|
|
49
|
+
('expression -> expression LBRACKET expression RBRACKET','expression',4,'p_expression_index','parser.py',183),
|
|
50
|
+
('expression -> expression LBRACKET optional_expression COLON optional_expression RBRACKET','expression',6,'p_expression_slice','parser.py',191),
|
|
51
|
+
('optional_expression -> <empty>','optional_expression',0,'p_optional_expression_empty','parser.py',199),
|
|
52
|
+
('optional_expression -> expression','optional_expression',1,'p_optional_expression_value','parser.py',203),
|
|
53
|
+
('optional_arguments -> <empty>','optional_arguments',0,'p_optional_arguments_empty','parser.py',207),
|
|
54
|
+
('optional_arguments -> arguments','optional_arguments',1,'p_optional_arguments_value','parser.py',211),
|
|
55
|
+
('arguments -> expression','arguments',1,'p_arguments_single','parser.py',215),
|
|
56
|
+
('arguments -> arguments COMMA expression','arguments',3,'p_arguments_many','parser.py',219),
|
|
57
|
+
('expression -> NAME LPAREN optional_arguments RPAREN','expression',4,'p_expression_function_call','parser.py',223),
|
|
58
|
+
('expression -> RANGE LPAREN optional_arguments RPAREN','expression',4,'p_expression_range_call','parser.py',227),
|
|
59
|
+
('expression -> expression DOT NAME LPAREN optional_arguments RPAREN','expression',6,'p_expression_method_call','parser.py',231),
|
|
60
|
+
('expression -> expression DOT NAME','expression',3,'p_expression_attribute','parser.py',235),
|
|
61
|
+
('expression -> expression AND expression','expression',3,'p_expression_and','parser.py',487),
|
|
62
|
+
('expression -> expression OR expression','expression',3,'p_expression_or','parser.py',491),
|
|
63
|
+
('expression -> NOT expression','expression',2,'p_expression_not','parser.py',495),
|
|
64
|
+
('expression -> expression EQUALTO expression','expression',3,'p_expression_equalto','parser.py',499),
|
|
65
|
+
('expression -> expression NOTEQUALTO expression','expression',3,'p_expression_notequalto','parser.py',503),
|
|
66
|
+
('expression -> expression GREATERTHAN expression','expression',3,'p_expression_greaterthan','parser.py',507),
|
|
67
|
+
('expression -> expression LESSTHAN expression','expression',3,'p_expression_lessthan','parser.py',511),
|
|
68
|
+
('expression -> expression GREATERTHANEQUALTO expression','expression',3,'p_expression_greaterthanequalto','parser.py',515),
|
|
69
|
+
('expression -> expression LESSTHANEQUALTO expression','expression',3,'p_expression_lessthanequalto','parser.py',519),
|
|
70
|
+
('expression -> TRUE','expression',1,'p_expression_true','parser.py',523),
|
|
71
|
+
('expression -> FALSE','expression',1,'p_expression_false','parser.py',527),
|
|
72
|
+
('expression -> COND LPAREN expression RPAREN','expression',4,'p_expression_cond','parser.py',531),
|
|
73
|
+
]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import contextlib
|
|
3
|
+
import unittest
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "core"))
|
|
8
|
+
import lexer as lexer_module
|
|
9
|
+
import parser
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def evaluate(source):
|
|
13
|
+
return parser.parser.parse(source, lexer=lexer_module.lexer.clone())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def evaluate_capturing(source):
|
|
17
|
+
output = io.StringIO()
|
|
18
|
+
with contextlib.redirect_stdout(output):
|
|
19
|
+
result = evaluate(source)
|
|
20
|
+
return result, output.getvalue()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ModuloPrecedenceTests(unittest.TestCase):
|
|
24
|
+
def test_modulo_binds_tighter_than_comparison(self):
|
|
25
|
+
self.assertIs(evaluate("7 % 3 == 1"), True)
|
|
26
|
+
self.assertIs(evaluate("7 % 3 != 1"), False)
|
|
27
|
+
self.assertIs(evaluate("10 % 4 > 1"), True)
|
|
28
|
+
|
|
29
|
+
def test_modulo_binds_tighter_than_addition(self):
|
|
30
|
+
self.assertEqual(evaluate("10 % 4 + 1"), 3)
|
|
31
|
+
self.assertEqual(evaluate("1 + 10 % 4"), 3)
|
|
32
|
+
|
|
33
|
+
def test_modulo_is_left_associative_with_the_other_products(self):
|
|
34
|
+
self.assertEqual(evaluate("10 % 4 * 2"), 4)
|
|
35
|
+
self.assertEqual(evaluate("2 * 10 % 4"), 0)
|
|
36
|
+
|
|
37
|
+
def test_modulo_by_zero_reports_an_error(self):
|
|
38
|
+
result, output = evaluate_capturing("10 % 0")
|
|
39
|
+
self.assertIsNone(result)
|
|
40
|
+
self.assertIn("modulo by zero", output)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ArithmeticPrecedenceTests(unittest.TestCase):
|
|
44
|
+
def test_products_bind_tighter_than_sums(self):
|
|
45
|
+
self.assertEqual(evaluate("2 + 3 * 4"), 14)
|
|
46
|
+
self.assertEqual(evaluate("2 * 3 + 4"), 10)
|
|
47
|
+
self.assertEqual(evaluate("8 / 4 + 1"), 3.0)
|
|
48
|
+
|
|
49
|
+
def test_grouping_overrides_precedence(self):
|
|
50
|
+
self.assertEqual(evaluate("(2 + 3) * 4"), 20)
|
|
51
|
+
|
|
52
|
+
def test_division_by_zero_reports_an_error(self):
|
|
53
|
+
result, output = evaluate_capturing("10 / 0")
|
|
54
|
+
self.assertIsNone(result)
|
|
55
|
+
self.assertIn("division by zero", output)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
unittest.main()
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import contextlib
|
|
3
|
+
import unittest
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "core"))
|
|
8
|
+
import lexer as lexer_module
|
|
9
|
+
import parser
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def evaluate(source):
|
|
13
|
+
return parser.parser.parse(source, lexer=lexer_module.lexer.clone())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def evaluate_capturing(source):
|
|
17
|
+
output = io.StringIO()
|
|
18
|
+
with contextlib.redirect_stdout(output):
|
|
19
|
+
result = evaluate(source)
|
|
20
|
+
return result, output.getvalue()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def call_capturing(function, *args):
|
|
24
|
+
output = io.StringIO()
|
|
25
|
+
with contextlib.redirect_stdout(output):
|
|
26
|
+
result = function(*args)
|
|
27
|
+
return result, output.getvalue()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class PyimportTests(unittest.TestCase):
|
|
31
|
+
def test_pyimport_returns_the_python_module(self):
|
|
32
|
+
import math as python_math
|
|
33
|
+
self.assertIs(parser.call_function("pyimport", ["math"]), python_math)
|
|
34
|
+
|
|
35
|
+
def test_pyimport_works_from_a_script_expression(self):
|
|
36
|
+
import json as python_json
|
|
37
|
+
self.assertIs(evaluate('pyimport("json")'), python_json)
|
|
38
|
+
|
|
39
|
+
def test_pyimport_reports_a_missing_module(self):
|
|
40
|
+
result, output = call_capturing(parser.call_function, "pyimport", ["no_such_module_xyz"])
|
|
41
|
+
self.assertIsNone(result)
|
|
42
|
+
self.assertIn("cannot import 'no_such_module_xyz'", output)
|
|
43
|
+
|
|
44
|
+
def test_pyimport_rejects_bad_arguments(self):
|
|
45
|
+
for args in ([], [1], ["math", "json"]):
|
|
46
|
+
result, output = call_capturing(parser.call_function, "pyimport", args)
|
|
47
|
+
self.assertIsNone(result)
|
|
48
|
+
self.assertIn("pyimport() expects one string argument", output)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class MethodFallbackTests(unittest.TestCase):
|
|
52
|
+
def test_fallback_calls_a_python_method(self):
|
|
53
|
+
self.assertEqual(parser.call_method("a,b,c", "split", [","]), ["a", "b", "c"])
|
|
54
|
+
self.assertEqual(parser.call_method("hello", "count", ["l"]), 2)
|
|
55
|
+
self.assertEqual(parser.call_method([3, 1, 2], "index", [2]), 2)
|
|
56
|
+
|
|
57
|
+
def test_fallback_returns_a_non_callable_attribute(self):
|
|
58
|
+
import decimal
|
|
59
|
+
value = decimal.Decimal("1.5")
|
|
60
|
+
self.assertEqual(parser.call_method(value, "real", []), value)
|
|
61
|
+
|
|
62
|
+
def test_fallback_works_from_a_script_expression(self):
|
|
63
|
+
self.assertEqual(evaluate('"a b".split(" ")'), ["a", "b"])
|
|
64
|
+
|
|
65
|
+
def test_whitelisted_methods_still_win_over_the_fallback(self):
|
|
66
|
+
# 'add' on a list appends in BrittainScript; Python lists have no add()
|
|
67
|
+
values = [1, 2]
|
|
68
|
+
self.assertIsNone(parser.call_method(values, "add", [3]))
|
|
69
|
+
self.assertEqual(values, [1, 2, 3])
|
|
70
|
+
# 'contains' and 'locate' are BrittainScript names, not Python ones
|
|
71
|
+
self.assertIs(parser.call_method("hello", "contains", ["ell"]), True)
|
|
72
|
+
self.assertEqual(parser.call_method("hello", "locate", ["l"]), 2)
|
|
73
|
+
self.assertEqual(parser.call_method(" hi ", "trim", []), "hi")
|
|
74
|
+
self.assertEqual(parser.call_method("hi", "upper", []), "HI")
|
|
75
|
+
|
|
76
|
+
def test_missing_method_reports_an_error(self):
|
|
77
|
+
result, output = call_capturing(parser.call_method, "hello", "notamethod", [])
|
|
78
|
+
self.assertIsNone(result)
|
|
79
|
+
self.assertIn("no method 'notamethod' on str", output)
|
|
80
|
+
|
|
81
|
+
def test_failing_python_call_reports_an_error(self):
|
|
82
|
+
result, output = call_capturing(parser.call_method, "hello", "split", [1, 2, 3])
|
|
83
|
+
self.assertIsNone(result)
|
|
84
|
+
self.assertIn("Error calling 'split'", output)
|
|
85
|
+
|
|
86
|
+
def test_module_methods_still_route_to_the_module_caller(self):
|
|
87
|
+
module = {"__bs_module__": True, "name": "demo", "funcs": {}}
|
|
88
|
+
calls = []
|
|
89
|
+
previous = parser.module_caller
|
|
90
|
+
parser.set_module_caller(lambda receiver, name, args: calls.append((name, args)))
|
|
91
|
+
try:
|
|
92
|
+
parser.call_method(module, "greet", ["world"])
|
|
93
|
+
finally:
|
|
94
|
+
parser.set_module_caller(previous)
|
|
95
|
+
self.assertEqual(calls, [("greet", ["world"])])
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class AttributeAccessTests(unittest.TestCase):
|
|
99
|
+
def test_attribute_access_reads_a_python_attribute(self):
|
|
100
|
+
self.assertEqual(evaluate('pyimport("math").pi'), 3.141592653589793)
|
|
101
|
+
|
|
102
|
+
def test_attribute_access_on_a_value(self):
|
|
103
|
+
parser.set_name("value", complex(3, 4))
|
|
104
|
+
self.assertEqual(evaluate("value.imag"), 4.0)
|
|
105
|
+
|
|
106
|
+
def test_method_call_syntax_is_unaffected_by_the_attribute_rule(self):
|
|
107
|
+
self.assertEqual(evaluate('"hi".upper()'), "HI")
|
|
108
|
+
self.assertEqual(evaluate('pyimport("math").floor(3.7)'), 3)
|
|
109
|
+
|
|
110
|
+
def test_missing_attribute_reports_an_error(self):
|
|
111
|
+
result, output = evaluate_capturing('"hello".notanattribute')
|
|
112
|
+
self.assertIsNone(result)
|
|
113
|
+
self.assertIn("no attribute 'notanattribute' on str", output)
|
|
114
|
+
|
|
115
|
+
def test_module_members_must_be_called(self):
|
|
116
|
+
parser.set_name("demo", {"__bs_module__": True, "name": "demo", "funcs": {}})
|
|
117
|
+
result, output = evaluate_capturing("demo.greet")
|
|
118
|
+
self.assertIsNone(result)
|
|
119
|
+
self.assertIn("'demo' members must be called", output)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class MatrixMultiplyTests(unittest.TestCase):
|
|
123
|
+
def test_matmul_uses_the_python_operator(self):
|
|
124
|
+
class Recorder:
|
|
125
|
+
def __matmul__(self, other):
|
|
126
|
+
return ("matmul", other)
|
|
127
|
+
|
|
128
|
+
parser.set_name("left", Recorder())
|
|
129
|
+
parser.set_name("right", 7)
|
|
130
|
+
self.assertEqual(evaluate("left @ right"), ("matmul", 7))
|
|
131
|
+
|
|
132
|
+
def test_matmul_on_unsupported_types_reports_an_error(self):
|
|
133
|
+
result, output = evaluate_capturing("2 @ 3")
|
|
134
|
+
self.assertIsNone(result)
|
|
135
|
+
self.assertIn("cannot matrix-multiply", output)
|
|
136
|
+
|
|
137
|
+
def test_matmul_binds_like_multiplication(self):
|
|
138
|
+
class Recorder:
|
|
139
|
+
def __init__(self, tag):
|
|
140
|
+
self.tag = tag
|
|
141
|
+
|
|
142
|
+
def __matmul__(self, other):
|
|
143
|
+
return Recorder(f"({self.tag}@{other.tag})")
|
|
144
|
+
|
|
145
|
+
def __add__(self, other):
|
|
146
|
+
return Recorder(f"({self.tag}+{other.tag})")
|
|
147
|
+
|
|
148
|
+
parser.set_name("a", Recorder("a"))
|
|
149
|
+
parser.set_name("b", Recorder("b"))
|
|
150
|
+
parser.set_name("c", Recorder("c"))
|
|
151
|
+
self.assertEqual(evaluate("a + b @ c").tag, "(a+(b@c))")
|
|
152
|
+
self.assertEqual(evaluate("a @ b @ c").tag, "((a@b)@c)")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class NumpyBridgeTests(unittest.TestCase):
|
|
156
|
+
def setUp(self):
|
|
157
|
+
try:
|
|
158
|
+
import numpy
|
|
159
|
+
except ImportError:
|
|
160
|
+
self.skipTest("numpy is not installed")
|
|
161
|
+
|
|
162
|
+
def test_numpy_flows_through_the_bridge(self):
|
|
163
|
+
source = 'pyimport("numpy").array([[1, 2], [3, 4]])'
|
|
164
|
+
matrix = evaluate(source)
|
|
165
|
+
parser.set_name("matrix", matrix)
|
|
166
|
+
self.assertEqual(evaluate("matrix.shape"), (2, 2))
|
|
167
|
+
self.assertEqual(evaluate("matrix.sum()"), 10)
|
|
168
|
+
self.assertEqual(evaluate("matrix @ matrix").tolist(), [[7, 10], [15, 22]])
|
|
169
|
+
self.assertEqual(evaluate("matrix * 2").tolist(), [[2, 4], [6, 8]])
|
|
170
|
+
self.assertEqual(evaluate("matrix[0][1]"), 2)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class TorchBridgeTests(unittest.TestCase):
|
|
174
|
+
def setUp(self):
|
|
175
|
+
try:
|
|
176
|
+
import torch
|
|
177
|
+
except ImportError:
|
|
178
|
+
self.skipTest("torch is not installed")
|
|
179
|
+
|
|
180
|
+
def test_autograd_works_through_the_bridge(self):
|
|
181
|
+
torch_module = evaluate('pyimport("torch")')
|
|
182
|
+
parser.set_name("torch", torch_module)
|
|
183
|
+
parser.set_name("weight", torch_module.ones(2, 2, requires_grad=True))
|
|
184
|
+
self.assertEqual(evaluate("weight.shape")[0], 2)
|
|
185
|
+
loss = evaluate("(weight * 3).sum()")
|
|
186
|
+
parser.set_name("loss", loss)
|
|
187
|
+
evaluate("loss.backward()")
|
|
188
|
+
self.assertEqual(evaluate("weight.grad").tolist(), [[3.0, 3.0], [3.0, 3.0]])
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if __name__ == "__main__":
|
|
192
|
+
unittest.main()
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# parsetab.py
|
|
3
|
-
# This file is automatically generated. Do not edit.
|
|
4
|
-
# pylint: disable=W,C,R
|
|
5
|
-
_tabversion = '3.10'
|
|
6
|
-
|
|
7
|
-
_lr_method = 'LALR'
|
|
8
|
-
|
|
9
|
-
_lr_signature = 'leftORleftANDrightNOTleftEQUALTONOTEQUALTOleftLESSTHANGREATERTHANLESSTHANEQUALTOGREATERTHANEQUALTOleftPLUSMINUSleftMULTIPLYDIVIDErightPOWERleftLBRACKETleftDOTADD AND COLON COMMA COND COSINE DIVIDE DOT EQ EQUALTO FALSE GREATERTHAN GREATERTHANEQUALTO LBRACKET LESSTHAN LESSTHANEQUALTO LPAREN MINUS MODULO MULTIPLY NAME NOT NOTEQUALTO NUMBER OR PI PLUS POWER PRINT RANGE RBRACKET RPAREN SINE SQUAREROOT STRING TANGENT TRUEexpression : NUMBERexpression : LPAREN expression RPARENexpression : expression PLUS expressionexpression : expression MINUS expressionexpression : expression DIVIDE expressionexpression : expression MULTIPLY expressionexpression : expression MODULO expressionexpression : expression POWER expressionexpression : SQUAREROOT LPAREN expression RPARENexpression : SINE LPAREN expression RPARENexpression : COSINE LPAREN expression RPARENexpression : TANGENT LPAREN expression RPARENexpression : PIexpression : PRINT LPAREN expression RPARENexpression : STRINGexpression : NAME EQ expressionexpression : NAMEexpression : LBRACKET optional_arguments RBRACKETexpression : expression LBRACKET expression RBRACKETexpression : expression LBRACKET optional_expression COLON optional_expression RBRACKEToptional_expression :optional_expression : expressionoptional_arguments :optional_arguments : argumentsarguments : expressionarguments : arguments COMMA expressionexpression : NAME LPAREN optional_arguments RPARENexpression : RANGE LPAREN optional_arguments RPARENexpression : expression DOT NAME LPAREN optional_arguments RPARENexpression : expression AND expressionexpression : expression OR expressionexpression : NOT expressionexpression : expression EQUALTO expressionexpression : expression NOTEQUALTO expressionexpression : expression GREATERTHAN expressionexpression : expression LESSTHAN expressionexpression : expression GREATERTHANEQUALTO expressionexpression : expression LESSTHANEQUALTO expressionexpression : TRUEexpression : FALSEexpression : COND LPAREN expression RPAREN'
|
|
10
|
-
|
|
11
|
-
_lr_action_items = {'NUMBER':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,]),'LPAREN':([0,3,4,5,6,7,9,11,12,13,14,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,56,74,78,79,],[3,3,35,36,37,38,39,41,3,45,3,47,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,79,3,3,3,]),'SQUAREROOT':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,]),'SINE':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'COSINE':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'TANGENT':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'PI':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,]),'PRINT':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,]),'STRING':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,]),'NAME':([0,3,12,14,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[11,11,11,11,11,11,11,11,11,11,11,56,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,]),'LBRACKET':([0,1,2,3,8,10,11,12,14,15,16,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,44,45,46,47,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,74,76,77,78,79,80,81,82,83,84,85,86,87,88,89,92,93,],[12,24,-1,12,-13,-15,-17,12,12,-39,-40,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,24,12,12,12,12,12,12,12,24,12,24,12,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,-2,24,24,24,24,24,24,-18,12,24,-19,12,12,-9,-10,-11,-12,-14,-27,24,-28,-41,24,-20,-29,]),'RANGE':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,]),'NOT':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,]),'TRUE':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,]),'FALSE':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,]),'COND':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,]),'$end':([1,2,8,10,11,15,16,46,48,49,50,51,52,53,57,58,59,60,61,62,63,64,65,71,73,77,80,81,82,83,84,85,87,88,92,93,],[0,-1,-13,-15,-17,-39,-40,-32,-3,-4,-5,-6,-7,-8,-30,-31,-33,-34,-35,-36,-37,-38,-2,-16,-18,-19,-9,-10,-11,-12,-14,-27,-28,-41,-20,-29,]),'PLUS':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[18,-1,-13,-15,-17,-39,-40,18,18,18,-3,-4,-5,-6,18,-8,18,18,18,18,18,18,18,18,18,-2,18,18,18,18,18,18,-18,18,-19,-9,-10,-11,-12,-14,-27,18,-28,-41,18,-20,-29,]),'MINUS':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[19,-1,-13,-15,-17,-39,-40,19,19,19,-3,-4,-5,-6,19,-8,19,19,19,19,19,19,19,19,19,-2,19,19,19,19,19,19,-18,19,-19,-9,-10,-11,-12,-14,-27,19,-28,-41,19,-20,-29,]),'DIVIDE':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[20,-1,-13,-15,-17,-39,-40,20,20,20,20,20,-5,-6,20,-8,20,20,20,20,20,20,20,20,20,-2,20,20,20,20,20,20,-18,20,-19,-9,-10,-11,-12,-14,-27,20,-28,-41,20,-20,-29,]),'MULTIPLY':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[21,-1,-13,-15,-17,-39,-40,21,21,21,21,21,-5,-6,21,-8,21,21,21,21,21,21,21,21,21,-2,21,21,21,21,21,21,-18,21,-19,-9,-10,-11,-12,-14,-27,21,-28,-41,21,-20,-29,]),'MODULO':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[22,-1,-13,-15,-17,-39,-40,22,22,-32,-3,-4,-5,-6,22,-8,22,-30,-31,-33,-34,-35,-36,-37,-38,-2,22,22,22,22,22,22,-18,22,-19,-9,-10,-11,-12,-14,-27,22,-28,-41,22,-20,-29,]),'POWER':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[23,-1,-13,-15,-17,-39,-40,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,-2,23,23,23,23,23,23,-18,23,-19,-9,-10,-11,-12,-14,-27,23,-28,-41,23,-20,-29,]),'DOT':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[25,-1,-13,-15,-17,-39,-40,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,-2,25,25,25,25,25,25,-18,25,-19,-9,-10,-11,-12,-14,-27,25,-28,-41,25,-20,-29,]),'AND':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[26,-1,-13,-15,-17,-39,-40,26,26,-32,-3,-4,-5,-6,26,-8,26,-30,26,-33,-34,-35,-36,-37,-38,-2,26,26,26,26,26,26,-18,26,-19,-9,-10,-11,-12,-14,-27,26,-28,-41,26,-20,-29,]),'OR':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[27,-1,-13,-15,-17,-39,-40,27,27,-32,-3,-4,-5,-6,27,-8,27,-30,-31,-33,-34,-35,-36,-37,-38,-2,27,27,27,27,27,27,-18,27,-19,-9,-10,-11,-12,-14,-27,27,-28,-41,27,-20,-29,]),'EQUALTO':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[28,-1,-13,-15,-17,-39,-40,28,28,28,-3,-4,-5,-6,28,-8,28,28,28,-33,-34,-35,-36,-37,-38,-2,28,28,28,28,28,28,-18,28,-19,-9,-10,-11,-12,-14,-27,28,-28,-41,28,-20,-29,]),'NOTEQUALTO':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[29,-1,-13,-15,-17,-39,-40,29,29,29,-3,-4,-5,-6,29,-8,29,29,29,-33,-34,-35,-36,-37,-38,-2,29,29,29,29,29,29,-18,29,-19,-9,-10,-11,-12,-14,-27,29,-28,-41,29,-20,-29,]),'GREATERTHAN':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[30,-1,-13,-15,-17,-39,-40,30,30,30,-3,-4,-5,-6,30,-8,30,30,30,30,30,-35,-36,-37,-38,-2,30,30,30,30,30,30,-18,30,-19,-9,-10,-11,-12,-14,-27,30,-28,-41,30,-20,-29,]),'LESSTHAN':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[31,-1,-13,-15,-17,-39,-40,31,31,31,-3,-4,-5,-6,31,-8,31,31,31,31,31,-35,-36,-37,-38,-2,31,31,31,31,31,31,-18,31,-19,-9,-10,-11,-12,-14,-27,31,-28,-41,31,-20,-29,]),'GREATERTHANEQUALTO':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[32,-1,-13,-15,-17,-39,-40,32,32,32,-3,-4,-5,-6,32,-8,32,32,32,32,32,-35,-36,-37,-38,-2,32,32,32,32,32,32,-18,32,-19,-9,-10,-11,-12,-14,-27,32,-28,-41,32,-20,-29,]),'LESSTHANEQUALTO':([1,2,8,10,11,15,16,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,76,77,80,81,82,83,84,85,86,87,88,89,92,93,],[33,-1,-13,-15,-17,-39,-40,33,33,33,-3,-4,-5,-6,33,-8,33,33,33,33,33,-35,-36,-37,-38,-2,33,33,33,33,33,33,-18,33,-19,-9,-10,-11,-12,-14,-27,33,-28,-41,33,-20,-29,]),'RPAREN':([2,8,10,11,15,16,34,41,43,44,45,46,48,49,50,51,52,53,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,79,80,81,82,83,84,85,86,87,88,91,92,93,],[-1,-13,-15,-17,-39,-40,65,-23,-24,-25,-23,-32,-3,-4,-5,-6,-7,-8,-30,-31,-33,-34,-35,-36,-37,-38,-2,80,81,82,83,84,-16,85,-18,87,88,-19,-23,-9,-10,-11,-12,-14,-27,-26,-28,-41,93,-20,-29,]),'COMMA':([2,8,10,11,15,16,43,44,46,48,49,50,51,52,53,57,58,59,60,61,62,63,64,65,71,73,77,80,81,82,83,84,85,86,87,88,92,93,],[-1,-13,-15,-17,-39,-40,74,-25,-32,-3,-4,-5,-6,-7,-8,-30,-31,-33,-34,-35,-36,-37,-38,-2,-16,-18,-19,-9,-10,-11,-12,-14,-27,-26,-28,-41,-20,-29,]),'RBRACKET':([2,8,10,11,12,15,16,42,43,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,65,71,73,77,78,80,81,82,83,84,85,86,87,88,89,90,92,93,],[-1,-13,-15,-17,-23,-39,-40,73,-24,-25,-32,-3,-4,-5,-6,-7,-8,77,-30,-31,-33,-34,-35,-36,-37,-38,-2,-16,-18,-19,-21,-9,-10,-11,-12,-14,-27,-26,-28,-41,-22,92,-20,-29,]),'COLON':([2,8,10,11,15,16,24,46,48,49,50,51,52,53,54,55,57,58,59,60,61,62,63,64,65,71,73,77,80,81,82,83,84,85,87,88,92,93,],[-1,-13,-15,-17,-39,-40,-21,-32,-3,-4,-5,-6,-7,-8,-22,78,-30,-31,-33,-34,-35,-36,-37,-38,-2,-16,-18,-19,-9,-10,-11,-12,-14,-27,-28,-41,-20,-29,]),'EQ':([11,],[40,]),}
|
|
12
|
-
|
|
13
|
-
_lr_action = {}
|
|
14
|
-
for _k, _v in _lr_action_items.items():
|
|
15
|
-
for _x,_y in zip(_v[0],_v[1]):
|
|
16
|
-
if not _x in _lr_action: _lr_action[_x] = {}
|
|
17
|
-
_lr_action[_x][_k] = _y
|
|
18
|
-
del _lr_action_items
|
|
19
|
-
|
|
20
|
-
_lr_goto_items = {'expression':([0,3,12,14,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,45,47,74,78,79,],[1,34,44,46,48,49,50,51,52,53,54,57,58,59,60,61,62,63,64,66,67,68,69,70,71,44,44,76,86,89,44,]),'optional_arguments':([12,41,45,79,],[42,72,75,91,]),'arguments':([12,41,45,79,],[43,43,43,43,]),'optional_expression':([24,78,],[55,90,]),}
|
|
21
|
-
|
|
22
|
-
_lr_goto = {}
|
|
23
|
-
for _k, _v in _lr_goto_items.items():
|
|
24
|
-
for _x, _y in zip(_v[0], _v[1]):
|
|
25
|
-
if not _x in _lr_goto: _lr_goto[_x] = {}
|
|
26
|
-
_lr_goto[_x][_k] = _y
|
|
27
|
-
del _lr_goto_items
|
|
28
|
-
_lr_productions = [
|
|
29
|
-
("S' -> expression","S'",1,None,None,None),
|
|
30
|
-
('expression -> NUMBER','expression',1,'p_expression_number','parser.py',79),
|
|
31
|
-
('expression -> LPAREN expression RPAREN','expression',3,'p_expression_group','parser.py',83),
|
|
32
|
-
('expression -> expression PLUS expression','expression',3,'p_expression_plus','parser.py',87),
|
|
33
|
-
('expression -> expression MINUS expression','expression',3,'p_expression_minus','parser.py',95),
|
|
34
|
-
('expression -> expression DIVIDE expression','expression',3,'p_expression_divide','parser.py',99),
|
|
35
|
-
('expression -> expression MULTIPLY expression','expression',3,'p_expression_times','parser.py',107),
|
|
36
|
-
('expression -> expression MODULO expression','expression',3,'p_expression_modulo','parser.py',115),
|
|
37
|
-
('expression -> expression POWER expression','expression',3,'p_expression_power','parser.py',119),
|
|
38
|
-
('expression -> SQUAREROOT LPAREN expression RPAREN','expression',4,'p_expression_squareroot','parser.py',123),
|
|
39
|
-
('expression -> SINE LPAREN expression RPAREN','expression',4,'p_expression_sine','parser.py',127),
|
|
40
|
-
('expression -> COSINE LPAREN expression RPAREN','expression',4,'p_expression_cosine','parser.py',131),
|
|
41
|
-
('expression -> TANGENT LPAREN expression RPAREN','expression',4,'p_expression_tangent','parser.py',135),
|
|
42
|
-
('expression -> PI','expression',1,'p_expression_pi','parser.py',139),
|
|
43
|
-
('expression -> PRINT LPAREN expression RPAREN','expression',4,'p_expression_print','parser.py',143),
|
|
44
|
-
('expression -> STRING','expression',1,'p_expression_string','parser.py',148),
|
|
45
|
-
('expression -> NAME EQ expression','expression',3,'p_statement_assign','parser.py',152),
|
|
46
|
-
('expression -> NAME','expression',1,'p_expression_name','parser.py',157),
|
|
47
|
-
('expression -> LBRACKET optional_arguments RBRACKET','expression',3,'p_expression_list','parser.py',165),
|
|
48
|
-
('expression -> expression LBRACKET expression RBRACKET','expression',4,'p_expression_index','parser.py',169),
|
|
49
|
-
('expression -> expression LBRACKET optional_expression COLON optional_expression RBRACKET','expression',6,'p_expression_slice','parser.py',177),
|
|
50
|
-
('optional_expression -> <empty>','optional_expression',0,'p_optional_expression_empty','parser.py',185),
|
|
51
|
-
('optional_expression -> expression','optional_expression',1,'p_optional_expression_value','parser.py',189),
|
|
52
|
-
('optional_arguments -> <empty>','optional_arguments',0,'p_optional_arguments_empty','parser.py',193),
|
|
53
|
-
('optional_arguments -> arguments','optional_arguments',1,'p_optional_arguments_value','parser.py',197),
|
|
54
|
-
('arguments -> expression','arguments',1,'p_arguments_single','parser.py',201),
|
|
55
|
-
('arguments -> arguments COMMA expression','arguments',3,'p_arguments_many','parser.py',205),
|
|
56
|
-
('expression -> NAME LPAREN optional_arguments RPAREN','expression',4,'p_expression_function_call','parser.py',209),
|
|
57
|
-
('expression -> RANGE LPAREN optional_arguments RPAREN','expression',4,'p_expression_range_call','parser.py',213),
|
|
58
|
-
('expression -> expression DOT NAME LPAREN optional_arguments RPAREN','expression',6,'p_expression_method_call','parser.py',217),
|
|
59
|
-
('expression -> expression AND expression','expression',3,'p_expression_and','parser.py',402),
|
|
60
|
-
('expression -> expression OR expression','expression',3,'p_expression_or','parser.py',406),
|
|
61
|
-
('expression -> NOT expression','expression',2,'p_expression_not','parser.py',410),
|
|
62
|
-
('expression -> expression EQUALTO expression','expression',3,'p_expression_equalto','parser.py',414),
|
|
63
|
-
('expression -> expression NOTEQUALTO expression','expression',3,'p_expression_notequalto','parser.py',418),
|
|
64
|
-
('expression -> expression GREATERTHAN expression','expression',3,'p_expression_greaterthan','parser.py',422),
|
|
65
|
-
('expression -> expression LESSTHAN expression','expression',3,'p_expression_lessthan','parser.py',426),
|
|
66
|
-
('expression -> expression GREATERTHANEQUALTO expression','expression',3,'p_expression_greaterthanequalto','parser.py',430),
|
|
67
|
-
('expression -> expression LESSTHANEQUALTO expression','expression',3,'p_expression_lessthanequalto','parser.py',434),
|
|
68
|
-
('expression -> TRUE','expression',1,'p_expression_true','parser.py',438),
|
|
69
|
-
('expression -> FALSE','expression',1,'p_expression_false','parser.py',442),
|
|
70
|
-
('expression -> COND LPAREN expression RPAREN','expression',4,'p_expression_cond','parser.py',446),
|
|
71
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|