5 Reader specs
This chapter defines reader-spec source, lexical structure, syntax, placement, format metadata, and parser limits. The formal productions are in grammar.ebnf; appendix A explains its layers and named predicates. Chapter 6 defines types and value reads. Further execution rules belong to chapter 7 (input structure and patterns), chapter 8 (evaluation, checks, and record names), and chapter 9 (parameters, instances, and catalog). Chapter 10 defines work budgets.
5.1 Reader specs and parsing
A reader spec MAY be empty. Parsing MUST proceed in this order:
- Validate the entire source byte sequence as UTF-8.
- Lex the complete source into tokens.
- Parse statements, including embedded line patterns and their types.
- Check comprehension-binding/value conflicts, then named-type/value conflicts, then structural-name conflicts, then resolve expressions. §11.2 defines the order within each phase.
Source validation MUST use strict UTF-8: reject malformed continuation sequences, truncated sequences, overlong encodings, surrogate encodings, and encodings above U+10FFFF. Implementations MUST NOT normalize Unicode or strip a BOM. NUL, noncharacters, and U+FEFF are valid scalar values; the lexical rules still restrict where they can occur.
Invalid source MUST report E-SPEC-UTF8
at the first byte of the first ill-formed subsequence. Its reader-spec
line is one plus the number of preceding LF bytes; its column is one plus
the number of bytes since the preceding LF, or since the start of source.
Tabs and each byte of a multibyte character each occupy one column. The
error MUST have null input location, context, and record path. This
Iris-defined position also applies to truncated sequences, whose initial
byte is the error position.
This check precedes every other parse-time error, even an earlier lexical error. The requirement is a deliberate difference from Gecode 6.5.0. Input validation is separate; see §4.10.
Iris-only UTF-8 requirement; Gecode accepts these bytes. The invalid byte is inside a reader-spec string.
id: reader-invalid-utf8-stringoperation: parse--- spec hex6c 65 74 20 73 3d 22 ff 22--- expected error{"code": "E-SPEC-UTF8", "message": "reader spec is not valid UTF-8", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": 8}, "context": null, "record_path": null}Iris-only UTF-8 requirement; Gecode accepts these bytes. The invalid byte is in a comment on line 2, at byte column 4.
id: reader-invalid-utf8-commentoperation: parse--- spec hex78 3a 69 6e 74 0a 23 20 20 ff--- expected error{"code": "E-SPEC-UTF8", "message": "reader spec is not valid UTF-8", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 2, "column": 4}, "context": null, "record_path": null}After source validation, complete-source lexing MUST precede statement
parsing. A bad string at the end can therefore precede an unknown statement
at the start. Pattern strings are compiled during statement parsing, not
during source lexing. Syntactic recognition alone does not guarantee a
successful parse: name conflicts, unknown functions, type requirements,
and record-scope errors are also parse-time failures.
§11.2 defines error order. Except for
E-SPEC-UTF8, reader-spec parse errors report a line and a null column.
5.2 White space and comments
Reader-spec whitespace MUST consist of these ASCII bytes: space (20),
tab (09), LF (0a), CR (0d), vertical tab (0b), and form feed (0c),
in hexadecimal. Only LF increments the reader-spec line number. A final LF
is OPTIONAL; a lone CR does not end a physical line.
Outside a quoted string, # MUST begin a comment through the next LF or
end of source. It needs no preceding whitespace. CR does not end a comment.
Whitespace and comments MUST separate tokens without producing tokens.
They do not separate statements or stop expressions.
Every non-ASCII character outside a string or comment MUST report
E-SPEC-CHARACTER. This includes a valid
UTF-8 BOM at the start of source. Ill-formed UTF-8 anywhere instead fails
the earlier source-validation phase. An unrecognized ASCII character also
reports E-SPEC-CHARACTER, except that a literal NUL is tokenized as
punctuation with no syntactic role and consequently gives E-SPEC-SYNTAX.
Semicolons are not statement separators; //
is two division tokens, not a comment.
The lexer MUST choose the longest punctuation token starting at its
position. The complete punctuation inventory is in grammar.ebnf.
An identifier and a number need not be separated by whitespace:
let x=1e2foo:int consists of a float expression followed by a declaration
named foo.
id: reader-unexpected-characteroperation: parse--- speclet x=@--- expected error{"code": "E-SPEC-CHARACTER", "message": "unexpected character '@'", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}5.3 Strings
A string MUST start and end with double quotes. Its contents MAY include
any Unicode scalar value except an unescaped double quote, backslash, or
physical LF. A physical LF, even immediately after backslash, or end of
source before the closing quote MUST report
E-SPEC-STRING.
Exactly four escapes MUST be recognized. They yield the named characters:
| Source escape | Character |
|---|---|
\n |
LF, U+000A |
\t |
Tab, U+0009 |
\\ |
Backslash, U+005C |
\" |
Double quote, U+0022 |
Every other escape MUST report E-SPEC-STRING. In particular, there are
no \r, \0, hexadecimal, Unicode, or escaped-slash forms. Literal CR
and NUL are permitted; their example transport requires a hex spec part
under §2.4.
Escaped LF is string content and does not increment the source line count.
id: reader-comments-and-stringsoperation: read--- spec no-final-newlinelet s = "a\nb\tc\\d\"e" # commentn: int--- input no-final-newline7--- expected data{"iris": "0.1", "entries": [ {"name": "s", "type": "string", "depth": 0, "value": "a\nb\tc\\d\"e"}, {"name": "n", "type": "int", "depth": 0, "value": 7}]}id: reader-invalid-escapeoperation: parse--- spec no-final-newlinelet s="\r"--- expected error{"code": "E-SPEC-STRING", "message": "unknown escape '\\r' in string (use \\n, \\t, \\\\, or \\\")", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}This complete source uses all six whitespace bytes, literal CR and NUL in its string, and a comment containing CR. Only LF ends the comment.
id: reader-source-bytesoperation: read--- spec hex09 0d 0b 0c 6c 65 74 20 73 3d 22 61 0d 00 62 22 23 20 63 6f 6d 6d 65 6e 74 0d 73 74 69 6c 6c 20 63 6f 6d 6d 65 6e 74 0a 6e 3a 69 6e 74--- input no-final-newline7--- expected data{"iris": "0.1", "entries": [ {"name": "s", "type": "string", "depth": 0, "value": "a\r\u0000b"}, {"name": "n", "type": "int", "depth": 0, "value": 7}]}5.4 Names
An ordinary name MUST match ASCII [A-Za-z_][A-Za-z0-9_]*. Names are
case-sensitive. Keywords are contextual: statement and option words MAY
be declaration names, subject to the top-level format exception in
§5.9.
id: reader-keyword-declarationsoperation: read--- spec no-final-newlineline: int type: 0.. list: word each: int layout: int--- input no-final-newline1 2 a 3 4--- expected data{"iris": "0.1", "entries": [ {"name": "line", "type": "int", "depth": 0, "value": 1}, {"name": "type", "type": "int", "depth": 0, "value": 2}, {"name": "list", "type": "string", "depth": 0, "value": "a"}, {"name": "each", "type": "int", "depth": 0, "value": 3}, {"name": "layout", "type": "int", "depth": 0, "value": 4}]}Dots are postfix field access, not part of an ordinary definition name.
Whitespace and comments MAY surround dots and brackets in expressions.
For example, xs [0] . a selects the same field as xs[0].a.
A glued gecode. followed by one or more ASCII letters, digits, or
underscores MUST instead form one identifier token. Its suffix MAY begin
with a digit. Thus gecode.int_max is one token, while gecode . int_max
is three tokens and uses field syntax. gecode alone is an ordinary name.
Definitions using the gecode. prefix MUST report
E-SPEC-NAME. This applies to declarations,
let, param, type, lists, as, each, store, and comprehension
bindings. The two known host constants and errors for unknown constants
are defined in §8.11.
Pattern names use the ordinary-name form, not this special token form.
_ MUST be accepted as a declaration, list, or capture name, and in
as, each, and store positions. It MUST NOT be accepted as the defined
name of let, param, or type, or as a comprehension binding; these
fail with E-SPEC-NAME. It is not universally discarded: store _
stores an entry named _. §6.3
defines declaration and list discards.
§7.2 defines capture discards;
§7.6 defines record structure.
§8.12 defines
record-name resolution;
§8.10 defines comprehension bindings.
Reserved/discard definition checks occur after consuming the name. Their reported line MAY therefore be the following token's line; implementations MUST preserve that position rather than substitute the name's start.
id: reader-record-fieldsoperation: read--- spec no-final-newlinerepeat 1 as xs {each x a:int} check x.a==xs[0].a let first=xs[0].a--- input no-final-newline4--- expected data{"iris": "0.1", "entries": [ {"name": "a", "type": "int", "depth": 1, "value": [4]}, {"name": "first", "type": "int", "depth": 0, "value": 4}]}5.5 Numbers
A numeric literal token MUST start with an ASCII digit. Unary minus is a
separate operator; unary plus does not exist. Consequently .5 and +1
are not expression literals, although input conversion accepts those
spellings under §§4.4–4.5.
Starting at a digit, the lexer MUST scan digits, dots, e, E, and a sign
only immediately after e or E. It MUST truncate this candidate before
its first .., if any, then validate and convert the entire remaining
candidate. Thus 0..9 contains a range operator; 1.2.3 is one invalid
number, not several tokens. Failure MUST report
E-SPEC-NUMBER.
An all-digit candidate MUST be an integer token from 0 through
9223372036854775807 inclusive. Leading zeros are decimal. The source
-9223372036854775808 fails because its positive literal token overflows
before unary negation. The minimum integer can be constructed by
-9223372036854775807-1.
Every other candidate MUST be a decimal float: digits followed by a decimal
point and optional fractional digits, an exponent, or both. An exponent
has e or E, an optional sign, and one or more digits. Accepted spellings
include 1., 1.e2, and 01e+2. Conversion MUST obey the binary64
rounding, overflow, and underflow rules in
§4.5, with E-SPEC-NUMBER on failure.
There are no hexadecimal, infinity, or NaN literals.
id: reader-number-spellingsoperation: read--- spec no-final-newlinelet i=007 let f=1.e2 let lo=-9223372036854775807-1--- input no-final-newline--- expected data{"iris": "0.1", "entries": [ {"name": "i", "type": "int", "depth": 0, "value": 7}, {"name": "f", "type": "float", "depth": 0, "value": 100}, {"name": "lo", "type": "int", "depth": 0, "value": -9223372036854775808}]}id: reader-number-overflowoperation: parse--- spec no-final-newlinelet x=-9223372036854775808--- expected error{"code": "E-SPEC-NUMBER", "message": "bad number 9223372036854775808", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}5.6 Statements, declarations, and blocks
Statements MUST be sequenced without separators. LF is whitespace, so an expression MUST continue across it when an operator follows.
id: reader-statement-sequencingoperation: read--- spec no-final-newlinelet x=1+2 y:int--- input no-final-newline4--- expected data{"iris": "0.1", "entries": [ {"name": "x", "type": "int", "depth": 0, "value": 3}, {"name": "y", "type": "int", "depth": 0, "value": 4}]}At a statement position, the parser MUST first test for a declaration:
an identifier, zero or more balanced square-bracket token groups, then a
colon. Only punctuation tokens count as brackets; brackets inside strings
do not. If this lookahead succeeds, the statement MUST be parsed as a
declaration, even when its name is a keyword. Otherwise its first identifier
MUST name a statement. Unknown statements and missing syntax report
E-SPEC-SYNTAX.
The statement forms and their semantic chapters are:
| Forms | Defining chapter |
|---|---|
Declarations, list, type |
6, types and value reads |
expect, line, find, skip, index, repeat, each, sections, if |
7, input structure |
let |
§7.9, execution; chapter 8: expressions |
check |
§8.13: checks |
param, instances |
9, parameters and instances |
A block MUST be a brace-enclosed sequence of statements. It MAY be empty.
Blocks occur as repeat and instances bodies, if/else bodies, and optional
sections-arm bodies. Standalone blocks are not statements. The outer
braces of sections enclose arms, each beginning with a pattern string;
that outer enclosure is not an ordinary block.
After else, either an ordinary block or a token spelled if MUST follow.
In the latter case, declaration-first dispatch still applies. Accordingly,
else if:int and else if[1]:int are permitted declarations, as well as
ordinary else-if chains.
id: reader-else-declarationoperation: read--- spec no-final-newlineif 0 {} else if:int--- input no-final-newline7--- expected data{"iris": "0.1", "entries": [ {"name": "if", "type": "int", "depth": 0, "value": 7}]}id: reader-missing-braceoperation: parse--- spec no-final-newlinerepeat 2 {x:int--- expected error{"code": "E-SPEC-SYNTAX", "message": "missing '}'", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}5.7 Types, ranges, and options
The grammar MUST permit the base types int, float, num, word, and
rest; alphabet followed by a string and options; visible named types;
and ranges. At a type position, a base-type name MUST take priority, then
alphabet, then a visible named type, then a range expression. Parentheses
can disambiguate a range bound that has the name of a type.
Type visibility and type compatibility follow
§6.1 and
§6.5, rather
than unrestricted alternatives in this dispatch.
An inclusive range MAY omit either bound, but MUST contain at least one.
An upper-exclusive range ..< MAY omit its lower bound and MUST contain
its upper bound. Missing required bounds report E-SPEC-SYNTAX.
After the range operator, an upper bound MUST begin only when the next token satisfies this test:
- An integer, float, or string token begins an upper bound.
- Punctuation begins one only for
(,-, or!. - An identifier begins one unless declaration lookahead succeeds or it is in the stop set below.
- End of source does not begin one.
The exact identifier stop set is:
comment stop expect tokens separators ignore param list line find skipindex repeat each instances sections if let check type layout offset untilParentheses permit keyword-named upper bounds, as in 0..(check).
format MUST NOT stop a range: 0..format uses it as the bound. A following
format declaration may therefore be consumed as part of range parsing.
id: reader-open-rangesoperation: read--- spec no-final-newlinelet check=7 a:0.. b:..3 c[1][1]:0.. layout "FULL_MATRIX" offset -1 list d:0.. until 0 e:0..(check) f:0.. check f>0--- input no-final-newline1 2 3 4 0 5 6--- expected data{"iris": "0.1", "entries": [ {"name": "check", "type": "int", "depth": 0, "value": 7}, {"name": "a", "type": "int", "depth": 0, "value": 1}, {"name": "b", "type": "int", "depth": 0, "value": 2}, {"name": "c", "type": "int", "depth": 2, "value": [[2]]}, {"name": "d", "type": "int", "depth": 1, "value": [4]}, {"name": "e", "type": "int", "depth": 0, "value": 5}, {"name": "f", "type": "int", "depth": 0, "value": 6}]}id: reader-range-missing-boundoperation: parse--- spec no-final-newlinex:0..<--- expected error{"code": "E-SPEC-SYNTAX", "message": "'..<' needs an upper bound", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}A declaration MAY have layout followed by an expression, then offset
followed by an expression, each at most once and in that order. A list MAY
have offset after its terminator. An alphabet MAY have any number of
blank string, strip string, and base integer options, in any order,
including repetitions. An alphabet base permits an optional minus followed
by one integer literal token, rather than an arbitrary expression.
Repeated alphabet options MUST replace the preceding value of that option.
Before consuming layout, offset, blank, strip, or base as an
option, the parser MUST check that it is not a declaration start. A
same-named declaration ends the preceding option list.
id: reader-option-namesoperation: read--- spec no-final-newlineg[1][1]:alphabet "ab" base:int x:int offset:int--- input no-final-newlinea 7 8 9--- expected data{"iris": "0.1", "entries": [ {"name": "g", "type": "int", "depth": 2, "value": [[1]]}, {"name": "base", "type": "int", "depth": 0, "value": 7}, {"name": "x", "type": "int", "depth": 0, "value": 8}, {"name": "offset", "type": "int", "depth": 0, "value": 9}]}Sections options MAY repeat and interleave: until followed by one or
more strings and optional store name, and skip other. Terminator strings
MUST accumulate, a later store name MUST replace the previous store name,
and skip other remains enabled once present. Arm modifiers MUST occur
as optional optional, then optional last, then an optional body.
§7.8 defines their matching and execution
effects.
Chapter 6 defines range evaluation, layouts,
offsets, alphabets, and lists.
5.8 Settings
comment and stop MUST be followed by one or more strings. tokens and
separators MUST each be followed by exactly one string. ignore MUST be
followed by trailing. These settings MAY repeat and MAY appear among
top-level statements before instances; they need not form a header.
They MUST NOT appear inside blocks, even on an unreachable execution path.
The error is E-SPEC-PLACEMENT.
Declaration lookahead still allows a declaration named comment, for
example, inside a block.
Settings MUST activate in statement execution order. Comment and stop
prefix lists, token bytes, and separator bytes MUST accumulate across
repeated settings. ignore trailing remains enabled once executed.
Their input effects are defined in
§4.3,
§4.7, and
§4.8.
id: reader-settings-in-orderoperation: read--- spec no-final-newlinea:word comment "#" b:word comment "A" comment "B" stop "END" tokens "!" tokens "?" separators "," separators ";" c:int d:int expect "!" "?" ignore trailing--- input no-final-newlinebefore# skipafterA skipB skip1,2;!? extra--- expected data{"iris": "0.1", "entries": [ {"name": "a", "type": "string", "depth": 0, "value": "before"}, {"name": "b", "type": "string", "depth": 0, "value": "after"}, {"name": "c", "type": "int", "depth": 0, "value": 1}, {"name": "d", "type": "int", "depth": 0, "value": 2}]}id: reader-setting-in-blockoperation: parse--- spec no-final-newlineif 0 {comment "#"}--- expected error{"code": "E-SPEC-PLACEMENT", "message": "the setting 'comment' must be at the top level of the spec", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}5.9 Format metadata
At the top level, format MUST be handled before statement declaration
lookahead. It MUST be followed by an identifier or string, whose text is
the format name. Subsequent - or . tokens MUST be joined to that name
only when both the joiner and its following identifier or integer token
are glued to their predecessors, with no whitespace or comment between.
All such joins MUST be consumed. A float token is not a join component;
format iris-1.0 fails, while format "iris-1.0" succeeds.
An empty quoted name is permitted. Each format declaration MUST replace
the preceding name; the final name is metadata, not a data entry or an
extra member of canonical JSON.
Format declarations MAY appear after instances, including repeatedly,
because they are not executable statements.
Top-level format:int MUST fail with E-SPEC-SYNTAX: the colon is not a
format name. Inside a block, format:int is an ordinary declaration, while
format "name" fails as an unknown statement with E-SPEC-SYNTAX.
The final format name in this example is last name; the data contains
only x.
id: reader-format-metadataoperation: read--- spec no-final-newlineformat dimacs-cnf.v2 instances {x:int} format "last name"--- input no-final-newline7--- expected data{"iris": "0.1", "entries": [ {"name": "x", "type": "int", "depth": 0, "value": 7}]}id: reader-format-keywordoperation: parse--- spec no-final-newlineformat:int--- expected error{"code": "E-SPEC-SYNTAX", "message": "expected a format name, found ':'", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}5.10 Expression syntax and precedence
Expressions MUST permit integer, float, and string literals; names and host constants; parenthesized expressions; ordinary function calls; comprehensions; and repeated postfix indexing or field selection.
An ordinary call has an identifier, (, zero or more comma-separated
expressions, and ). A host-constant token cannot be called. For callees
all, any, sum, or count, an identifier followed by the identifier
in immediately after ( MUST instead select comprehension syntax:
a binding name, in, an expression, :, another expression, and ).
This is token lookahead; intervening whitespace and comments are permitted.
Function names, arities, and bindings are defined in
§8.8 and
§8.10;
chapter 8 defines evaluation.
Implementations MUST use this precedence, from loosest to tightest:
| Level | Operators/forms | Association |
|---|---|---|
| 1 | || |
Left |
| 2 | && |
Left |
| 3 | ==, != |
Left |
| 4 | <, >, <=, >= |
Left |
| 5 | +, - |
Left |
| 6 | *, /, % |
Left |
| 7 | Unary -, ! |
Prefix |
| 8 | ^ |
Right; right operand is a unary expression |
| 9 | [expression], .name |
Left, repeated suffixes |
| 10 | Literals, names, calls, comprehensions, parenthesized expressions | Primary |
Thus -2^2 groups as -(2^2), 2^3^2 as 2^(3^2), and 2^-1
as 2^(-1). Parsing the last form succeeds;
§8.4 defines its
runtime exponent error. Chained comparisons group left, rather than
introducing a special comparison-chain form.
id: reader-precedenceoperation: read--- spec no-final-newlinelet a=2*3^2 let b=2^3^2 let c=-2^2 let d=8/2/2 let e=1<2<3 let f=1||0&&0--- input no-final-newline--- expected data{"iris": "0.1", "entries": [ {"name": "a", "type": "int", "depth": 0, "value": 18}, {"name": "b", "type": "int", "depth": 0, "value": 512}, {"name": "c", "type": "int", "depth": 0, "value": -4}, {"name": "d", "type": "int", "depth": 0, "value": 2}, {"name": "e", "type": "int", "depth": 0, "value": 1}, {"name": "f", "type": "int", "depth": 0, "value": 1}]}5.11 Placement restrictions
These restrictions MUST be checked during parsing, including in bodies that execution would not reach. They apply to actual statements/settings, not declarations with the same contextual keyword as their name.
| Form | Permitted position; failure |
|---|---|
comment, stop, tokens, separators, ignore trailing |
Top level before instances; nested use gives E-SPEC-PLACEMENT. |
format metadata |
Top level anywhere, including after instances; nested metadata syntax gives E-SPEC-SYNTAX. |
instances |
Top level, at most once, with no subsequent executable statement; otherwise E-SPEC-PLACEMENT. Subsequent format metadata is permitted. |
each |
First direct statement in a repeat body, at most once; otherwise E-SPEC-PLACEMENT. A first declaration named each uses up the first statement position. |
Declarations, param, expect, other ordinary statements |
Top level before instances, or in ordinary blocks, subject to their own syntax and semantic checks. |
index |
Syntactically permitted wherever an ordinary statement is permitted; execution outside a repeat gives E-INDEX-CONTEXT, not a parse-time placement error. |
The ordinary-block restriction also applies to a sections arm's body;
the outer sections braces admit only arms. Whitespace and comments do
not count as statements for each placement.
5.12 Parser limits
Implementations MUST enforce two independent counters, initially zero.
Attempting to increase either to 257 MUST report
E-SPEC-NESTING at the current token's
reader-spec line, with null column. These are operational parser limits,
not a general maximum syntax-tree depth.
The block counter MUST increase after an ordinary block's opening brace
is consumed and remain held through its closing brace. An else followed
by if MUST hold an additional entry while its declaration-first statement
is parsed, including when it is a declaration. The outer braces of
sections MUST NOT increase this counter; each arm body does.
The expression counter MUST account as follows:
- Each invocation parsing unary syntax holds one entry until it returns, including an invocation with no unary operator.
- Binary parsing first parses its left unary expression. For each binary operator in levels 1–6, it holds an additional entry before consuming that operator and parses the right operand at the next tighter binary precedence. It retains all its operator entries until that binary invocation returns. They accumulate along a left-associative chain.
- Postfix parsing first parses a primary. For each suffix, it consumes
[or., then holds an additional entry until that postfix invocation returns. Index expressions are parsed while these entries remain held. - Parenthesized expressions, call arguments, and both comprehension expressions are parsed while the surrounding unary entry remains held. Power parses its right operand through another unary invocation.
Returning from these operations releases exactly their held entries. Separate statements, array dimensions, and call arguments do not accumulate entries from their completed predecessors. Re-lexing a capture type does not reset counters.
At otherwise empty nesting, these are the exact boundaries. The field-chain accepted column means it reaches name resolution, which can still fail.
| Construction | Permitted count | First excessive count |
|---|---|---|
| Nested ordinary blocks | 256 | 257 |
Parenthesis pairs around 1 |
255 | 256 |
Unary minus signs before 1 |
255 | 256 |
Additions +1 after initial 1 |
255 | 256 |
Powers ^1 after initial 1 |
255 | 256 |
Index suffixes [0] after a name |
254 | 255 |
Field suffixes .a after a name |
255 | 256 |
| Additional else-if arms after an initial if | 255 | 256 |
These limits MUST NOT be substituted for runtime array/count bounds or the work budgets in chapter 10. There is no separate language limit on source bytes, tokens, statements, string length, or the number of separate array dimensions.
The following are complete literal sources at four first-failing boundaries. Their single long lines are intentional.
id: reader-block-limitoperation: parse--- spec no-final-newlinerepeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {repeat 0 {}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}--- expected error{"code": "E-SPEC-NESTING", "message": "blocks are nested too deeply", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}id: reader-expression-limitoperation: parse--- spec no-final-newlinelet x=1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1--- expected error{"code": "E-SPEC-NESTING", "message": "expressions are nested too deeply", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}id: reader-else-if-limitoperation: parse--- spec no-final-newlineif 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {} else if 0 {}--- expected error{"code": "E-SPEC-NESTING", "message": "blocks are nested too deeply", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}id: reader-index-limitoperation: parse--- spec no-final-newlinea[1]:int let x=a[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]--- expected error{"code": "E-SPEC-NESTING", "message": "expressions are nested too deeply", "input_location": null, "spec_location": {"origin": "spec.iris", "line": 1, "column": null}, "context": null, "record_path": null}