Skip to content

Commit b16a0dc

Browse files
committed
приоритет операторов вместо рекурсивного спуска
1 parent 8c9206e commit b16a0dc

File tree

2 files changed

+90
-133
lines changed

2 files changed

+90
-133
lines changed

src/OneScript.Language/LanguageDef.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,31 @@ public static Token GetToken(string tokText)
282282
public static int GetPriority(Token op)
283283
{
284284
return _priority[op];
285-
}
285+
}
286+
287+
public static int GetBinaryPriority(Token op)
288+
{
289+
return IsBinaryOperator(op) ? _priority[op] : -1;
290+
}
291+
292+
public static int GetUnaryPriority(Token op)
293+
{
294+
return op switch
295+
{
296+
Token.OpenPar => MAX_OPERATION_PRIORITY + 1,
297+
298+
Token.Not => _priority[op],
299+
Token.UnaryMinus => _priority[op],
300+
Token.UnaryPlus => _priority[op],
301+
302+
Token.Minus => _priority[Token.UnaryMinus],
303+
Token.Plus => _priority[Token.UnaryPlus],
304+
305+
_ => MAX_OPERATION_PRIORITY
306+
};
307+
}
308+
309+
286310

287311
[MethodImpl(MethodImplOptions.AggressiveInlining)]
288312
public static bool IsBuiltInFunction(Token token)

src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs

Lines changed: 65 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,8 @@ private void BuildMethodBody()
389389
finally
390390
{
391391
PopContext();
392-
}
393-
392+
}
393+
394394
CreateChild(CurrentParent, NodeKind.BlockEnd, _lastExtractedLexem);
395395
NextLexem();
396396
}
@@ -1237,130 +1237,68 @@ private BslSyntaxNode BuildExpression(NonTerminalNode parent, Token stopToken)
12371237
return default;
12381238
}
12391239

1240-
var op = BuildOrExpression();
1240+
var op = BuildExpression(0);
12411241
parent.AddChild(op);
12421242
return op;
12431243
}
1244-
1245-
private BslSyntaxNode BuildOrExpression()
1246-
{
1247-
var firstArg = BuildAndExpression();
1248-
while (_lastExtractedLexem.Token == Token.Or)
1249-
{
1250-
var operationLexem = _lastExtractedLexem;
1251-
NextLexem();
1252-
var secondArg = BuildAndExpression();
1253-
firstArg = MakeBinaryOperationNode(firstArg, secondArg, operationLexem);
1254-
}
12551244

1256-
return firstArg;
1257-
}
1258-
1259-
private BslSyntaxNode BuildAndExpression()
1245+
private BslSyntaxNode BuildExpression(int prio)
12601246
{
1261-
var firstArg = BuildNotExpression();
1262-
while (_lastExtractedLexem.Token == Token.And)
1247+
var firstArg = BuildPrimaryExpression();
1248+
while (LanguageDef.GetBinaryPriority(_lastExtractedLexem.Token) > prio)
12631249
{
12641250
var operationLexem = _lastExtractedLexem;
12651251
NextLexem();
1266-
var secondArg = BuildNotExpression();
1267-
firstArg = MakeBinaryOperationNode(firstArg, secondArg, operationLexem);
1268-
}
1252+
var secondArg = BuildExpression(LanguageDef.GetBinaryPriority(operationLexem.Token));
12691253

1270-
return firstArg;
1271-
}
1272-
1273-
private BslSyntaxNode BuildNotExpression()
1274-
{
1275-
if (_lastExtractedLexem.Token == Token.Not)
1276-
{
1277-
var operation = _lastExtractedLexem;
1278-
NextLexem();
1279-
var op = new UnaryOperationNode(operation);
1280-
var argument = BuildLogicalComparison();
1281-
op.AddChild(argument);
1282-
return op;
1283-
}
1284-
1285-
return BuildLogicalComparison();
1286-
}
1287-
1288-
private BslSyntaxNode BuildLogicalComparison()
1289-
{
1290-
var firstArg = BuildAdditionExpression();
1291-
while (_lastExtractedLexem.Token == Token.Equal ||
1292-
_lastExtractedLexem.Token == Token.MoreThan ||
1293-
_lastExtractedLexem.Token == Token.LessThan ||
1294-
_lastExtractedLexem.Token == Token.MoreOrEqual ||
1295-
_lastExtractedLexem.Token == Token.LessOrEqual ||
1296-
_lastExtractedLexem.Token == Token.NotEqual)
1297-
{
1298-
var operationLexem = _lastExtractedLexem;
1299-
NextLexem();
1300-
var secondArg = BuildAdditionExpression();
13011254
firstArg = MakeBinaryOperationNode(firstArg, secondArg, operationLexem);
13021255
}
13031256

13041257
return firstArg;
1305-
}
1306-
1307-
private BslSyntaxNode BuildAdditionExpression()
1258+
}
1259+
1260+
private BslSyntaxNode BuildPrimaryExpression()
13081261
{
1309-
var firstArg = BuildMultiplyExpression();
1310-
while (_lastExtractedLexem.Token == Token.Plus ||
1311-
_lastExtractedLexem.Token == Token.Minus)
1312-
{
1313-
var operationLexem = _lastExtractedLexem;
1314-
NextLexem();
1315-
var secondArg = BuildMultiplyExpression();
1316-
firstArg = MakeBinaryOperationNode(firstArg, secondArg, operationLexem);
1317-
}
1318-
1319-
return firstArg;
1320-
}
1321-
1322-
private BslSyntaxNode BuildMultiplyExpression()
1323-
{
1324-
var firstArg = BuildUnaryMathExpression();
1325-
while (_lastExtractedLexem.Token == Token.Multiply ||
1326-
_lastExtractedLexem.Token == Token.Division ||
1327-
_lastExtractedLexem.Token == Token.Modulo)
1328-
{
1329-
var operationLexem = _lastExtractedLexem;
1330-
NextLexem();
1331-
var secondArg = BuildUnaryMathExpression();
1332-
firstArg = MakeBinaryOperationNode(firstArg, secondArg, operationLexem);
1333-
}
1334-
1335-
return firstArg;
1336-
}
1337-
1338-
private BslSyntaxNode BuildUnaryMathExpression()
1339-
{
1340-
if (_lastExtractedLexem.Token == Token.Plus)
1341-
_lastExtractedLexem.Token = Token.UnaryPlus;
1342-
else if (_lastExtractedLexem.Token == Token.Minus)
1343-
_lastExtractedLexem.Token = Token.UnaryMinus;
1344-
else
1345-
return BuildParenthesis();
1346-
1347-
// Можно оптимизировать численный литерал до константы
1348-
var operation = _lastExtractedLexem;
1349-
NextLexem();
1350-
if (_lastExtractedLexem.Type == LexemType.NumberLiteral)
1351-
{
1352-
if (operation.Token == Token.UnaryMinus)
1353-
_lastExtractedLexem.Content = '-' + _lastExtractedLexem.Content;
1354-
1355-
return TerminalNode();
1356-
}
1357-
1358-
var op = new UnaryOperationNode(operation);
1359-
var argument = BuildParenthesis();
1360-
op.AddChild(argument);
1361-
return op;
1362-
}
1363-
1262+
if (_lastExtractedLexem.Token == Token.OpenPar)
1263+
{
1264+
return BuildParenthesis();
1265+
}
1266+
1267+
var operation = _lastExtractedLexem;
1268+
var prio = LanguageDef.GetUnaryPriority(operation.Token);
1269+
1270+
if (prio == LanguageDef.MAX_OPERATION_PRIORITY)
1271+
{
1272+
return TerminalNode();
1273+
}
1274+
1275+
NextLexem();
1276+
1277+
if (operation.Token == Token.Plus)
1278+
operation.Token = Token.UnaryPlus;
1279+
else if (operation.Token == Token.Minus)
1280+
{
1281+
operation.Token = Token.UnaryMinus;
1282+
if (_lastExtractedLexem.Type == LexemType.NumberLiteral) //TODO:move it to lexer
1283+
{
1284+
_lastExtractedLexem.Content = '-' + _lastExtractedLexem.Content;
1285+
return TerminalNode();
1286+
}
1287+
}
1288+
1289+
if (LanguageDef.GetUnaryPriority(_lastExtractedLexem.Token) <= prio)
1290+
{
1291+
AddError(LocalizedErrors.ExpressionSyntax());
1292+
return default;
1293+
}
1294+
1295+
var arg = BuildExpression(prio);
1296+
var op = new UnaryOperationNode(operation);
1297+
op.AddChild(arg);
1298+
return op;
1299+
}
1300+
1301+
13641302
private BslSyntaxNode BuildExpressionUpTo(NonTerminalNode parent, Token stopToken)
13651303
{
13661304
var node = BuildExpression(parent, stopToken);
@@ -1392,36 +1330,31 @@ private void BuildOptionalExpression(NonTerminalNode parent, Token stopToken)
13921330
return;
13931331
}
13941332

1395-
var op = BuildOrExpression();
1333+
var op = BuildExpression(0);
13961334
parent.AddChild(op);
13971335
}
13981336

13991337
#region Operators
14001338

1401-
private static BslSyntaxNode MakeBinaryOperationNode(BslSyntaxNode firstArg, BslSyntaxNode secondArg, in Lexem lexem)
1339+
private static BinaryOperationNode MakeBinaryOperationNode(BslSyntaxNode firstArg, BslSyntaxNode secondArg, in Lexem lexem)
14021340
{
14031341
var node = new BinaryOperationNode(lexem);
14041342
node.AddChild(firstArg);
14051343
node.AddChild(secondArg);
14061344
return node;
1407-
}
1408-
1345+
}
1346+
14091347
private BslSyntaxNode BuildParenthesis()
1410-
{
1411-
if (_lastExtractedLexem.Token == Token.OpenPar)
1412-
{
1413-
NextLexem();
1414-
var expr = BuildOrExpression();
1415-
if (_lastExtractedLexem.Token != Token.ClosePar)
1416-
{
1417-
AddError(LocalizedErrors.TokenExpected(Token.ClosePar));
1418-
}
1419-
NextLexem();
1420-
1421-
return BuildDereference(expr);
1422-
}
1423-
1424-
return TerminalNode();
1348+
{
1349+
NextLexem();
1350+
var expr = BuildExpression(0);
1351+
if (_lastExtractedLexem.Token != Token.ClosePar)
1352+
{
1353+
AddError(LocalizedErrors.TokenExpected(Token.ClosePar));
1354+
}
1355+
NextLexem();
1356+
1357+
return BuildDereference(expr);
14251358
}
14261359

14271360
#endregion
@@ -1676,7 +1609,7 @@ private Token[] PopStructureToken()
16761609
return tok;
16771610
}
16781611

1679-
private BslSyntaxNode CreateChild(NonTerminalNode parent, NodeKind kind, in Lexem lex)
1612+
private static BslSyntaxNode CreateChild(NonTerminalNode parent, NodeKind kind, in Lexem lex)
16801613
{
16811614
var child = NodeBuilder.CreateNode(kind, lex);
16821615
parent.AddChild(child);

0 commit comments

Comments
 (0)