Skip to content

[script] Allow statements on one line without ';' after a closing delimiter - #1

Closed
Andrew Gazelka (andrewgazelka) wants to merge 1 commit into
masterfrom
script-same-line-statements
Closed

Andrew Gazelka (andrewgazelka) wants to merge 1 commit into
masterfrom
script-same-line-statements

Conversation

@andrewgazelka

Copy link
Copy Markdown
Member

Motivation

This line fails with missing ; or newline:

Prefab mullion { (MadeOf, aluminium_6063)  Profile: {width_mm: 65, depth_mm: 200, wall_mm: 3} }

Nothing about it is ambiguous: the pair ends at ) and the next token can only start a new statement.

Rule

In flecs_script_stmt_w_separator, after a statement that is not followed by ;, a newline, } or the end of the script, the parser now accepts the next statement on the same line when both of these hold:

  1. The previous statement's last token ends with ), } or ].
  2. The next token is one of:
    • an identifier or a string;
    • a statement keyword: with module using template prop mut const export if for include fn await try continue async while;
    • (, but only when the previous statement ended with } or ].

Everything else still errors with missing ; or newline.

Restrictions that keep it unambiguous

  • Only after a closing delimiter. After Foo or Mass: 10, an identifier could be part of the Kind name declaration or of an expression, so Foo Bar still declares entity Bar of kind Foo, and Foo Bar Baz, Mass: 10 Foo and const x = 10 Foo are still errors.
  • No ( after ). (A, B) (C, D) and X(...) (...) read as an initializer, the same as with (A, B) (expr), so this stays an error.
  • No { as the next statement. Position: {10, 20} {} reads like a second initializer or a scope, so it stays an error. Anonymous entities still need a separator.
  • No @ annotations as the next statement. An annotation consumes the rest of its line, so it must start a line.
  • A token that a statement consumes itself is never seen by this check. Examples are else and catch after }, and a { after (A, B) (a pair scope) or after Foo bar (an entity scope). Previously valid scripts therefore parse exactly as before; only inputs that used to be errors change.

Changes

  • src/addons/script/parser.c: adds flecs_script_stmt_can_juxtapose, and flecs_script_stmt_w_separator calls it. The last token is found with the existing flecs_parser_stmt_end.
  • distr/flecs.c: the same edit, applied verbatim.
  • docs/FlecsScript.md: the Newlines section documents the rule.

Tests (test/script)

Four upstream Error tests asserted the old behaviour and are now valid input, so they were removed and replaced by Eval tests: missing_separator_between_components, missing_separator_between_component_and_tag, missing_separator_between_component_and_pair and missing_separator_after_scope.

New Eval tests (positive):

  • 2_components_same_line_wo_semicolon: e { Position: {10, 20} Velocity: {1, 2} }
  • component_and_tag_same_line_wo_semicolon: e { Position: {10, 20} Foo }
  • component_and_pair_same_line_wo_semicolon: e { Position: {10, 20} (Likes, Apples) }
  • pair_and_component_same_line_wo_semicolon (the motivating case): Prefab e { (Likes, Apples) Position: {x: 10, y: 20} }
  • pair_and_child_same_line_wo_semicolon: e { (Likes, Apples) child { Foo } }
  • 3_entities_same_line_wo_semicolon: a {} b { Foo } c {}
  • kind_entity_after_scope_same_line_wo_semicolon: a { Foo } Prefab e { Position: {10, 20} }
  • pair_after_scope_same_line_wo_semicolon: e { child {} (Likes, Apples) }
  • const_after_pair_same_line_wo_semicolon: e { (Likes, Apples) const x = 10; Position: {$x, 20} }

New Error tests (must still fail with missing ; or newline):

  • missing_separator_between_scalar_component_and_tag: e { Position: {10, 20}; Mass: 10 Foo }
  • missing_separator_between_const_and_tag: e { const x = 10 Foo }
  • missing_separator_between_tags_after_kind: e { Foo Bar Baz }
  • missing_separator_between_pairs: e { (Likes, Apples) (Likes, Pears) }
  • missing_separator_between_component_and_anonymous_entity: e { Position: {10, 20} {} }
  • missing_separator_between_scope_and_annotation: e { Foo {} @brief hello }

missing_separator_between_const (const x = 10 const y = 20) is unchanged and still passes.

Results: the full script suite passes (8826 passed, 0 failed, IR disabled and enabled), built with CMake against the bake test driver. distr/flecs.c compiles with -Wall -Wextra -Werror.

…imiter

A statement that ends with ')', '}' or ']' may be followed on the same line
by a statement that starts with an identifier, string or statement keyword,
or by '(' when the previous statement ends with '}' or ']'.
@andrewgazelka

Copy link
Copy Markdown
Member Author

Superseded by the upstream PR SanderMertens#2379 (SanderMertens#2379).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant