<p>I've found that many grammars have a production called <code>PrimaryExpression</code> or something along those lines. <a href="https://tc39.es/ecma262/#prod-PrimaryExpression" rel="noreferrer">ECMAScript has <code>PrimaryExpression</code></a>, <a href="https://docs.python.org/3/reference/grammar.html" rel="noreferrer">Python has <code>primary</code></a>, <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/grammar" rel="noreferrer">C# has <code>primary_expression</code></a>, <a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html" rel="noreferrer">Java has <code>Primary</code></a>, and many more I've seen over the years.</p>
<p>It cannot be a coincidence that all these specifications have it. What is considered a &quot;primary expression&quot;?</p>
<p>Maybe Haskell has one too, but <a href="https://www.haskell.org/onlinereport/syntax-iso.html" rel="noreferrer">I can't decipher which one it is</a>. If there's a primary expression, what's it called in their specification? If there's no primary expression, what's different about Haskell's syntax (or the way grammar is defined) that makes it stand out?</p>

<expressions><grammar>
What is a "primary expression"?
CC BY-SA 4.0
2023-11-29T22:43:57.143Z
I would argue that it is indeed a coincidence - "primary" is just a good name for the "top" of whatever expression hierarchy you have.
blueberry
CC BY-SA 4.0
2023-11-29T23:21:37.410Z
In Haskell it seems to be "aexp".
kaya3
<p>It's merely a convention, which goes back to at least Schorre's definition of Meta-2 in 1964. I don't know to what extent there were equivalent (published) syntax specifications before that, particularly in the form of text-based rules or equations.</p>
<p>See <a href="https://dl.acm.org/doi/10.1145/800257.808896" rel="nofollow noreferrer">https://dl.acm.org/doi/10.1145/800257.808896</a> where in the specification for either the VALGOL-I or VALGOL-II demonstration language a primary is defined as the product of terms and so on.</p>
<p>This has obviously been quite a lot of tidying up and codification in the intervening 60 years.</p>
<p>Updated: here is a direct link to a reprint <a href="https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=56614.0;attach=45608" rel="nofollow noreferrer">https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=56614.0;attach=45608</a></p>

CC BY-SA 4.0
2023-11-30T08:16:13.223Z
2023-11-30T09:33:45.440Z
2023-11-30T09:33:45.440Z
Mark Morgan Lloyd
<p>All of the instances you link are atomic (or at least cohesive) value head expressions, without including any operator expressions: <code>x</code> and <code>3.5</code> and <code>(x + 3.5)</code> are primary expressions, but <code>x + 3.5</code> is not, while still being an <em>expression</em>. This structure can make unambiguous parsing easier. The name itself is not significant, but Primary is a common term for it.</p>
<p>Other parts of the grammar can say they accept any &quot;expression&quot; (for example, the right-hand side of an assignment or an argument list), but the parts that deal with constructing expressions themselves want to talk about the indivisible units of expressions in places.</p>

CC BY-SA 4.0
2023-11-29T22:55:22.330Z
2023-11-29T23:12:59.633Z
2023-11-29T23:12:59.633Z
Michael Homer
CC BY-SA 4.0
2023-11-29T23:07:13.263Z
This isn't quite accurate: in Java `x.y.z` is a primary expression, but I wouldn't call it atomic.
kaya3
CC BY-SA 4.0
2023-11-29T23:11:55.387Z
Yeah, I’m not sure quite what the right phrasing is. It’s treated as a unit by the rest of the grammar and most are genuinely atomic, but a few are still slightly divisible. Some of the others don’t include that sort of thing in with the rest.
Michael Homer
<p>I don't think there is a universal definition, but I'll attempt one anyway: the primary expressions in a language are those which have the highest level of precedence, and for which there is no need to specify the relative precedence of different primary expressions because the syntax would never be ambiguous.</p>
<p>So, expressions like <code>1</code> (a literal) or <code>x</code> (a simple name) are primary, but also <code>f(x)</code> is primary in languages like Java because there are no other primaries you could replace <code>f</code> or <code>x</code> with that would need additional parentheses to be unambiguous. Likewise, <code>x.y.z()</code> is primary because there is no syntactic ambiguity: it must mean <code>(x.y).z()</code>, because <code>x.(y.z())</code> is not valid.</p>
<p>Compare this with binary operator expressions, like <code>x + y * z</code> where either <code>(x + y) * z</code> or <code>x + (y * z)</code> could be valid, or unary operator expressions like <code>*x++</code> where either <code>(*x)++</code> or <code>*(x++)</code> could be valid. In these cases, precedence rules are required to disambiguate.</p>
<hr />
<p>It's also worth thinking about this from the perspective of parsers. In a hand-written parser, the <code>parseExpression()</code> function could look something like this:</p>
<pre class="lang-js prettyprint-override"><code>function parseExpression(minPrecedence) {
    let expr = parseUnaryExpression(minPrecedence);
    while(hasNextBinaryOperator(minPrecedence)) {
        let op = pollBinaryOperator();
        let rhs = parseExpression(precedenceOf(op));
        expr = new BinaryExpr(expr, op, rhs);
    }
    return expr;
}
</code></pre>
<p>This is an oversimplification, but let's keep it simple. You need a <code>parseUnaryExpression()</code> function because you want to call it unconditionally; if you called <code>parseExpression()</code> recursively there, it would never terminate. So then the <code>parseUnaryExpression()</code> function could look like this:</p>
<pre class="lang-js prettyprint-override"><code>function parseUnaryExpression(minPrecedence) {
    if(hasNextUnaryOperator(minPrecedence)) {
        let op = pollUnaryOperator();
        let rhs = parseUnaryExpression(precedenceOf(op));
        return new UnaryExpr(op, rhs);
    } else {
        return parsePrimaryExpression();
    }
}
</code></pre>
<p>Again, this is an oversimplification (e.g. it ignores the possibility of postfix unary operators), but it gets the point across: the binary operators are already handled in the first function, and now this function handles all the unary operators, and then for the same reason ─ recursion needing a base case ─ you need a separate <code>parsePrimaryExpression()</code> function.</p>
<p>However, note that <code>parsePrimaryExpression()</code> doesn't need a <code>minPrecedence</code> argument. This is because for all the remaining types of expression, we know when to stop parsing based on knowing what the last token in that expression should be. There might be a loop condition (e.g. to parse <code>a.b.c.d</code>, keep going as long as there is another dot) but there is no need to consider precedence, because all operators with precedences below the maximum have already been handled elsewhere.</p>

CC BY-SA 4.0
2023-11-29T23:16:41.957Z
2023-12-03T18:15:16.573Z
2023-12-03T18:15:16.573Z
kaya3
CC BY-SA 4.0
2023-11-30T20:32:27.647Z
And of course there are languages (not even terribly obscure ones) where `f(x)` or `x.y.z()` *wouldn't* be primary in that sense. So it all comes down to the language you're parsing.
hobbs
CC BY-SA 4.0
2023-11-30T21:55:41.907Z
... such as C, among others.
John Bollinger
CC BY-SA 4.0
2023-11-30T21:59:25.300Z
But precedence of operations does seem to be the conventional way to look at it.  The primary expressions are those that can be operands of the highest-precedence operators.
John Bollinger
CC BY-SA 4.0
2023-11-30T22:39:38.347Z
@JohnBollinger Yes, although I wouldn't phrase it like that because conventionally things like `(...)` and `x.y` are included alongside "operators" in precedence tables, e.g. [Python](https://docs.python.org/3/reference/expressions.html#operator-precedence) and [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table). So many people would consider these to be the highest-precedence constructs, even though they are not technically operators
kaya3
CC BY-SA 4.0
2023-12-01T01:25:10.780Z
In my language they are both implemented as the highest-precedence postfix operators, not as primaries, so you can still have that “technically” not be technical
Seggan
# What is a "primary expression"?
Posted by: username_0 on 2023-11-29
I've found that many grammars have a production called `PrimaryExpression` or something along those lines. [ECMAScript has `PrimaryExpression`](https://tc39.es/ecma262/#prod-PrimaryExpression), [Python has `primary`](https://docs.python.org/3/reference/grammar.html), [C# has `primary_expression`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/grammar), [Java has `Primary`](https://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html), and many more I've seen over the years.

It cannot be a coincidence that all these specifications have it. What is considered a "primary expression"?

Maybe Haskell has one too, but [I can't decipher which one it is](https://www.haskell.org/onlinereport/syntax-iso.html). If there's a primary expression, what's it called in their specification? If there's no primary expression, what's different about Haskell's syntax (or the way grammar is defined) that makes it stand out?
**Tags:** expressions grammar
> **Comments:**
> **username_1**: I would argue that it is indeed a coincidence - "primary" is just a good name for the "top" of whatever expression hierarchy you have.  
> **username_2**: In Haskell it seems to be "aexp".  
---
## 3 answers
### Answer by username_2 on 2023-11-29. Score: 13 | Accepted answer
I don't think there is a universal definition, but I'll attempt one anyway: the primary expressions in a language are those which have the highest level of precedence, and for which there is no need to specify the relative precedence of different primary expressions because the syntax would never be ambiguous.
So, expressions like 1 (a literal) or x (a simple name) are primary, but also f(x) is primary in languages like Java because there are no other primaries you could replace f or x with that would need additional parentheses to be unambiguous. Likewise, x.y.z() is primary because there is no syntactic ambiguity: it must mean (x.y).z(), because x.(y.z()) is not valid.
Compare this with binary operator expressions, like x + y * z where either (x + y) * z or x + (y * z) could be valid, or unary operator expressions like *x++ where either (*x)++ or *(x++) could be valid. In these cases, precedence rules are required to disambiguate.

It's also worth thinking about this from the perspective of parsers. In a hand-written parser, the parseExpression() function could look something like this:
function parseExpression(minPrecedence) {
    let expr = parseUnaryExpression(minPrecedence);
    while(hasNextBinaryOperator(minPrecedence)) {
        let op = pollBinaryOperator();
        let rhs = parseExpression(precedenceOf(op));
        expr = new BinaryExpr(expr, op, rhs);
    }
    return expr;
}

This is an oversimplification, but let's keep it simple. You need a parseUnaryExpression() function because you want to call it unconditionally; if you called parseExpression() recursively there, it would never terminate. So then the parseUnaryExpression() function could look like this:
function parseUnaryExpression(minPrecedence) {
    if(hasNextUnaryOperator(minPrecedence)) {
        let op = pollUnaryOperator();
        let rhs = parseUnaryExpression(precedenceOf(op));
        return new UnaryExpr(op, rhs);
    } else {
        return parsePrimaryExpression();
    }
}

Again, this is an oversimplification (e.g. it ignores the possibility of postfix unary operators), but it gets the point across: the binary operators are already handled in the first function, and now this function handles all the unary operators, and then for the same reason ─ recursion needing a base case ─ you need a separate parsePrimaryExpression() function.
However, note that parsePrimaryExpression() doesn't need a minPrecedence argument. This is because for all the remaining types of expression, we know when to stop parsing based on knowing what the last token in that expression should be. There might be a loop condition (e.g. to parse a.b.c.d, keep going as long as there is another dot) but there is no need to consider precedence, because all operators with precedences below the maximum have already been handled elsewhere.
> **Comments:**
> **username_5** (2023-11-30): And of course there are languages (not even terribly obscure ones) where `f(x)` or `x.y.z()` *wouldn't* be primary in that sense. So it all comes down to the language you're parsing.  
> **username_6** (2023-11-30): ... such as C, among others.  
> **username_6** (2023-11-30): But precedence of operations does seem to be the conventional way to look at it.  The primary expressions are those that can be operands of the highest-precedence operators.  
> **username_2** (2023-11-30): @JohnBollinger Yes, although I wouldn't phrase it like that because conventionally things like `(...)` and `x.y` are included alongside "operators" in precedence tables, e.g. [Python](https://docs.python.org/3/reference/expressions.html#operator-precedence) and [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table). So many people would consider these to be the highest-precedence constructs, even though they are not technically operators  
> **username_7** (2023-12-01): In my language they are both implemented as the highest-precedence postfix operators, not as primaries, so you can still have that “technically” not be technical  
---
### Answer by username_3 on 2023-11-30. Score: 2
It's merely a convention, which goes back to at least Schorre's definition of Meta-2 in 1964. I don't know to what extent there were equivalent (published) syntax specifications before that, particularly in the form of text-based rules or equations.

See <https://dl.acm.org/doi/10.1145/800257.808896> where in the specification for either the VALGOL-I or VALGOL-II demonstration language a primary is defined as the product of terms and so on.

This has obviously been quite a lot of tidying up and codification in the intervening 60 years.

Updated: here is a direct link to a reprint <https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=56614.0;attach=45608>
---
### Answer by username_4 on 2023-11-29. Score: 1
All of the instances you link are atomic (or at least cohesive) value head expressions, without including any operator expressions: `x` and `3.5` and `(x + 3.5)` are primary expressions, but `x + 3.5` is not, while still being an *expression*. This structure can make unambiguous parsing easier. The name itself is not significant, but Primary is a common term for it.

Other parts of the grammar can say they accept any "expression" (for example, the right-hand side of an assignment or an argument list), but the parts that deal with constructing expressions themselves want to talk about the indivisible units of expressions in places.
> **Comments:**
> **username_2** (2023-11-29): This isn't quite accurate: in Java `x.y.z` is a primary expression, but I wouldn't call it atomic.  
> **username_4** (2023-11-29): Yeah, I’m not sure quite what the right phrasing is. It’s treated as a unit by the rest of the grammar and most are genuinely atomic, but a few are still slightly divisible. Some of the others don’t include that sort of thing in with the rest.  
---
