public void ParseEqualityExpression() { var expression = "not a and b >= c"; var lexer = new Lexer(expression); var parser = new RilaParser(lexer); var ast = parser.ParseExpression(); Assert.IsType <BinaryOperatorExpression>(ast); var and = ast as BinaryOperatorExpression; Assert.True(and.Operation == TokenType.And); Assert.IsType <PrefixOperatorExpression>(and.Lhs); var not = and.Lhs as PrefixOperatorExpression; Assert.True(not.Operation == TokenType.Not); Assert.IsType <IdentifierExpression>(not.Rhs); var a = not.Rhs as IdentifierExpression; Assert.True(a.Name == "a"); Assert.IsType <BinaryOperatorExpression>(and.Rhs); var eqGt = and.Rhs as BinaryOperatorExpression; Assert.True(eqGt.Operation == TokenType.EqGreaterThan); Assert.IsType <IdentifierExpression>(eqGt.Lhs); var b = eqGt.Lhs as IdentifierExpression; Assert.True(b.Name == "b"); Assert.IsType <IdentifierExpression>(eqGt.Rhs); var c = eqGt.Rhs as IdentifierExpression; Assert.True(c.Name == "c"); }
public void ParseFunctionDefinition() { var program = File.ReadAllText("TestPrograms/Parser/function.rila"); var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 3); var noArgsFun = ast.Statements.First() as FunctionDefinition; Assert.True(noArgsFun.Name == "noArgs"); Assert.True(noArgsFun.Parameters.Count == 0); Assert.True(noArgsFun.Body.Statements.Count == 1); var oneArgFun = ast.Statements.ElementAt(1) as FunctionDefinition; Assert.True(oneArgFun.Name == "oneArg"); Assert.True(oneArgFun.Parameters.Count == 1); Assert.True(oneArgFun.Body.Statements.Count == 1); Assert.IsType <ReturnStatement>(oneArgFun.Body.Statements.First()); var multiArgsFun = ast.Statements.ElementAt(2) as FunctionDefinition; Assert.True(multiArgsFun.Name == "multiArgs"); Assert.True(multiArgsFun.Parameters.Count == 3); Assert.True(multiArgsFun.Body.Statements.Count == 1); Assert.IsType <IfStatement>(multiArgsFun.Body.Statements.First()); }
public void ParseMultAndPlusPrecedenceExpression() { var expression = "a * (b + c)"; var lexer = new Lexer(expression); var parser = new RilaParser(lexer); var ast = parser.ParseExpression(); Assert.IsType <BinaryOperatorExpression>(ast); var op = ast as BinaryOperatorExpression; Assert.True(op.Operation == TokenType.Asterisk); Assert.IsType <BinaryOperatorExpression>(op.Rhs); var rhs = op.Rhs as BinaryOperatorExpression; Assert.True(rhs.Operation == TokenType.Plus); Assert.IsType <IdentifierExpression>(rhs.Lhs); Assert.True((rhs.Lhs as IdentifierExpression).Name == "b"); Assert.IsType <IdentifierExpression>(rhs.Rhs); Assert.True((rhs.Rhs as IdentifierExpression).Name == "c"); Assert.IsType <IdentifierExpression>(op.Lhs); Assert.True((op.Lhs as IdentifierExpression).Name == "a"); }
public void ParseAssignmentStatement() { var statement = "a = a + 1"; var lexer = new Lexer(statement); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 1); var first = ast.Statements.First(); Assert.IsType <AssignmentStatement>(first); var assign = first as AssignmentStatement; Assert.IsType <IdentifierExpression>(assign.Target); var assignTarget = assign.Target as IdentifierExpression; Assert.True(assignTarget.Name == "a"); Assert.IsType <BinaryOperatorExpression>(assign.Expression); var plus = assign.Expression as BinaryOperatorExpression; Assert.True(plus.Operation == TokenType.Plus); Assert.IsType <IdentifierExpression>(plus.Lhs); Assert.True((plus.Lhs as IdentifierExpression).Name == "a"); Assert.IsType <NumberExpression>(plus.Rhs); Assert.True((plus.Rhs as NumberExpression).Value == 1); }
public Expression Parse(RilaParser parser, Token token) { var expression = parser.ParseExpression(); parser.Expect(out Token match, TokenType.RParen); return(expression); }
public void ParseIfStatements() { var program = File.ReadAllText("TestPrograms/Parser/if.rila"); var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 1); Assert.IsType <IfStatement>(ast.Statements.First()); var ifStmt = ast.Statements.First() as IfStatement; Assert.True(ifStmt.Branches.Count == 3); var first = ifStmt.Branches.First(); Assert.IsType <BinaryOperatorExpression>(first.Condition); Assert.True(first.Block.Statements.Count == 3); Assert.IsType <AssignmentStatement>(first.Block.Statements.First()); Assert.IsType <AssignmentStatement>(first.Block.Statements.ElementAt(1)); Assert.IsType <IfStatement>(first.Block.Statements.ElementAt(2)); var firstNestedIf = first.Block.Statements.ElementAt(2) as IfStatement; Assert.True(firstNestedIf.Branches.Count == 1); Assert.IsType <BinaryOperatorExpression>(firstNestedIf.Branches.First().Condition); Assert.IsType <AssignmentStatement>(firstNestedIf.Branches.First().Block.Statements.First()); var second = ifStmt.Branches.ElementAt(1); Assert.IsType <BoolExpression>(second.Condition); Assert.True(second.Block.Statements.Count == 1); Assert.IsType <AssignmentStatement>(second.Block.Statements.First()); var third = ifStmt.Branches.ElementAt(2); Assert.IsType <BoolExpression>(third.Condition); Assert.True(third.Block.Statements.Count == 1); Assert.IsType <IfStatement>(third.Block.Statements.First()); var thirdNestedIf = third.Block.Statements.First() as IfStatement; Assert.True(thirdNestedIf.Branches.Count == 2); Assert.True(thirdNestedIf.ElseBranch == null); Assert.IsType <BoolExpression>(thirdNestedIf.Branches.First().Condition); Assert.True(thirdNestedIf.Branches.First().Block.Statements.Count == 1); Assert.IsType <AssignmentStatement>(thirdNestedIf.Branches.First().Block.Statements.First()); Assert.IsType <BoolExpression>(thirdNestedIf.Branches.ElementAt(1).Condition); Assert.True(thirdNestedIf.Branches.ElementAt(1).Block.Statements.Count == 1); Assert.IsType <AssignmentStatement>(thirdNestedIf.Branches.ElementAt(1).Block.Statements.First()); Assert.True(ifStmt.ElseBranch != null); Assert.True(ifStmt.ElseBranch.Statements.Count == 1); Assert.IsType <AssignmentStatement>(ifStmt.ElseBranch.Statements.First()); }
public void ParseIndexerExpression() { var program = "a = arr[0]\nb = arr[myVar, otherParam]\nc = a + b + arr[a - b]"; var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count(x => x is AssignmentStatement) == 3); var a = ast.Statements.First() as AssignmentStatement; Assert.IsType <IndexerExpression>(a.Expression); var aIndexer = a.Expression as IndexerExpression; Assert.IsType <IdentifierExpression>(aIndexer.Identifier); var arr = aIndexer.Identifier as IdentifierExpression; Assert.True(arr.Name == "arr"); Assert.True(aIndexer.Parameters.Count == 1); Assert.IsType <NumberExpression>(aIndexer.Parameters.First()); var b = ast.Statements.ElementAt(1) as AssignmentStatement; Assert.IsType <IndexerExpression>(b.Expression); var bIndexer = b.Expression as IndexerExpression; Assert.IsType <IdentifierExpression>(bIndexer.Identifier); var arrB = bIndexer.Identifier as IdentifierExpression; Assert.True(arrB.Name == "arr"); Assert.True(bIndexer.Parameters.Count == 2); Assert.IsType <IdentifierExpression>(bIndexer.Parameters.First()); Assert.IsType <IdentifierExpression>(bIndexer.Parameters.ElementAt(1)); var c = ast.Statements.ElementAt(2) as AssignmentStatement; Assert.IsType <BinaryOperatorExpression>(c.Expression); Assert.IsType <BinaryOperatorExpression>((c.Expression as BinaryOperatorExpression).Lhs); Assert.IsType <IndexerExpression>((c.Expression as BinaryOperatorExpression).Rhs); var cIndexer = (c.Expression as BinaryOperatorExpression).Rhs as IndexerExpression; Assert.IsType <IdentifierExpression>(cIndexer.Identifier); var arrC = cIndexer.Identifier as IdentifierExpression; Assert.True(arrC.Name == "arr"); Assert.True(cIndexer.Parameters.Count == 1); Assert.IsType <BinaryOperatorExpression>(cIndexer.Parameters.First()); }
public Expression Parse(RilaParser parser, Token token) { if (token.TokenType == TokenType.At) { token = parser.Consume(); if (token.TokenType != TokenType.Identifier) { parser.AppendError($"Expecting a cell variable identifier. Got: \"{token.Content}\"", token); } } return(new IdentifierExpression(token.Content)); }
public void ParseForLoop() { var program = File.ReadAllText("TestPrograms/Parser/for.rila"); var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 2); Assert.IsType <ForLoopStatement>(ast.Statements.First()); var forLoop = ast.Statements.First() as ForLoopStatement; Assert.True(forLoop.VariableName == "i"); Assert.IsType <RangeExpression>(forLoop.InExpression); var forExpression = forLoop.InExpression as RangeExpression; Assert.IsType <NumberExpression>(forExpression.Start); Assert.True((forExpression.Start as NumberExpression).Value == 0); Assert.IsType <NumberExpression>(forExpression.End); Assert.True((forExpression.End as NumberExpression).Value == 100); Assert.True(forLoop.Block.Statements.Count == 1); Assert.IsType <IfStatement>(forLoop.Block.Statements.First()); var ifStmt = forLoop.Block.Statements.First() as IfStatement; Assert.True(ifStmt.Branches.Count == 1); Assert.IsType <ForLoopStatement>(ifStmt.Branches.First().Block.Statements.First()); var nestedFor = ifStmt.Branches.First().Block.Statements.First() as ForLoopStatement; Assert.True(nestedFor.VariableName == "j"); Assert.IsType <RangeExpression>(nestedFor.InExpression); var nestedForExpression = nestedFor.InExpression as RangeExpression; Assert.IsType <NumberExpression>(nestedForExpression.Start); Assert.True((nestedForExpression.Start as NumberExpression).Value == 0); Assert.IsType <IdentifierExpression>(nestedForExpression.End); Assert.True((nestedForExpression.End as IdentifierExpression).Name == "i"); Assert.True(nestedFor.Block.Statements.Count == 2); Assert.IsType <DotExpression>(nestedFor.Block.Statements.First()); Assert.IsType <DotExpression>(nestedFor.Block.Statements.ElementAt(1)); Assert.True(ifStmt.ElseBranch.Statements.Count == 1); Assert.IsType <ContinueStatement>(ifStmt.ElseBranch.Statements.First()); Assert.IsType <AssignmentStatement>(ast.Statements.ElementAt(1)); }
public void ParseWhileLoop() { var program = File.ReadAllText("TestPrograms/Parser/while.rila"); var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 2); Assert.IsType <WhileLoopStatement>(ast.Statements.First()); var whileLoop = ast.Statements.First() as WhileLoopStatement; Assert.IsType <BinaryOperatorExpression>(whileLoop.Condition); var condition = whileLoop.Condition as BinaryOperatorExpression; Assert.IsType <IdentifierExpression>(condition.Lhs); Assert.True((condition.Lhs as IdentifierExpression).Name == "i"); Assert.IsType <NumberExpression>(condition.Rhs); Assert.True((condition.Rhs as NumberExpression).Value == 100); Assert.True(condition.Operation == TokenType.GreaterThan); Assert.True(whileLoop.Block.Statements.Count == 1); Assert.IsType <IfStatement>(whileLoop.Block.Statements.First()); var ifStmt = whileLoop.Block.Statements.First() as IfStatement; Assert.True(ifStmt.Branches.Count == 1); Assert.IsType <ForLoopStatement>(ifStmt.Branches.First().Block.Statements.First()); var nestedFor = ifStmt.Branches.First().Block.Statements.First() as ForLoopStatement; Assert.True(nestedFor.VariableName == "j"); Assert.IsType <RangeExpression>(nestedFor.InExpression); var nestedForExpression = nestedFor.InExpression as RangeExpression; Assert.IsType <NumberExpression>(nestedForExpression.Start); Assert.True((nestedForExpression.Start as NumberExpression).Value == 0); Assert.IsType <IdentifierExpression>(nestedForExpression.End); Assert.True((nestedForExpression.End as IdentifierExpression).Name == "i"); Assert.True(nestedFor.Block.Statements.Count == 2); Assert.IsType <DotExpression>(nestedFor.Block.Statements.First()); Assert.IsType <DotExpression>(nestedFor.Block.Statements.ElementAt(1)); Assert.True(ifStmt.ElseBranch.Statements.Count == 1); Assert.IsType <ContinueStatement>(ifStmt.ElseBranch.Statements.First()); Assert.IsType <AssignmentStatement>(ast.Statements.ElementAt(1)); }
public Expression Parse(RilaParser parser, Token token, Expression lhs) { var args = new List <Expression>(); if (!parser.ConsumeIf(TokenType.RParen)) { do { args.Add(parser.ParseExpression()); }while (parser.ConsumeIf(TokenType.Comma)); parser.Expect(out Token match, TokenType.RParen); } return(new CallExpression(lhs, args)); }
public override ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink) { try { var lexer = new Lexer(sourceUnit.GetReader().ReadToEnd()); var program = new RilaParser(lexer).Parse().ConstructProgram(rila); return(new RilaScriptCode(program.Compile(), rila, sourceUnit)); } catch (Exception e) { errorSink.Add(sourceUnit, e.Message, SourceSpan.None, 0, Severity.FatalError); } return(null); }
public void ParseFunctionCall() { var program = File.ReadAllText("TestPrograms/Parser/function-call.rila"); var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 3); Assert.IsType <AssignmentStatement>(ast.Statements.First()); var assign = ast.Statements.First() as AssignmentStatement; Assert.IsType <CallExpression>(assign.Expression); var call = assign.Expression as CallExpression; Assert.IsType <IdentifierExpression>(call.Function); Assert.True((call.Function as IdentifierExpression).Name == "myFun"); Assert.True(call.Arguments.Count == 4); Assert.IsType <NumberExpression>(call.Arguments.First()); Assert.IsType <BinaryOperatorExpression>(call.Arguments.ElementAt(1)); Assert.IsType <CallExpression>(call.Arguments.ElementAt(2)); var nestedCall = call.Arguments.ElementAt(2) as CallExpression; Assert.IsType <IdentifierExpression>(nestedCall.Function); Assert.True((nestedCall.Function as IdentifierExpression).Name == "funCall"); Assert.True(nestedCall.Arguments.Count == 1); Assert.IsType <NumberExpression>(nestedCall.Arguments.First()); Assert.IsType <IdentifierExpression>(call.Arguments.ElementAt(3)); Assert.IsType <CallExpression>(ast.Statements.ElementAt(1)); var secondCall = ast.Statements.ElementAt(1) as CallExpression; Assert.True(secondCall.Arguments.Count == 0); Assert.IsType <IdentifierExpression>(secondCall.Function); Assert.True((secondCall.Function as IdentifierExpression).Name == "result"); Assert.IsType <CallExpression>(ast.Statements.ElementAt(2)); var thirdCall = ast.Statements.ElementAt(2) as CallExpression; Assert.True(thirdCall.Arguments.Count == 1); Assert.IsType <BinaryOperatorExpression>(thirdCall.Arguments.First()); Assert.IsType <IdentifierExpression>(thirdCall.Function); Assert.True((thirdCall.Function as IdentifierExpression).Name == "oneMore"); }
public Expression Parse(RilaParser parser, Token token) { var distance = 0; var next = parser.Peek(distance); var cellNames = new List <string>(); while (true) { if (next.TokenType == TokenType.EOF) { parser.AppendError("Missing closing \"}\".", next); break; } if (next.TokenType == TokenType.RCurly) { break; } if (next.TokenType == TokenType.At) { var identifier = parser.Peek(++distance); if (identifier.TokenType != TokenType.Identifier) { parser.AppendError($"Expecting a cell variable identifier. Got: \"{identifier.Content}\"", identifier); continue; } cellNames.Add(identifier.Content); } next = parser.Peek(++distance); } var expression = parser.ParseExpression(); parser.Expect(out Token _, TokenType.RCurly); return(new SignalExpression(expression, cellNames)); }
public Expression Parse(RilaParser parser, Token token, Expression lhs) { var expressions = new List <Expression>() { lhs }; do { expressions.Add(parser.ParseExpression(Precedence)); }while (parser.ConsumeIf(TokenType.Dot)); if (parser.ConsumeIf(TokenType.Assign)) { expressions.Add(parser.ParseExpression()); return(new DotExpression(expressions, true)); } return(new DotExpression(expressions, false)); }
public Expression Parse(RilaParser parser, Token token) { var args = new List <Expression>(); var expression = parser.ParseExpression(); if (expression is DotExpression dot) { var call = dot.Expressions.Last() as CallExpression; var ctor = call.Function as IdentifierExpression; if (call is null) { parser.AppendError("Expecting a constructor call!", token); } var namespaces = dot.Expressions.ToList().GetRange(0, dot.Expressions.Count - 1).Select(x => x as IdentifierExpression).ToList(); namespaces.Add(ctor); if (namespaces.Any(x => x is null)) { parser.AppendError("Expecting namespace definition!", token); } return(new NewExpression(string.Join(".", namespaces.Select(x => x.Name)), call.Arguments)); } else if (expression is CallExpression call) { var identifier = call.Function as IdentifierExpression; if (identifier is null) { parser.AppendError("Expecting a constructor call!", token); } return(new NewExpression(identifier.Name, call.Arguments)); } return(null); }
public void ParseFieldAccess() { var program = File.ReadAllText("TestPrograms/Parser/field-access.rila"); var lexer = new Lexer(program); var parser = new RilaParser(lexer); var ast = parser.Parse(); Assert.True(ast.Statements.Count == 2); Assert.IsType <CallExpression>(ast.Statements.First()); var first = ast.Statements.First() as CallExpression; Assert.IsType <IdentifierExpression>(first.Function); Assert.True(first.Arguments.Count == 1); Assert.IsType <DotExpression>(first.Arguments.First()); var arg = first.Arguments.First() as DotExpression; Assert.IsType <IdentifierExpression>(arg.Expressions.First()); Assert.IsType <CallExpression>(arg.Expressions.ElementAt(1)); Assert.IsType <IdentifierExpression>(arg.Expressions.ElementAt(2)); Assert.IsType <AssignmentStatement>(ast.Statements.ElementAt(1)); var assign = ast.Statements.ElementAt(1) as AssignmentStatement; Assert.IsType <IdentifierExpression>(assign.Target); var assignTarget = assign.Target as IdentifierExpression; Assert.True(assignTarget.Name == "myVar"); Assert.IsType <DotExpression>(assign.Expression); var assignFieldAccess = assign.Expression as DotExpression; Assert.IsType <IdentifierExpression>(assignFieldAccess.Expressions.First()); Assert.IsType <CallExpression>(assignFieldAccess.Expressions.ElementAt(1)); Assert.IsType <IdentifierExpression>(assignFieldAccess.Expressions.ElementAt(2)); Assert.IsType <IdentifierExpression>(assignFieldAccess.Expressions.ElementAt(3)); Assert.IsType <CallExpression>(assignFieldAccess.Expressions.ElementAt(4)); }
public Expression Parse(RilaParser parser, Token token, Expression lhs) { var parameters = new List <Expression>(); if (!parser.ConsumeIf(TokenType.RSquare)) { do { parameters.Add(parser.ParseExpression()); }while (parser.ConsumeIf(TokenType.Comma)); parser.Expect(out Token rSquare, TokenType.RSquare); } if (parser.ConsumeIf(TokenType.Assign)) { parameters.Add(parser.ParseExpression()); return(new IndexerExpression(lhs, parameters, true)); } return(new IndexerExpression(lhs, parameters, false)); }
public Expression Parse(RilaParser parser, Token token) { var rhs = parser.ParseExpression(Precedence); return(new PrefixOperatorExpression(token.TokenType, rhs)); }
public Expression Parse(RilaParser parser, Token token) { return(new StringExpression(token.Content)); }
public Precedence Precedence => Precedence.Equality; //This way we can include nested expressions public Expression Parse(RilaParser parser, Token token, Expression lhs) { var right = parser.ParseExpression(Precedence); return(new RangeExpression(lhs, right)); }
public Expression Parse(RilaParser parser, Token token) { return(new NumberExpression(int.Parse(token.Content))); }
public Expression Parse(RilaParser parser, Token token) { return(new TypeOfExpression(parser.ParseExpression())); }
public Expression Parse(RilaParser parser, Token token, Expression lhs) { var right = parser.ParseExpression(Precedence); return(new BinaryOperatorExpression(lhs, token.TokenType, right)); }
public Expression Parse(RilaParser parser, Token token) { return(new BoolExpression(bool.Parse(token.Content))); }