Skip to content

Commit aa145e7

Browse files
committed
fix EvilBeaver#1542: точное позиционирование ошибки
1 parent bd084c3 commit aa145e7

File tree

4 files changed

+87
-42
lines changed

4 files changed

+87
-42
lines changed

src/OneScript.Language/LanguageDef.cs

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public static class LanguageDef
1717
static readonly Dictionary<Token, int> _priority = new Dictionary<Token, int>();
1818
public const int MAX_OPERATION_PRIORITY = 8;
1919

20+
private static readonly Dictionary<Token, (string, string)> _keywords = new Dictionary<Token, (string, string)>();
21+
2022
private static readonly IdentifiersTrie<Token> _stringToToken = new IdentifiersTrie<Token>();
2123

2224
private static readonly IdentifiersTrie<bool> _undefined = new IdentifiersTrie<bool>();
@@ -72,42 +74,42 @@ static LanguageDef()
7274

7375
#region Ключевые слова
7476

75-
AddToken(Token.If, "если", "if");
76-
AddToken(Token.Then, "тогда", "then");
77-
AddToken(Token.Else, "иначе", "else");
78-
AddToken(Token.ElseIf, "иначеесли", "elsif");
79-
AddToken(Token.EndIf, "конецесли", "endif");
80-
AddToken(Token.VarDef, "перем", "var");
81-
AddToken(Token.ByValParam, "знач", "val");
82-
AddToken(Token.Procedure, "процедура", "procedure");
83-
AddToken(Token.EndProcedure, "конецпроцедуры", "endprocedure");
84-
AddToken(Token.Function, "функция", "function");
85-
AddToken(Token.EndFunction, "конецфункции", "endfunction");
86-
AddToken(Token.For, "для", "for");
87-
AddToken(Token.Each, "каждого", "each");
88-
AddToken(Token.In, "из", "in");
89-
AddToken(Token.To, "по", "to");
90-
AddToken(Token.While, "пока", "while");
91-
AddToken(Token.Loop, "цикл", "do");
92-
AddToken(Token.EndLoop, "конеццикла", "enddo");
93-
AddToken(Token.Return, "возврат", "return");
94-
AddToken(Token.Continue, "продолжить", "continue");
95-
AddToken(Token.Break, "прервать", "break");
96-
AddToken(Token.Try, "попытка", "try");
97-
AddToken(Token.Exception, "исключение", "except");
98-
AddToken(Token.Execute, "выполнить", "execute");
99-
AddToken(Token.RaiseException, "вызватьисключение", "raise");
100-
AddToken(Token.EndTry, "конецпопытки", "endtry");
101-
AddToken(Token.NewObject, "новый", "new");
102-
AddToken(Token.Export, "экспорт", "export");
103-
AddToken(Token.And, "и", "and");
104-
AddToken(Token.Or, "или", "or");
105-
AddToken(Token.Not, "не", "not");
106-
AddToken(Token.AddHandler, "ДобавитьОбработчик", "AddHandler");
107-
AddToken(Token.RemoveHandler, "УдалитьОбработчик", "RemoveHandler");
108-
AddToken(Token.Async, "Асинх", "Async");
109-
AddToken(Token.Await, "Ждать", "Await");
110-
AddToken(Token.Goto, "Перейти", "Goto");
77+
AddKeyword(Token.If, "Если", "If");
78+
AddKeyword(Token.Then, "Тогда", "Then");
79+
AddKeyword(Token.Else, "Иначе", "Else");
80+
AddKeyword(Token.ElseIf, "ИначеЕсли", "ElsIf");
81+
AddKeyword(Token.EndIf, "КонецЕсли", "EndIf");
82+
AddKeyword(Token.VarDef, "Перем", "Var");
83+
AddKeyword(Token.ByValParam, "Знач", "Val");
84+
AddKeyword(Token.Procedure, "Процедура", "Procedure");
85+
AddKeyword(Token.EndProcedure, "КонецПроцедуры", "EndProcedure");
86+
AddKeyword(Token.Function, "Функция", "Function");
87+
AddKeyword(Token.EndFunction, "КонецФункции", "EndFunction");
88+
AddKeyword(Token.For, "Для", "For");
89+
AddKeyword(Token.Each, "Каждого", "Each");
90+
AddKeyword(Token.In, "Из", "In");
91+
AddKeyword(Token.To, "По", "To");
92+
AddKeyword(Token.While, "Пока", "While");
93+
AddKeyword(Token.Loop, "Цикл", "Do");
94+
AddKeyword(Token.EndLoop, "КонецЦикла", "EndDo");
95+
AddKeyword(Token.Return, "Возврат", "Return");
96+
AddKeyword(Token.Continue, "Продолжить", "Continue");
97+
AddKeyword(Token.Break, "Прервать", "Break");
98+
AddKeyword(Token.Try, "Попытка", "Try");
99+
AddKeyword(Token.Exception, "Исключение", "Except");
100+
AddKeyword(Token.Execute, "Выполнить", "Execute");
101+
AddKeyword(Token.RaiseException, "ВызватьИсключение", "Raise");
102+
AddKeyword(Token.EndTry, "КонецПопытки", "EndTry");
103+
AddKeyword(Token.NewObject, "Новый", "New");
104+
AddKeyword(Token.Export, "Экспорт", "Export");
105+
AddKeyword(Token.And, "И", "And");
106+
AddKeyword(Token.Or, "Или", "Or");
107+
AddKeyword(Token.Not, "Не", "Not");
108+
AddKeyword(Token.AddHandler, "ДобавитьОбработчик", "AddHandler");
109+
AddKeyword(Token.RemoveHandler, "УдалитьОбработчик", "RemoveHandler");
110+
AddKeyword(Token.Async, "Асинх", "Async");
111+
AddKeyword(Token.Await, "Ждать", "Await");
112+
AddKeyword(Token.Goto, "Перейти", "Goto");
111113

112114
#endregion
113115

@@ -229,6 +231,33 @@ private static void AddToken(Token token, string name, string alias)
229231
_stringToToken.Add(alias, token);
230232
}
231233

234+
private static void AddKeyword(Token token, string name, string alias)
235+
{
236+
_keywords.Add(token, (name,alias));
237+
_stringToToken.Add(name, token);
238+
_stringToToken.Add(alias, token);
239+
}
240+
241+
public static string GetTokenName(Token token)
242+
{
243+
if (_keywords.TryGetValue(token,out var strings))
244+
{
245+
return strings.Item1;
246+
}
247+
248+
return Enum.GetName(typeof(Token), token);
249+
}
250+
public static string GetTokenAlias(Token token)
251+
{
252+
if (_keywords.TryGetValue(token,out var strings))
253+
{
254+
return strings.Item2;
255+
}
256+
257+
return Enum.GetName(typeof(Token), token);
258+
}
259+
260+
232261
public static Token GetToken(string tokText)
233262
{
234263
Token result;

src/OneScript.Language/ScriptException.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,20 @@ public override string Message
9797
get
9898
{
9999
var sb = new StringBuilder(MessageWithoutCodeFragment);
100-
sb.AppendLine(" ");
101-
sb.Append(Code);
100+
sb.AppendLine();
101+
sb.AppendLine(Code.Replace('\t', ' ').TrimEnd());
102+
103+
if (ColumnNumber != ErrorPositionInfo.OUT_OF_TEXT)
104+
{
105+
if (ColumnNumber > 1)
106+
sb.Append(' ', ColumnNumber - 1);
107+
sb.AppendLine(BilingualString.Localize("^--здесь", "^--here"));
108+
}
102109

103110
return sb.ToString();
104111
}
105112
}
106-
113+
107114
public object RuntimeSpecificInfo { get; set; }
108115

109116
public void SetPositionIfEmpty(ErrorPositionInfo newPosition)

src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1366,8 +1366,8 @@ private BslSyntaxNode BuildExpressionUpTo(NonTerminalNode parent, Token stopToke
13661366
}
13671367
else
13681368
{
1369+
AddError(LocalizedErrors.TokenExpected(stopToken), false);
13691370
SkipToNextStatement(new []{stopToken});
1370-
AddError(LocalizedErrors.ExpressionSyntax(), false);
13711371
if (_lastExtractedLexem.Token == stopToken)
13721372
{
13731373
NextLexem();
@@ -1640,6 +1640,7 @@ private void SkipToNextStatement(Token[] additionalStops = null)
16401640
private void AddError(CodeError err, bool doFastForward = true)
16411641
{
16421642
err.Position = _lexer.GetErrorPosition();
1643+
err.Position.ColumnNumber -= _lastExtractedLexem.Content.Length;
16431644
ErrorSink.AddError(err);
16441645

16451646
if (doFastForward)

src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,17 @@ public static CodeError ExpressionSyntax()
5252

5353
public static CodeError TokenExpected(params Token[] expected)
5454
{
55-
var names = String.Join("/", expected.Select(x => Enum.GetName(typeof(Token), x)));
55+
if (expected.Length == 1)
56+
{
57+
return Create($"Ожидается символ: {LanguageDef.GetTokenName(expected[0])}",
58+
$"Expecting symbol: {LanguageDef.GetTokenAlias(expected[0])}");
59+
}
60+
61+
var names = String.Join("/", expected.Select(x => LanguageDef.GetTokenName(x)));
62+
var aliases = String.Join("/", expected.Select(x => LanguageDef.GetTokenAlias(x)));
63+
64+
return Create($"Ожидается один из симолов: {names}", $"Expecting one of symbols: {names}");
5665

57-
return Create($"Ожидается символ: {names}", $"Expecting symbol: {names}");
5866
}
5967

6068
public static CodeError ExportedLocalVar(string varName)

0 commit comments

Comments
 (0)