Skip to content

Commit d9e6179

Browse files
Remove square brackets as block delimiters: only curly brackets are now supported
1 parent 8c1517c commit d9e6179

File tree

4 files changed

+24
-35
lines changed

4 files changed

+24
-35
lines changed

asmln.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def _output_sink(text: str) -> None:
5252
uc = stripped.upper()
5353
if uc.startswith("FUNC") or uc.startswith("IF") or uc.startswith("WHILE") or uc.startswith("FOR"):
5454
is_block_start = True
55-
if stripped.endswith("[") or stripped.endswith("{"):
55+
if stripped.endswith("{"):
5656
is_block_start = True
5757

5858
if not buffer and stripped != "" and not is_block_start:

lexer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ class Token:
3636
SYMBOLS = {
3737
"(": "LPAREN",
3838
")": "RPAREN",
39-
"[": "LBRACKET",
40-
"]": "RBRACKET",
4139
"{": "LBRACE",
4240
"}": "RBRACE",
4341
",": "COMMA",

parser.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,14 +289,11 @@ def _parse_continue(self) -> ContinueStatement:
289289

290290
def _parse_block(self) -> Block:
291291
opening = self._peek().type
292-
if opening == "LBRACKET":
293-
start = self._consume("LBRACKET")
294-
closing = "RBRACKET"
295-
elif opening == "LBRACE":
292+
if opening == "LBRACE":
296293
start = self._consume("LBRACE")
297294
closing = "RBRACE"
298295
else:
299-
raise ASMParseError(f"Expected '[' or '{{' to start block but found {opening}")
296+
raise ASMParseError(f"Expected '{{' to start block but found {opening}")
300297
statements: List[Statement] = self._parse_statements(stop_tokens={closing})
301298
self._consume(closing)
302299
return Block(location=self._location_from_token(start), statements=statements)

spec.txt

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ line. Comments have no effect on execution.
4848

4949
The program text is divided into several token kinds: binary integer literals
5050
(Section 3.1); string literals delimited by double or single quotation marks
51-
('"', "'", Section 3.2); identifiers for variable names and user-defined
51+
("\"", "'", Section 3.2); identifiers for variable names and user-defined
5252
function names (Section 2.5); keywords and built-ins (control-flow keywords,
5353
built-in operators and functions; see Sections 4 and 5); and delimiters, namely
54-
'(', ')', '[', ']', '{', '}', ',', ':', and '='.
54+
'(', ')', '{', '}', ',', ':', and '='.
5555

5656
Keywords: The language's reserved keywords (for example, 'IF', 'WHILE', 'FUNC',
5757
etc.) are matched by the lexer exactly as listed in this specification and are
@@ -110,7 +110,7 @@ match the reference lexer implementation:
110110
'; / ! @ $ % & ~ _ + | < > ?'
111111

112112
As noted above, non-ASCII characters remain disallowed, and the delimiter
113-
characters '{', '}', '[', ']', '(', ')', '=', ',', and '#' are never
113+
characters '{', '}', '(', ')', '=', ',', and '#' are never
114114
permitted inside identifiers.
115115

116116
This deliberately-permissive identifier character set preserves an unambiguous
@@ -233,11 +233,8 @@ expression statements such as calls to 'PRINT' whose result is ignored,
233233
control-flow constructs ('IF', 'ELSIF', 'ELSE', 'WHILE', and 'FOR'), and
234234
function definitions ('FUNC' declarations; see Section 6).
235235

236-
Blocks group one or more statements and are enclosed in either square or curly
237-
brackets: '[ statement1 ... statementN ]' or '{ statement1 ... statementN }'.
238-
The two bracket styles are equivalent but must match (that is, '[' closes with
239-
']' and '{' closes with '}'). Blocks serve as the bodies of control-flow
240-
constructs and functions.
236+
Blocks group one or more statements and are enclosed in curly brackets: '{ statement1 ... statementN }'.
237+
Curly braces must match (that is, '{' closes with '}'). Blocks serve as the bodies of control-flow constructs and functions.
241238

242239
Assignments have the syntax 'TYPE : identifier = expression' on first use,
243240
where TYPE is 'INT' or 'STR'. Spaces around the colon and equals sign are
@@ -246,11 +243,10 @@ but must preserve the original type. Variables are deallocated only when
246243
'DEL(identifier)' is executed.
247244

248245
The language provides 'IF', 'ELSIF', and 'ELSE' constructs for conditional
249-
execution. An 'IF' statement has the general form 'IF(condition)[ block ]' or
250-
'IF(condition){ block }'. Optional chained branches may follow: one or more
251-
'ELSIF(condition)[ block ]' or 'ELSIF(condition){ block }' clauses and an
252-
optional terminal 'ELSE[ block ]' or 'ELSE{ block }' clause. An 'ELSIF' or
253-
'ELSE' must immediately follow an 'IF' or another 'ELSIF'; otherwise it is a
246+
execution. An 'IF' statement has the general form 'IF(condition){ block }'.
247+
Optional chained branches may follow: one or more 'ELSIF(condition){ block }'
248+
clauses and an optional terminal 'ELSE{ block }' clause. An 'ELSIF' or 'ELSE'
249+
must immediately follow an 'IF' or another 'ELSIF'; otherwise it is a
254250
syntax error. At most one 'ELSE' may appear in a given chain. Evaluation
255251
proceeds by first evaluating the condition of the initial 'IF'. If it is
256252
non-zero, the associated block executes and the rest of the chain is skipped.
@@ -264,14 +260,13 @@ the 'INT' built-in rules (empty -> 0; binary string -> that integer; other
264260
non-empty -> 1) before truthiness is checked.
265261

266262
Loops are provided via 'WHILE' and 'FOR'. A 'WHILE' loop has the form
267-
'WHILE(condition)[ block ]' or 'WHILE(condition){ block }'. On each iteration,
263+
'WHILE(condition){ block }'. On each iteration,
268264
the condition is evaluated; if it is non-zero, the block executes and control
269265
returns to the start of the loop to evaluate the condition again. If the
270266
condition evaluates to zero, the loop terminates and execution continues with
271267
the next statement.
272268

273-
The 'FOR' construct has the form 'FOR(counter, target)[ block ]' or
274-
'FOR(counter, target){ block }', where 'counter' is an identifier and 'target'
269+
The 'FOR' construct has the form 'FOR(counter, target){ block }', where 'counter' is an identifier and 'target'
275270
is an expression. At loop entry, 'target' is evaluated once to a value 'T'
276271
(must be INT), and 'counter' is initialized to the INT value '0', creating it
277272
as an INT if necessary. The loop then repeats: if the current value of
@@ -307,8 +302,7 @@ tracebacks remain deterministic.
307302

308303
Functions are defined using the 'FUNC' keyword with explicit parameter and
309304
return types. The canonical positional-only form is
310-
'FUNC name(T1:arg1, T2:arg2, ..., TN:argN):R[ block ]' or
311-
'FUNC name(T1:arg1, ..., TN:argN):R{ block }', where each 'Tk' and 'R' is
305+
'FUNC name(T1:arg1, T2:arg2, ..., TN:argN):R{ block }', where each 'Tk' and 'R' is
312306
either 'INT' or 'STR'. Parameters may also declare a call-time default value
313307
using 'Tk:arg=expr'. A parameter without a default is positional; a parameter
314308
with a default is keyword-capable. Positional parameters must appear before
@@ -620,7 +614,7 @@ semantics as file-mode execution. The following rules describe REPL behaviour:
620614
immediately and return the supplied exit code (or '0' if omitted), identical
621615
to the behaviour when 'EXIT()' is executed in a file.
622616
- Multi-line buffering: if a statement begins a block (for example a 'FUNC'
623-
definition or an 'IF(...)[' that spans multiple lines), the REPL buffers
617+
definition or an 'IF(...){' that spans multiple lines), the REPL buffers
624618
lines until the block is complete (a blank line may be used to indicate
625619
end-of-entry when appropriate). When the buffer is complete the REPL parses
626620
and executes the collected statements as a unit.
@@ -836,17 +830,17 @@ Host and environment information:
836830
Control / Function / Statement Signatures (statement position)
837831
- Assignment: 'TYPE : identifier = expression' on first use; subsequent
838832
assignments omit TYPE but must match the original type
839-
- Block: '[ statement1 ... statementN ]' or '{ statement1 ... statementN }'
840-
- 'IF(condition)[ block ]'
841-
(optional 'ELSIF(condition)[ block ]' ... 'ELSE[ block ]')
842-
- 'WHILE(condition)[ block ]'
843-
- 'FOR(counter, target)[ block ]' ; 'counter' initialized to 0, loop until
833+
- Block: '{ statement1 ... statementN }'
834+
- 'IF(condition){ block }'
835+
(optional 'ELSIF(condition){ block }' ... 'ELSE{ block }')
836+
- 'WHILE(condition){ block }'
837+
- 'FOR(counter, INT: target){ block }' ; 'counter' initialized to 0, loop until
844838
counter >= target
845-
- 'FUNC name(T1:arg1, T2:arg2, ..., TN:argN):R[ block ]' ; typed function
839+
'FUNC name(T1:arg1, T2:arg2, ..., TN:argN):R{ block }' ; typed function
846840
definition with return type R; optional defaults use 'Tk:arg=expr' and must
847841
appear only after all positional parameters
848-
- 'RETURN(a)' ; return from function with value 'a'
849-
- 'BREAK(n)' ; break out of the innermost 'n' enclosing loops; raises a
842+
- 'RETURN(ANY: a)' ; return from function with value 'a'
843+
- 'BREAK(INT: n)' ; break out of the innermost 'n' enclosing loops; raises a
850844
runtime error if 'n' ≤ 0 or if 'n' is greater than the current loop nesting
851845
depth
852846
- 'CONTINUE()' ; skip remaining statements in the innermost loop iteration

0 commit comments

Comments
 (0)