@@ -120,6 +120,42 @@ export class LuaPrinter {
120120 [ lua . SyntaxKind . BitwiseLeftShiftOperator ] : "<<" ,
121121 [ lua . SyntaxKind . BitwiseNotOperator ] : "~" ,
122122 } ;
123+ private static operatorPrecedence : Record < lua . Operator , number > = {
124+ [ lua . SyntaxKind . OrOperator ] : 1 ,
125+ [ lua . SyntaxKind . AndOperator ] : 2 ,
126+
127+ [ lua . SyntaxKind . EqualityOperator ] : 3 ,
128+ [ lua . SyntaxKind . InequalityOperator ] : 3 ,
129+ [ lua . SyntaxKind . LessThanOperator ] : 3 ,
130+ [ lua . SyntaxKind . LessEqualOperator ] : 3 ,
131+ [ lua . SyntaxKind . GreaterThanOperator ] : 3 ,
132+ [ lua . SyntaxKind . GreaterEqualOperator ] : 3 ,
133+
134+ [ lua . SyntaxKind . BitwiseOrOperator ] : 4 ,
135+ [ lua . SyntaxKind . BitwiseExclusiveOrOperator ] : 5 ,
136+ [ lua . SyntaxKind . BitwiseAndOperator ] : 6 ,
137+
138+ [ lua . SyntaxKind . BitwiseLeftShiftOperator ] : 7 ,
139+ [ lua . SyntaxKind . BitwiseRightShiftOperator ] : 7 ,
140+
141+ [ lua . SyntaxKind . ConcatOperator ] : 8 ,
142+
143+ [ lua . SyntaxKind . AdditionOperator ] : 9 ,
144+ [ lua . SyntaxKind . SubtractionOperator ] : 9 ,
145+
146+ [ lua . SyntaxKind . MultiplicationOperator ] : 10 ,
147+ [ lua . SyntaxKind . DivisionOperator ] : 10 ,
148+ [ lua . SyntaxKind . FloorDivisionOperator ] : 10 ,
149+ [ lua . SyntaxKind . ModuloOperator ] : 10 ,
150+
151+ [ lua . SyntaxKind . NotOperator ] : 11 ,
152+ [ lua . SyntaxKind . LengthOperator ] : 11 ,
153+ [ lua . SyntaxKind . NegationOperator ] : 11 ,
154+ [ lua . SyntaxKind . BitwiseNotOperator ] : 11 ,
155+
156+ [ lua . SyntaxKind . PowerOperator ] : 12 ,
157+ } ;
158+ private static rightAssociativeOperators = new Set ( [ lua . SyntaxKind . ConcatOperator , lua . SyntaxKind . PowerOperator ] ) ;
123159
124160 private currentIndent = "" ;
125161 private luaFile : string ;
@@ -676,34 +712,49 @@ export class LuaPrinter {
676712 const chunks : SourceChunk [ ] = [ ] ;
677713
678714 chunks . push ( this . printOperator ( expression . operator ) ) ;
679- chunks . push ( this . printExpressionInParenthesesIfNeeded ( expression . operand ) ) ;
715+ chunks . push (
716+ this . printExpressionInParenthesesIfNeeded (
717+ expression . operand ,
718+ LuaPrinter . operatorPrecedence [ expression . operator ]
719+ )
720+ ) ;
680721
681722 return this . createSourceNode ( expression , chunks ) ;
682723 }
683724
684725 public printBinaryExpression ( expression : lua . BinaryExpression ) : SourceNode {
685726 const chunks : SourceChunk [ ] = [ ] ;
686-
687- chunks . push ( this . printExpressionInParenthesesIfNeeded ( expression . left ) ) ;
727+ const isRightAssociative = LuaPrinter . rightAssociativeOperators . has ( expression . operator ) ;
728+ const precedence = LuaPrinter . operatorPrecedence [ expression . operator ] ;
729+ chunks . push (
730+ this . printExpressionInParenthesesIfNeeded ( expression . left , isRightAssociative ? precedence + 1 : precedence )
731+ ) ;
688732 chunks . push ( " " , this . printOperator ( expression . operator ) , " " ) ;
689- chunks . push ( this . printExpressionInParenthesesIfNeeded ( expression . right ) ) ;
733+ chunks . push (
734+ this . printExpressionInParenthesesIfNeeded (
735+ expression . right ,
736+ isRightAssociative ? precedence : precedence + 1
737+ )
738+ ) ;
690739
691740 return this . createSourceNode ( expression , chunks ) ;
692741 }
693742
694- private printExpressionInParenthesesIfNeeded ( expression : lua . Expression ) : SourceNode {
695- return this . needsParenthesis ( expression )
743+ private printExpressionInParenthesesIfNeeded ( expression : lua . Expression , minPrecedenceToOmit ?: number ) : SourceNode {
744+ return this . needsParenthesis ( expression , minPrecedenceToOmit )
696745 ? this . createSourceNode ( expression , [ "(" , this . printExpression ( expression ) , ")" ] )
697746 : this . printExpression ( expression ) ;
698747 }
699748
700- private needsParenthesis ( expression : lua . Expression ) : boolean {
701- return (
702- lua . isBinaryExpression ( expression ) ||
703- lua . isFunctionExpression ( expression ) ||
704- lua . isTableExpression ( expression ) ||
705- ( lua . isUnaryExpression ( expression ) && expression . operator === lua . SyntaxKind . NotOperator )
706- ) ;
749+ private needsParenthesis ( expression : lua . Expression , minPrecedenceToOmit ?: number ) : boolean {
750+ if ( lua . isBinaryExpression ( expression ) || lua . isUnaryExpression ( expression ) ) {
751+ return (
752+ minPrecedenceToOmit === undefined ||
753+ LuaPrinter . operatorPrecedence [ expression . operator ] < minPrecedenceToOmit
754+ ) ;
755+ } else {
756+ return lua . isFunctionExpression ( expression ) || lua . isTableExpression ( expression ) ;
757+ }
707758 }
708759
709760 public printCallExpression ( expression : lua . CallExpression ) : SourceNode {
@@ -769,10 +820,19 @@ export class LuaPrinter {
769820 return intersperse ( chunks , ", " ) ;
770821 }
771822
823+ /**
824+ * Returns true if the expression list (table field or parameters) should be printed on one line.
825+ */
826+ protected isSimpleExpressionList ( expressions : lua . Expression [ ] ) : boolean {
827+ if ( expressions . length <= 1 ) return true ;
828+ if ( expressions . length > 4 ) return false ;
829+ return expressions . every ( isSimpleExpression ) ;
830+ }
831+
772832 protected printExpressionList ( expressions : lua . Expression [ ] ) : SourceChunk [ ] {
773833 const chunks : SourceChunk [ ] = [ ] ;
774834
775- if ( expressions . every ( isSimpleExpression ) ) {
835+ if ( this . isSimpleExpressionList ( expressions ) ) {
776836 chunks . push ( ...this . joinChunksWithComma ( expressions . map ( e => this . printExpression ( e ) ) ) ) ;
777837 } else {
778838 chunks . push ( "\n" ) ;
0 commit comments