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.
Files changed (30) hide show
  1. {brittainscript-0.2.0 → brittainscript-0.3.0}/Documentation/README.md +112 -0
  2. {brittainscript-0.2.0 → brittainscript-0.3.0}/PKG-INFO +113 -1
  3. {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/PKG-INFO +113 -1
  4. {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/SOURCES.txt +3 -1
  5. {brittainscript-0.2.0 → brittainscript-0.3.0}/core/lexer.py +11 -0
  6. {brittainscript-0.2.0 → brittainscript-0.3.0}/core/parser.py +48 -3
  7. brittainscript-0.3.0/core/parsetab.py +73 -0
  8. {brittainscript-0.2.0 → brittainscript-0.3.0}/pyproject.toml +1 -1
  9. brittainscript-0.3.0/tests/test_operator_precedence.py +59 -0
  10. brittainscript-0.3.0/tests/test_python_bridge.py +192 -0
  11. brittainscript-0.2.0/core/parsetab.py +0 -71
  12. {brittainscript-0.2.0 → brittainscript-0.3.0}/LICENSE +0 -0
  13. {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/dependency_links.txt +0 -0
  14. {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/entry_points.txt +0 -0
  15. {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/requires.txt +0 -0
  16. {brittainscript-0.2.0 → brittainscript-0.3.0}/brittainscript.egg-info/top_level.txt +0 -0
  17. {brittainscript-0.2.0 → brittainscript-0.3.0}/core/__init__.py +0 -0
  18. {brittainscript-0.2.0 → brittainscript-0.3.0}/core/gui_backend.py +0 -0
  19. {brittainscript-0.2.0 → brittainscript-0.3.0}/core/main.py +0 -0
  20. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/__init__.py +0 -0
  21. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/convert.bs +0 -0
  22. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/datetime.bs +0 -0
  23. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/gui.bs +0 -0
  24. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/io.bs +0 -0
  25. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/math.bs +0 -0
  26. {brittainscript-0.2.0 → brittainscript-0.3.0}/libs/terminal.bs +0 -0
  27. {brittainscript-0.2.0 → brittainscript-0.3.0}/setup.cfg +0 -0
  28. {brittainscript-0.2.0 → brittainscript-0.3.0}/tests/test_datetime_builtin.py +0 -0
  29. {brittainscript-0.2.0 → brittainscript-0.3.0}/tests/test_gui_builtins.py +0 -0
  30. {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.2.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.2.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.
@@ -22,4 +22,6 @@ libs/math.bs
22
22
  libs/terminal.bs
23
23
  tests/test_datetime_builtin.py
24
24
  tests/test_gui_builtins.py
25
- tests/test_parser_builtins.py
25
+ tests/test_operator_precedence.py
26
+ tests/test_parser_builtins.py
27
+ tests/test_python_bridge.py
@@ -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
- print(f"Error: unsupported method {name}()")
439
- return None
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
+ ]
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "brittainscript"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "The BrittainScript programming language interpreter"
9
9
  readme = "Documentation/README.md"
10
10
  license = { file = "LICENSE" }
@@ -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