2121 */
2222package com .github ._1c_syntax .bsl .languageserver .utils .expressiontree ;
2323
24+ import com .github ._1c_syntax .bsl .languageserver .utils .Trees ;
2425import com .github ._1c_syntax .bsl .parser .BSLLexer ;
2526import com .github ._1c_syntax .bsl .parser .BSLParser ;
2627import com .github ._1c_syntax .bsl .parser .BSLParserBaseVisitor ;
27- import lombok . Value ;
28+ import org . antlr . v4 . runtime . tree . ErrorNode ;
2829import org .antlr .v4 .runtime .tree .ParseTree ;
2930import org .antlr .v4 .runtime .tree .TerminalNode ;
3031
4041 */
4142public final class ExpressionTreeBuildingVisitor extends BSLParserBaseVisitor <ParseTree > {
4243
43- @ Value
44- private static class OperatorInCode {
45- BslOperator operator ;
46- ParseTree actualSourceCode ; // ИЛИ vs OR в диагностических сообщениях, как написано в коде
47-
44+ /**
45+ * @param actualSourceCode ИЛИ vs OR в диагностических сообщениях, как написано в коде
46+ */
47+ private record OperatorInCode (BslOperator operator , ParseTree actualSourceCode ) {
4848 public int getPriority () {
4949 return operator .getPriority ();
5050 }
@@ -85,6 +85,16 @@ public ParseTree visitExpression(BSLParser.ExpressionContext ctx) {
8585 var nestingCount = operatorsInFly .size ();
8686 recursionLevel ++;
8787
88+ if (Trees .nodeContainsErrors (ctx ) || (ctx .getChildCount () == 0 || ctx .children .stream ().anyMatch (ErrorNode .class ::isInstance ))) {
89+ var errorExpressionNode = new ErrorExpressionNode (ctx );
90+ if (recursionLevel > 0 ) {
91+ operands .push (errorExpressionNode );
92+ } else {
93+ resultExpression = errorExpressionNode ;
94+ }
95+ return ctx ;
96+ }
97+
8898 visitMember (ctx .member (0 ));
8999 var count = ctx .getChildCount ();
90100
@@ -110,6 +120,7 @@ public ParseTree visitExpression(BSLParser.ExpressionContext ctx) {
110120 }
111121
112122 var operation = operands .peek ();
123+
113124 // В случае ошибок парсинга выражения, operation может быть null
114125 if (operation == null ) {
115126 recursionLevel --;
@@ -132,7 +143,8 @@ public ParseTree visitExpression(BSLParser.ExpressionContext ctx) {
132143 public ParseTree visitMember (BSLParser .MemberContext ctx ) {
133144
134145 // В случае ошибки парсинга member может быть пустой.
135- if (ctx .getChildCount () == 0 ) {
146+ if (Trees .nodeContainsErrors (ctx ) || ctx .getChildCount () == 0 || ctx .children .stream ().anyMatch (ErrorNode .class ::isInstance )) {
147+ operands .push (new ErrorExpressionNode (ctx ));
136148 return ctx ;
137149 }
138150
@@ -146,26 +158,26 @@ public ParseTree visitMember(BSLParser.MemberContext ctx) {
146158
147159 var unaryModifier = ctx .unaryModifier ();
148160 var childIndex = 0 ;
161+
149162 if (unaryModifier != null ) {
150163 visitUnaryModifier (unaryModifier );
151- childIndex = 1 ;
164+ childIndex = ctx . children . indexOf ( unaryModifier ) + 1 ;
152165 }
153166
154167 if (ctx .waitExpression () != null ) {
155168 return visitWaitExpression (ctx .waitExpression ());
156169 }
157170
158171 var dispatchChild = ctx .getChild (childIndex );
159- if (dispatchChild instanceof TerminalNode terminalNode ) {
172+ if (dispatchChild instanceof ErrorNode ) {
173+ operands .push (new ErrorExpressionNode (dispatchChild ));
174+ } else if (dispatchChild instanceof TerminalNode terminalNode ) {
160175 var token = terminalNode .getSymbol ().getType ();
161176
162177 // ручная диспетчеризация
163178 switch (token ) {
164- case BSLLexer .LPAREN :
165- visitParenthesis (ctx .expression (), ctx .modifier ());
166- break ;
167- default :
168- throw new IllegalStateException ("Unexpected rule " + dispatchChild );
179+ case BSLLexer .LPAREN -> visitParenthesis (ctx .expression (), ctx .modifier ());
180+ default -> operands .push (new ErrorExpressionNode (dispatchChild ));
169181 }
170182 } else {
171183 dispatchChild .accept (this );
@@ -177,7 +189,18 @@ public ParseTree visitMember(BSLParser.MemberContext ctx) {
177189 private void visitParenthesis (BSLParser .ExpressionContext expression ,
178190 List <? extends BSLParser .ModifierContext > modifiers ) {
179191
192+ // Handle the case where expression is empty (empty parentheses)
193+ if (expression == null || expression .getTokens ().isEmpty ()) {
194+ operands .push (new ErrorExpressionNode (expression ));
195+ return ;
196+ }
197+
180198 var subExpr = makeSubexpression (expression );
199+
200+ if (subExpr == null ) {
201+ subExpr = new ErrorExpressionNode (expression );
202+ }
203+
181204 operands .push (subExpr );
182205
183206 for (var modifier : modifiers ) {
@@ -314,6 +337,11 @@ public ParseTree visitGlobalMethodCall(BSLParser.GlobalMethodCallContext ctx) {
314337
315338 @ Override
316339 public ParseTree visitNewExpression (BSLParser .NewExpressionContext ctx ) {
340+ if (Trees .nodeContainsErrors (ctx )) {
341+ operands .push (new ErrorExpressionNode (ctx ));
342+ return ctx ;
343+ }
344+
317345 var typeName = ctx .typeName ();
318346
319347 List <? extends BSLParser .CallParamContext > args ;
@@ -327,6 +355,10 @@ public ParseTree visitNewExpression(BSLParser.NewExpressionContext ctx) {
327355 if (typeName == null ) {
328356 // function style
329357 var typeNameArg = args .get (0 );
358+ if (typeNameArg .expression () == null ) {
359+ operands .push (new ErrorExpressionNode (ctx ));
360+ return ctx ;
361+ }
330362 args = args .stream ().skip (1 ).toList ();
331363 callNode = ConstructorCallNode .createDynamic (makeSubexpression (typeNameArg .expression ()));
332364 } else {
@@ -407,18 +439,18 @@ private void buildOperation() {
407439 }
408440
409441 var operator = operatorsInFly .pop ();
410- if (Objects .requireNonNull (operator .getOperator ()) == BslOperator .UNARY_MINUS
411- || operator .getOperator () == BslOperator .NOT
412- || operator .getOperator () == BslOperator .UNARY_PLUS ) {
442+ if (Objects .requireNonNull (operator .operator ()) == BslOperator .UNARY_MINUS
443+ || operator .operator () == BslOperator .NOT
444+ || operator .operator () == BslOperator .UNARY_PLUS ) {
413445
414446 var operand = operands .pop ();
415- var operation = UnaryOperationNode .create (operator .getOperator (), operand , operator .getActualSourceCode ());
447+ var operation = UnaryOperationNode .create (operator .operator (), operand , operator .actualSourceCode ());
416448 operand .setParent (operation );
417449 operands .push (operation );
418450 } else {
419451 var right = operands .pop ();
420452 var left = operands .pop ();
421- var binaryOp = BinaryOperationNode .create (operator .getOperator (), left , right , operator .getActualSourceCode ());
453+ var binaryOp = BinaryOperationNode .create (operator .operator (), left , right , operator .actualSourceCode ());
422454
423455 left .setParent (binaryOp );
424456 right .setParent (binaryOp );
0 commit comments