Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| creating:expressions [2025/04/19 19:44] – Use internal wiki links ahelwer | creating:expressions [2025/05/13 15:58] (current) – Fixed lookahead in set literal parsing ahelwer | ||
|---|---|---|---|
| Line 37: | Line 37: | ||
| ternary | ternary | ||
| variadic | variadic | ||
| - | operator | + | operator |
| </ | </ | ||
| There are a few interesting differences. | There are a few interesting differences. | ||
| Line 50: | Line 50: | ||
| The only difference between '' | The only difference between '' | ||
| This is the perspective of a language implementer. | This is the perspective of a language implementer. | ||
| - | Later on we will extend | + | |
| + | Note that we //could// also include | ||
| ===== Section 5.2: Implementing Syntax Trees ===== | ===== Section 5.2: Implementing Syntax Trees ===== | ||
| Line 397: | Line 398: | ||
| Now we have to define a table of operators with their details. | Now we have to define a table of operators with their details. | ||
| - | For this, create | + | First use the handy Java 17 [[https:// |
| + | Put it at the top of the '' | ||
| - | <code java> | + | <code java [highlight_lines_extra=" |
| - | package tla; | + | class Parser { |
| + | private static enum Fix { PREFIX, INFIX, POSTFIX } | ||
| + | private static record Operator(Fix fix, TokenType token, | ||
| + | boolean assoc, int lowPrec, int highPrec) {} | ||
| - | enum Fix { | + | private |
| - | PREFIX, INFIX, POSTFIX | + | |
| - | } | + | |
| - | + | ||
| - | class Operator { | + | |
| - | | + | |
| - | final TokenType token; | + | |
| - | final boolean assoc; | + | |
| - | final int lowPrec; | + | |
| - | final int highPrec; | + | |
| - | + | ||
| - | public Operator(Fix fix, TokenType token, boolean assoc, | + | |
| - | int lowPrec, int highPrec) { | + | |
| - | this.fix = fix; | + | |
| - | this.token = token; | + | |
| - | this.assoc = assoc; | + | |
| - | this.lowPrec = lowPrec; | + | |
| - | this.highPrec = highPrec; | + | |
| - | } | + | |
| - | } | + | |
| </ | </ | ||
| - | |||
| - | For convenience, | ||
| - | |||
| - | <code java [highlight_lines_extra=" | ||
| - | package tla; | ||
| - | |||
| - | import java.util.List; | ||
| - | import java.util.ArrayList; | ||
| - | |||
| - | import static tla.TokenType.*; | ||
| - | import static tla.Fix.*; | ||
| - | |||
| - | class Parser { | ||
| - | </ | ||
| - | |||
| You can find operator attributes on page 271 of // | You can find operator attributes on page 271 of // | ||
| Line 445: | Line 416: | ||
| <code java> | <code java> | ||
| private static final Operator[] operators = new Operator[] { | private static final Operator[] operators = new Operator[] { | ||
| - | new Operator(PREFIX, | + | new Operator(Fix.PREFIX, |
| - | new Operator(PREFIX, | + | new Operator(Fix.PREFIX, |
| - | new Operator(PREFIX, | + | new Operator(Fix.PREFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.INFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.INFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.INFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.INFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.INFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.INFIX, |
| - | new Operator(INFIX, | + | new Operator(Fix.POSTFIX, PRIME, |
| - | new Operator(INFIX, | + | |
| - | new Operator(POSTFIX, | + | |
| }; | }; | ||
| </ | </ | ||
| Line 492: | Line 461: | ||
| Expr expr = operatorExpression(prec + 1); | Expr expr = operatorExpression(prec + 1); | ||
| - | while ((op = matchOp(INFIX, | + | while ((op = matchOp(Fix.INFIX, prec)) != null) { |
| Token operator = previous(); | Token operator = previous(); | ||
| Expr right = operatorExpression(op.highPrec + 1); | Expr right = operatorExpression(op.highPrec + 1); | ||
| Line 511: | Line 480: | ||
| We need to modify the loop to return immediately if the infix operator is not associative: | We need to modify the loop to return immediately if the infix operator is not associative: | ||
| <code java [highlight_lines_extra=" | <code java [highlight_lines_extra=" | ||
| - | while ((op = matchOp(INFIX, | + | while ((op = matchOp(Fix.INFIX, prec)) != null) { |
| Token operator = previous(); | Token operator = previous(); | ||
| Expr right = operatorExpression(op.highPrec + 1); | Expr right = operatorExpression(op.highPrec + 1); | ||
| Line 529: | Line 498: | ||
| Operator op; | Operator op; | ||
| - | if ((op = matchOp(PREFIX, | + | if ((op = matchOp(Fix.PREFIX, prec)) != null) { |
| Token opToken = previous(); | Token opToken = previous(); | ||
| Expr expr = operatorExpression( | Expr expr = operatorExpression( | ||
| Line 555: | Line 524: | ||
| } | } | ||
| - | while ((op = matchOp(POSTFIX, | + | while ((op = matchOp(Fix.POSTFIX, prec)) != null) { |
| Token opToken = previous(); | Token opToken = previous(); | ||
| expr = new Expr.Unary(opToken, | expr = new Expr.Unary(opToken, | ||
| Line 615: | Line 584: | ||
| if (match(LEFT_BRACE)) { | if (match(LEFT_BRACE)) { | ||
| Token operator = previous(); | Token operator = previous(); | ||
| - | List< | + | List< |
| - | if (RIGHT_BRACE | + | if (!check(RIGHT_BRACE)) { |
| do { | do { | ||
| elements.add(expression()); | elements.add(expression()); | ||
| Line 667: | Line 636: | ||
| Add the '' | Add the '' | ||
| - | <code java [highlight_lines_extra=" | + | <code java [highlight_lines_extra=" |
| class Parser { | class Parser { | ||
| + | private static enum Fix { PREFIX, INFIX, POSTFIX } | ||
| + | private static record Operator(Fix fix, TokenType token, | ||
| + | boolean assoc, int lowPrec, int highPrec) {} | ||
| private static class ParseError extends RuntimeException {} | private static class ParseError extends RuntimeException {} | ||
| Line 716: | Line 688: | ||
| ({ (+ 1 2) (IF true 3 4) ({)) | ({ (+ 1 2) (IF true 3 4) ({)) | ||
| </ | </ | ||
| - | If you got out of sync, you can find a snapshot of the expected state of the code in [[https:// | + | If you got out of sync, you can find a snapshot of the expected state of the code in [[https:// |
| Next tutorial: [[creating: | Next tutorial: [[creating: | ||