using CanonSharp.Pascal.Scanner; using CanonSharp.Tests.Utils; namespace CanonSharp.Tests.ScannerTests; public class LexicalParserTests : LexicalTestBase { [Fact] public void LexicalParserTest1() { const string pascalProgram = """ program HelloWorld; var message: char; begin message := 'h'; writeln(message); end. """; ValidateLexicalTokens(LexicalScanner.PascalParser(), pascalProgram, [ (LexicalTokenType.Keyword, "program"), (LexicalTokenType.Identifier, "HelloWorld"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "var"), (LexicalTokenType.Identifier, "message"), (LexicalTokenType.Delimiter, ":"), (LexicalTokenType.Keyword, "char"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "begin"), (LexicalTokenType.Identifier, "message"), (LexicalTokenType.Operator, ":="), (LexicalTokenType.Character, "h"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Identifier, "writeln"), (LexicalTokenType.Delimiter, "("), (LexicalTokenType.Identifier, "message"), (LexicalTokenType.Delimiter, ")"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "end"), (LexicalTokenType.Delimiter, ".") ]); } [Fact] public void LexicalParserTest2() { const string program = """ program main; var ab: integer; begin ab := 3; write(ab); end. """; ValidateLexicalTokens(LexicalScanner.PascalParser(), program, [ (LexicalTokenType.Keyword, "program"), (LexicalTokenType.Identifier, "main"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "var"), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Delimiter, ":"), (LexicalTokenType.Keyword, "integer"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "begin"), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Operator, ":="), (LexicalTokenType.ConstInteger, "3"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Identifier, "write"), (LexicalTokenType.Delimiter, "("), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Delimiter, ")"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "end"), (LexicalTokenType.Delimiter, ".") ]); } [Fact] public void LexicalParserTest3() { const string pascalProgram = """ {test} program main; var ab, ba: integer; begin ab := 3; ba := 5; ab := 5; write(ab + ba); end. """; ValidateLexicalTokens(LexicalScanner.PascalParser(), pascalProgram, [ (LexicalTokenType.Keyword, "program"), (LexicalTokenType.Identifier, "main"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "var"), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Delimiter, ","), (LexicalTokenType.Identifier, "ba"), (LexicalTokenType.Delimiter, ":"), (LexicalTokenType.Keyword, "integer"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "begin"), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Operator, ":="), (LexicalTokenType.ConstInteger, "3"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Identifier, "ba"), (LexicalTokenType.Operator, ":="), (LexicalTokenType.ConstInteger, "5"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Operator, ":="), (LexicalTokenType.ConstInteger, "5"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Identifier, "write"), (LexicalTokenType.Delimiter, "("), (LexicalTokenType.Identifier, "ab"), (LexicalTokenType.Operator, "+"), (LexicalTokenType.Identifier, "ba"), (LexicalTokenType.Delimiter, ")"), (LexicalTokenType.Delimiter, ";"), (LexicalTokenType.Keyword, "end"), (LexicalTokenType.Delimiter, ".") ]); } [Fact] public void LexicalParserTest4() { ValidateLexicalTokens(LexicalScanner.PascalParser(), "array [0..9] of integer", [ (LexicalTokenType.Keyword, "array"), (LexicalTokenType.Delimiter, "["), (LexicalTokenType.ConstInteger, "0"), (LexicalTokenType.Delimiter, ".."), (LexicalTokenType.ConstInteger, "9"), (LexicalTokenType.Delimiter, "]"), (LexicalTokenType.Keyword, "of"), (LexicalTokenType.Keyword, "integer") ]); } [Theory] [InlineData(""" program exFunction; var a, b, ret : integer; begin a := 100; b := 200; { calling a function to get max valued } ret := a - b; end. """, 29)] [InlineData(""" { This is a block comment that does closed. } program CommentClosed; """, 3)] [InlineData(""" {} program CommentClosed; """, 3)] public void LexicalParserTest(string input, int count) { LexicalScanner scanner = new(); List tokens = scanner.Tokenize(new StringReadState(input)).ToList(); Assert.Equal(count, tokens.Count); } }