<p>My language is expression based; many of its language constructs are not statements, but rather expressions that return a value. However, since everything is an expression, my grammar looks like</p>
<pre><code>code  := stmt*
stmt  := expr ';'
expr  := var | loop | if | ... | literal | ident | block
block := '{' code '}'
if    := 'if' expr block ('else' (block | if))?
</code></pre>
<p>which leads to code with standalone constructs like <code>if</code> in their own statements, or at the end of statements:</p>
<pre><code>let x = if condition { 1 } else { -1 };
if foo {};
if bar {} else {};
if woo {} else if daar {};
if baz {} else if quuz {} else {};
</code></pre>
<p>which have a nasty <code>};</code> at the end.</p>
<p>How can I modify my grammar so that I can eliminate <code>};</code> and use <code>}</code> as a statement ender?</p>

<syntax><parsing><expressions>
Allowing `}` as a statement terminator in an expression-based language?
CC BY-SA 4.0
2024-12-27T15:03:05.177Z
I suggest not doing that, and just leave `};` be. Rust allows omitting semicolons after `}`, and although semicolon insertion in Rust isn’t nearly as nasty as in JavaScript, it still creates traps that would not otherwise exist: <https://twitter.com/i/status/1440771870177980421>
user3840170
CC BY-SA 4.0
2023-05-17T13:47:28.963Z
You might want to look at OCaml's grammar: it looks like `let x = if cond then foo else bar in print "foo"; 2` (`;` is an operator that discards the value on the left)
user
CC BY-SA 4.0
2023-05-17T14:04:32.003Z
FWIW, I don’t think `};` is that bad. I’m also saying that with the background that C++ requires that for every struct and class definition.
Bbrk24
CC BY-SA 4.0
2023-05-17T15:57:41.940Z
There was a [similar question](https://languagedesign.stackexchange.com/q/332/110) on how to infer statement endings. Basically, you have to look ahead for the `}`.
chrisaycock
CC BY-SA 4.0
2023-05-17T17:35:06.360Z
You might want to see how Rust uses semicolons: https://doc.rust-lang.org/book/ch03-03-how-functions-work.html#statements-and-expressions, https://stackoverflow.com/questions/26665471/are-semicolons-optional-in-rust, https://lucumr.pocoo.org/2012/10/18/such-a-little-thing/, https://users.rust-lang.org/t/why-semicolons/25074/10, https://news.ycombinator.com/item?id=20612277
Solomon Ucko
<p>My own language does this, and it disambiguates between <code>if</code> statements and <code>if</code> expressions:</p>
<pre><code>code    := stmt*
stmt    := expr ';' | if_stmt | block
expr    := var | loop | if_expr | ... | literal | ident | block
block   := '{' code '}'
if_stmt := 'if' expr block ('else' (block | if))?
if_expr := if_stmt
</code></pre>
<p>Yes, that grammar seems redundant, but it adds an extra state that can then be used to differentiate the cases.</p>
<p>Basically, the parser knows when it parsing an <code>if</code> that is a standalone statement versus an expression and expects the semicolon only in the latter case.</p>

CC BY-SA 4.0
2023-05-17T19:50:51.797Z
2023-05-17T19:50:51.797Z
Gavin D. Howard
<p>This is one the things easier to resolve manually than implementing a grammar.</p>
<p>Something like this ought to work:</p>
<pre><code>stmt          := expr_no_block ';' | expr_block
expr_no_block := var_no_block | literal | ident
expr_block    := if | block | loop | var_block
expr_any      := expr_no_block | expr_block
block         := '{' (stmt* expr_any)? '}'
if            := 'if' expr_any block ('else' (block | if))?
</code></pre>
<p>This also allows you to elide the final <code>;</code> in a block. If you don't want that then <code>block := '{' stmt* '}'</code> is sufficient.</p>

CC BY-SA 4.0
2023-05-17T13:58:31.677Z
2023-05-17T13:58:31.677Z
Nuoji
CC BY-SA 4.0
2023-05-18T09:15:47.827Z
@LHP, yes that would be a consequence of that grammar. I understood it to be desired, but I may be wrong. My experience is that many "innovations" in terms of things like reducing separators and terminators end up having bad corner cases in the end, that end up harder to *read* than they were to parse(!)
Nuoji
CC BY-SA 4.0
2023-05-18T10:18:29.363Z
I agree! "Growing up" with Pascal, I guess I've been brainwashed to actually _like_ the semicolon; possibly to a degree where I also frequently use it for punctuation in normal text. :-)
LHP
CC BY-SA 4.0
2023-05-17T17:24:52.083Z
Wouldn't that - assuming grammar rules for a typical expression syntax with arithmetic operators were omitted above for brevity - result in the rather odd situation that:
{ x := if cond { 42 } else { 666 }
foo();
}
does not require a semicolon before foo, whereas:
{ x := 2*if cond {42 } else { 666 };
foo();
}
does require it?

I believe this is a difficult problem to fix; and it might be easier to generalise it, making it "bigger" actually, and not have ';' as a terminator, but as a separator, only required when needed to separate two exprs that would otherwise be parsed as one.
LHP
<p>As I understand the question, the intent is that whenever an expression statement ends in a '}', the terminating ';' can be omitted, even with statements like</p>
<pre><code>{ let x = 2*if cond { foobar(); 42; } else { 666; }
  foo();
}
</code></pre>
<p>As can be seen, using ';' as a terminator in an expression language &quot;clashes&quot;; it might be worth considering whether the value yielded by a block should be followed by ';' as in my example. (I noticed that it was omitted from the examples in the question, which would be a syntax error with the provided grammar.)</p>
<p>Perhaps it is better to use ';' as a separator, and let it be optional, except in cases where two adjacent expressions would be parsed as one expression. (Using line breaks as separation hints might also be a good idea.) This way:</p>
<pre><code>{ let x = 2*if cond {42} else {666}
  foo()
}
</code></pre>
<p>would not need any (assuming that a function call cannot follow at that point), but</p>
<pre><code>{ let x = 2*if cond {42} else {666}
  *p = foo()
}
</code></pre>
<p>would be parsed as a multiplication by p unless the prefix '*' was separated from the preceding expression by ';'.</p>
<p>Designing this in a formal grammar would be easier than making a grammar that distinguishes expressions that end in '}' from ones that don't. However, in a hand-written recursive descent parser it would not be too hard to hack the expression parser function to provide information on whether its last symbol was a '}'. Just add a bool curlycue flag to the CST nodes for expressions, and then inspect it in the stmt parse function:</p>
<pre><code>CST stmt() {
    ExprCST ex = expr();
    if(!ex-&gt;curlycue) expect(';');
    return new StmtCST(ex);
}
</code></pre>
<p>All parse functions for subexpressions just need to check for curlycue and propagate it up in the parse tree, for example:</p>
<pre><code>ExprCST mult_expr() {
    ExprCST left_operand = cast_expr();
    while(sym() == '*' || sym() == '/' || sym() == '%') {
        int op = sym(); nextsym();
        ExprCST right_operand = cast_expr();
        left_operand = new BinaryExprCST(op, left_operand, right_operand);
        left_operand-&gt;curlycue = right_operand-&gt;curlycue;
    }
    return left_operand;
}
</code></pre>
<p>Alternatively, a special expect_semi parser function could be used
(assuming sym() gives the current token as an int, nextsym() advances to the next token, you'll also need a prevsym() that un-gets the current token):</p>
<pre><code>void expect_semi() {
    prevsym(); // un-gets the last token of a preceding expression.
    if(sym() == '}') { nextsym(); } // skip it, but do nothing further
    else { nextsym(); //skip whatever else it may have been
        if(sym() == ';') { nextsym(); } // but require a semicolon now.
        else { syntax_error(&quot;semicolon expected&quot;); }
    }
}
</code></pre>
<p>Note however, that this will still not solve the issue with separating two expressions that could be parsed as one, when the second begins with an unary operator that is also an infix operator. I'd not recommend doing this. The only reason to have it seems to be a desire to mimic the absence of ';' after compound-statements in C, which I actually always have thought was a bit strange. In Algol (and descendants like Pascal), ';' is a separator and is not omitted after the <strong>end</strong> keyword of blocks and compound-statements.</p>

CC BY-SA 4.0
2023-05-17T19:18:16.000Z
2023-05-17T19:18:16.000Z
LHP
<p>You could do something like this:</p>
<pre><code>stmt := expr ';' | block | if
</code></pre>
<p>This way, a block counts as a statement on it's own and doesn't need the <code>;</code> like a expression would have.</p>

CC BY-SA 4.0
2023-05-17T13:46:00.990Z
2023-05-17T15:34:24.187Z
2023-05-17T15:34:24.187Z
mousetail 'he-him'
CC BY-SA 4.0
2023-05-17T13:47:35.067Z
This doesn't seem to remove the need to have `};` - it only potentially removes the `;` inside the block
lyxal
CC BY-SA 4.0
2023-05-17T13:49:32.817Z
@lyxal I completely misread the question, it should be fixed now
mousetail 'he-him'
CC BY-SA 4.0
2023-05-17T16:10:15.163Z
What if OP wants to use syntax like: `{ 1; } + { 1; };`? A statement separator is still necessary, no?
Lucrecious
CC BY-SA 4.0
2023-05-17T16:15:38.213Z
In that case the `;` at the end would still be necessary yes, this matches behavior in other languages that require semicolons though. In those cases `;` can only be ommited if the block is a statement and not if it is some sub part of a statement
mousetail 'he-him'
<p>I have the same issue in my language, and I've decided to take the Go solution and just add implicit semicolons during lexing.</p>
<p>The issue with implicit semicolons is that it forces a certain programming style at the compilation level. I'm working on a very opionated language, so this is fine for me.</p>
<p>Edit: one style quirk is that in Go</p>
<pre><code>if (x)
{
}
</code></pre>
<p>This style isn't allowed since a semicolon is inserted after the <code>)</code> after the condition. Thus, you must keep the opening brace on the same same.</p>
<pre><code>if (x) {
}
</code></pre>

CC BY-SA 4.0
2023-05-17T16:06:35.470Z
2023-05-17T16:19:52.527Z
2023-05-17T16:19:52.527Z
Lucrecious
# Allowing `}` as a statement terminator in an expression-based language?
Posted by: username_0 on 2023-05-17
My language is expression based; many of its language constructs are not statements, but rather expressions that return a value. However, since everything is an expression, my grammar looks like
code  := stmt*
stmt  := expr ';'
expr  := var | loop | if | ... | literal | ident | block
block := '{' code '}'
if    := 'if' expr block ('else' (block | if))?

which leads to code with standalone constructs like if in their own statements, or at the end of statements:
let x = if condition { 1 } else { -1 };
if foo {};
if bar {} else {};
if woo {} else if daar {};
if baz {} else if quuz {} else {};

which have a nasty }; at the end.
How can I modify my grammar so that I can eliminate }; and use } as a statement ender?
**Tags:** syntax parsing expressions
> **Comments:**
> **username_2**: You might want to look at OCaml's grammar: it looks like `let x = if cond then foo else bar in print "foo"; 2` (`;` is an operator that discards the value on the left)  
> **username_3**: FWIW, I don’t think `};` is that bad. I’m also saying that with the background that C++ requires that for every struct and class definition.  
> **username_4**: There was a [similar question](https://languagedesign.stackexchange.com/q/332/110) on how to infer statement endings. Basically, you have to look ahead for the `}`.  
> **username_5**: You might want to see how Rust uses semicolons: https://doc.rust-lang.org/book/ch03-03-how-functions-work.html#statements-and-expressions, https://stackoverflow.com/questions/26665471/are-semicolons-optional-in-rust, https://lucumr.pocoo.org/2012/10/18/such-a-little-thing/, https://users.rust-lang.org/t/why-semicolons/25074/10, https://news.ycombinator.com/item?id=20612277  
> **username_1**: I suggest not doing that, and just leave `};` be. Rust allows omitting semicolons after `}`, and although semicolon insertion in Rust isn’t nearly as nasty as in JavaScript, it still creates traps that would not otherwise exist: <https://twitter.com/i/status/1440771870177980421>  
---
## 5 answers
### Answer by username_8 on 2023-05-17. Score: 5 | Accepted answer
As I understand the question, the intent is that whenever an expression statement ends in a '}', the terminating ';' can be omitted, even with statements like
{ let x = 2*if cond { foobar(); 42; } else { 666; }
  foo();
}

As can be seen, using ';' as a terminator in an expression language "clashes"; it might be worth considering whether the value yielded by a block should be followed by ';' as in my example. (I noticed that it was omitted from the examples in the question, which would be a syntax error with the provided grammar.)
Perhaps it is better to use ';' as a separator, and let it be optional, except in cases where two adjacent expressions would be parsed as one expression. (Using line breaks as separation hints might also be a good idea.) This way:
{ let x = 2*if cond {42} else {666}
  foo()
}

would not need any (assuming that a function call cannot follow at that point), but
{ let x = 2*if cond {42} else {666}
  *p = foo()
}

would be parsed as a multiplication by p unless the prefix '*' was separated from the preceding expression by ';'.
Designing this in a formal grammar would be easier than making a grammar that distinguishes expressions that end in '}' from ones that don't. However, in a hand-written recursive descent parser it would not be too hard to hack the expression parser function to provide information on whether its last symbol was a '}'. Just add a bool curlycue flag to the CST nodes for expressions, and then inspect it in the stmt parse function:
CST stmt() {
    ExprCST ex = expr();
    if(!ex->curlycue) expect(';');
    return new StmtCST(ex);
}

All parse functions for subexpressions just need to check for curlycue and propagate it up in the parse tree, for example:
ExprCST mult_expr() {
    ExprCST left_operand = cast_expr();
    while(sym() == '*' || sym() == '/' || sym() == '%') {
        int op = sym(); nextsym();
        ExprCST right_operand = cast_expr();
        left_operand = new BinaryExprCST(op, left_operand, right_operand);
        left_operand->curlycue = right_operand->curlycue;
    }
    return left_operand;
}

Alternatively, a special expect_semi parser function could be used
(assuming sym() gives the current token as an int, nextsym() advances to the next token, you'll also need a prevsym() that un-gets the current token):
void expect_semi() {
    prevsym(); // un-gets the last token of a preceding expression.
    if(sym() == '}') { nextsym(); } // skip it, but do nothing further
    else { nextsym(); //skip whatever else it may have been
        if(sym() == ';') { nextsym(); } // but require a semicolon now.
        else { syntax_error("semicolon expected"); }
    }
}

Note however, that this will still not solve the issue with separating two expressions that could be parsed as one, when the second begins with an unary operator that is also an infix operator. I'd not recommend doing this. The only reason to have it seems to be a desire to mimic the absence of ';' after compound-statements in C, which I actually always have thought was a bit strange. In Algol (and descendants like Pascal), ';' is a separator and is not omitted after the end keyword of blocks and compound-statements.
---
### Answer by username_9 on 2023-05-17. Score: 6
You could do something like this:
stmt := expr ';' | block | if

This way, a block counts as a statement on it's own and doesn't need the ; like a expression would have.
> **Comments:**
> **username_10** (2023-05-17): This doesn't seem to remove the need to have `};` - it only potentially removes the `;` inside the block  
> **username_9** (2023-05-17): @lyxal I completely misread the question, it should be fixed now  
> **username_11** (2023-05-17): What if OP wants to use syntax like: `{ 1; } + { 1; };`? A statement separator is still necessary, no?  
> **username_9** (2023-05-17): In that case the `;` at the end would still be necessary yes, this matches behavior in other languages that require semicolons though. In those cases `;` can only be ommited if the block is a statement and not if it is some sub part of a statement  
---
### Answer by username_11 on 2023-05-17. Score: 4
I have the same issue in my language, and I've decided to take the Go solution and just add implicit semicolons during lexing.
The issue with implicit semicolons is that it forces a certain programming style at the compilation level. I'm working on a very opionated language, so this is fine for me.
Edit: one style quirk is that in Go
if (x)
{
}

This style isn't allowed since a semicolon is inserted after the ) after the condition. Thus, you must keep the opening brace on the same same.
if (x) {
}
---
### Answer by username_6 on 2023-05-17. Score: 3
My own language does this, and it disambiguates between if statements and if expressions:
code    := stmt*
stmt    := expr ';' | if_stmt | block
expr    := var | loop | if_expr | ... | literal | ident | block
block   := '{' code '}'
if_stmt := 'if' expr block ('else' (block | if))?
if_expr := if_stmt

Yes, that grammar seems redundant, but it adds an extra state that can then be used to differentiate the cases.
Basically, the parser knows when it parsing an if that is a standalone statement versus an expression and expects the semicolon only in the latter case.
---
### Answer by username_7 on 2023-05-17. Score: 2
This is one the things easier to resolve manually than implementing a grammar.
Something like this ought to work:
stmt          := expr_no_block ';' | expr_block
expr_no_block := var_no_block | literal | ident
expr_block    := if | block | loop | var_block
expr_any      := expr_no_block | expr_block
block         := '{' (stmt* expr_any)? '}'
if            := 'if' expr_any block ('else' (block | if))?

This also allows you to elide the final ; in a block. If you don't want that then block := '{' stmt* '}' is sufficient.
> **Comments:**
> **username_8** (2023-05-17): Wouldn't that - assuming grammar rules for a typical expression syntax with arithmetic operators were omitted above for brevity - result in the rather odd situation that:
{ x := if cond { 42 } else { 666 }
foo();
}
does not require a semicolon before foo, whereas:
{ x := 2*if cond {42 } else { 666 };
foo();
}
does require it?

I believe this is a difficult problem to fix; and it might be easier to generalise it, making it "bigger" actually, and not have ';' as a terminator, but as a separator, only required when needed to separate two exprs that would otherwise be parsed as one.  
> **username_7** (2023-05-18): @LHP, yes that would be a consequence of that grammar. I understood it to be desired, but I may be wrong. My experience is that many "innovations" in terms of things like reducing separators and terminators end up having bad corner cases in the end, that end up harder to *read* than they were to parse(!)  
> **username_8** (2023-05-18): I agree! "Growing up" with Pascal, I guess I've been brainwashed to actually _like_ the semicolon; possibly to a degree where I also frequently use it for punctuation in normal text. :-)  
---
