diff --git a/src/OneScript.Language/ScriptException.cs b/src/OneScript.Language/ScriptException.cs index 329285557..f6f3d0179 100644 --- a/src/OneScript.Language/ScriptException.cs +++ b/src/OneScript.Language/ScriptException.cs @@ -104,11 +104,11 @@ public override string Message ColumnNumber = codeLine.Length; } - if (ColumnNumber != ErrorPositionInfo.OUT_OF_TEXT) + if (ColumnNumber > 0) { - sb.Append(codeLine[..ColumnNumber]); + sb.Append(codeLine[..(ColumnNumber - 1)]); sb.Append("<>"); - sb.AppendLine(codeLine[ColumnNumber..]); + sb.AppendLine(codeLine[(ColumnNumber - 1)..]); } else { diff --git a/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs b/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs index 94c19feed..c1e5acdca 100644 --- a/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs +++ b/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs @@ -1410,59 +1410,82 @@ private BslSyntaxNode BuildQuestionOperator() } return BuildDereference(node); - } + } + + private bool IsDereferenceable(BslSyntaxNode node) + => node.Kind switch + { + NodeKind.Identifier + or NodeKind.GlobalCall or NodeKind.MethodCall + or NodeKind.DereferenceOperation or NodeKind.IndexAccess + or NodeKind.TernaryOperator + or NodeKind.NewObject // несовместимо с 1С + => true, + + _ => false + }; private BslSyntaxNode BuildDereference(BslSyntaxNode target) { var activeTarget = BuildIndexerAccess(target); - if (_lastExtractedLexem.Token == Token.Dot) + if (_lastExtractedLexem.Token != Token.Dot) + { + return activeTarget; + } + + if (!IsDereferenceable(target)) { - var dotNode = new NonTerminalNode(NodeKind.DereferenceOperation, _lastExtractedLexem); - dotNode.AddChild(activeTarget); - NextLexem(); - if (!LanguageDef.IsValidPropertyName(_lastExtractedLexem)) - { - return CreateError(LocalizedErrors.IdentifierExpected()); - } - - var identifier = _lastExtractedLexem; - NextLexem(); - if (_lastExtractedLexem.Token == Token.OpenPar) - { - var ident = new TerminalNode(NodeKind.Identifier, identifier); - var call = BuildCall(ident, NodeKind.MethodCall); - dotNode.AddChild(call); - } - else - { - _lastDereferenceIsWritable = true; - CreateChild(dotNode, NodeKind.Identifier, identifier); - } - - return BuildDereference(dotNode); - } - - return activeTarget; + AddError(LocalizedErrors.ValueIsNotObjectException(), false); + } + + var dotNode = new NonTerminalNode(NodeKind.DereferenceOperation, _lastExtractedLexem); + dotNode.AddChild(activeTarget); + NextLexem(); + if (!LanguageDef.IsValidPropertyName(_lastExtractedLexem)) + { + return CreateError(LocalizedErrors.IdentifierExpected()); + } + + var identifier = _lastExtractedLexem; + NextLexem(); + if (_lastExtractedLexem.Token == Token.OpenPar) + { + var ident = new TerminalNode(NodeKind.Identifier, identifier); + var call = BuildCall(ident, NodeKind.MethodCall); + dotNode.AddChild(call); + } + else + { + _lastDereferenceIsWritable = true; + CreateChild(dotNode, NodeKind.Identifier, identifier); + } + + return BuildDereference(dotNode); } private BslSyntaxNode BuildIndexerAccess(BslSyntaxNode target) { - if (_lastExtractedLexem.Token == Token.OpenBracket) + if (_lastExtractedLexem.Token != Token.OpenBracket) + { + return target; + } + + if (!IsDereferenceable(target)) { - var node = new NonTerminalNode(NodeKind.IndexAccess, _lastExtractedLexem); - node.AddChild(target); - NextLexem(); - var expression = BuildExpression(node, Token.CloseBracket); - if (expression.Kind == NodeKind.Unknown) - { - return CreateError(LocalizedErrors.ExpressionSyntax()); - } - NextLexem(); - _lastDereferenceIsWritable = true; - return BuildDereference(node); + AddError(LocalizedErrors.ValueIsNotObjectException(), false); } - return target; + var node = new NonTerminalNode(NodeKind.IndexAccess, _lastExtractedLexem); + node.AddChild(target); + NextLexem(); + var expression = BuildExpression(node, Token.CloseBracket); + if (expression.Kind == NodeKind.Unknown) + { + return CreateError(LocalizedErrors.ExpressionSyntax()); + } + NextLexem(); + _lastDereferenceIsWritable = true; + return BuildDereference(node); } private BslSyntaxNode BuildNewObjectCreation() diff --git a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs index fca4526e5..128b2dd9e 100644 --- a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs +++ b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs @@ -164,5 +164,10 @@ public static CodeError SymbolNotFound(string symbol) => public static CodeError AsyncMethodsNotSupported() => Create("Асинхронные методы не поддерживаются", "Async methods aren't supported"); - } -} \ No newline at end of file + + public static CodeError ValueIsNotObjectException() + { + return Create("Значение не является значением объектного типа", "Value is not of object type"); + } + } +}