Skip to content

Commit

Permalink
Add a ** b syntax for number::pow (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
RunDevelopment authored May 12, 2024
1 parent d0a0dda commit f99087b
Show file tree
Hide file tree
Showing 7 changed files with 778 additions and 637 deletions.
6 changes: 5 additions & 1 deletion src/antlr4/Navi.g4
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ ifExpression:

fieldAccessExpression: primaryExpression ('.' Identifier)*;

negateExpression: OpMinus? fieldAccessExpression;
powExpression:
fieldAccessExpression (OpPow fieldAccessExpression)?;

negateExpression: OpMinus? powExpression;

multiplicativeExpression:
negateExpression ((OpMult | OpDiv) negateExpression)*;
Expand Down Expand Up @@ -168,6 +171,7 @@ OpMinus: '-';
OpPlus: '+';
OpMult: '*';
OpDiv: '/';
OpPow: '**';
OpEqual: '==';
OpNotEqual: '!=';
OpGt: '>';
Expand Down
289 changes: 146 additions & 143 deletions src/antlr4/NaviLexer.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/antlr4/NaviListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,15 @@ export default class NaviListener extends antlr4.tree.ParseTreeListener {
}


// Enter a parse tree produced by NaviParser#powExpression.
enterPowExpression(ctx) {
}

// Exit a parse tree produced by NaviParser#powExpression.
exitPowExpression(ctx) {
}


// Enter a parse tree produced by NaviParser#negateExpression.
enterNegateExpression(ctx) {
}
Expand Down
1,064 changes: 575 additions & 489 deletions src/antlr4/NaviParser.js

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ class AstConverter {
| Contexts['AdditiveExpressionContext']
| Contexts['MultiplicativeExpressionContext']
| Contexts['NegateExpressionContext']
| Contexts['PowExpressionContext']
| Contexts['FieldAccessExpressionContext']
| Contexts['PrimaryExpressionContext']
| Contexts['FunctionCallContext']
Expand Down Expand Up @@ -465,12 +466,30 @@ class AstConverter {
);
}
if (context instanceof NaviParser.NegateExpressionContext) {
const expr = this.toExpression(getRequired(context, 'fieldAccessExpression'));
const powContext = getRequired(context, 'powExpression');
const expr = this.toExpression(powContext);

if (getOptionalToken(context, 'OpMinus')) {
if (getOptionalToken(powContext, 'OpPow')) {
// error: -a ** b is not allowed
throw new ConversionError(
context,
'Negation cannot be applied to exponentiation. -a**b is not allowed. Write either -(a**b) or (-a)**b instead.'
);
}
return new FunctionCallExpression('number::neg', [expr]);
}

return expr;
}
if (context instanceof NaviParser.PowExpressionContext) {
const expressions = getMultiple(context, 'fieldAccessExpression').map(
this.toExpression
);
if (expressions.length === 1) return expressions[0];
const [x, y] = expressions;
return new FunctionCallExpression('number::pow', [x, y]);
}
if (context instanceof NaviParser.FieldAccessExpressionContext) {
const ofExpression = this.toExpression(getRequired(context, 'primaryExpression'));
const fields = getMultipleTokens(context, 'Identifier').map((t) => t.getText());
Expand Down
19 changes: 17 additions & 2 deletions tests/__snapshots__/parse.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,18 @@ number::add(-100, number::neg(-100))
>>> a---100
number::add(a, number::neg(number::neg(-100)))
>>> a**b
number::pow(a, b)
>>> (-a)**b
number::pow(number::neg(a), b)
>>> -(a**b)
number::neg(number::pow(a, b))
>>> a*b**c*d
number::mul(a, number::pow(b, c), d)
>>> not a and b or c
bool::or(bool::and(bool::not(a), b), c)
Expand Down Expand Up @@ -844,8 +856,11 @@ SyntaxError: At 1:3: extraneous input '-' expecting {'{', '(', 'if', 'match', In
>>> a++a
SyntaxError: At 1:2: extraneous input '+' expecting {'{', '(', 'if', 'match', IntInterval, NonIntInterval, IntervalInclusive, IntervalMinExclusive, IntervalMaxExclusive, IntervalExclusive, Number, String, Identifier, '-'}
>>> a**a
SyntaxError: At 1:2: extraneous input '*' expecting {'{', '(', 'if', 'match', IntInterval, NonIntInterval, IntervalInclusive, IntervalMinExclusive, IntervalMaxExclusive, IntervalExclusive, Number, String, Identifier, '-'}
>>> a* *a
SyntaxError: At 1:3: extraneous input '*' expecting {'{', '(', 'if', 'match', IntInterval, NonIntInterval, IntervalInclusive, IntervalMinExclusive, IntervalMaxExclusive, IntervalExclusive, Number, String, Identifier, '-'}
>>> -a**a
Error: Unable to convert \`-a**a\`: Negation cannot be applied to exponentiation. -a**b is not allowed. Write either -(a**b) or (-a)**b instead.
>>> a-100
SyntaxError: At 1:1: extraneous input '-100' expecting <EOF>
Expand Down
7 changes: 6 additions & 1 deletion tests/parse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ const expressionSnippets: string[] = [
String.raw`a + b * c`,
String.raw`-100 - -100`,
String.raw`a---100`,
String.raw`a**b`,
String.raw`(-a)**b`,
String.raw`-(a**b)`,
String.raw`a*b**c*d`,

// logical
String.raw`not a and b or c`,
Expand Down Expand Up @@ -308,7 +312,8 @@ const invalidExpressionSnippets: string[] = [
String.raw`--a`,
String.raw`a+--a`,
String.raw`a++a`,
String.raw`a**a`,
String.raw`a* *a`,
String.raw`-a**a`,
String.raw`a-100`,

// logical
Expand Down

0 comments on commit f99087b

Please sign in to comment.