Implement a lexer that will break the input code into a sequence of tokens, including comments. The lexer should correctly identify all tokens as defined in the language grammar, including:
All keywords.
All constants.
Variables and function names.
All operators.
Parentheses, curly braces, semicolons, and comments.