| | use nom::{ |
| | branch::alt, |
| | bytes::complete::{tag, take_while1, take_until, take_while}, |
| | character::complete::{alpha1, alphanumeric1, char, digit1, multispace0, multispace1, anychar}, |
| | combinator::{map, map_res, recognize, value, eof, opt}, |
| | multi::many0, |
| | sequence::{delimited, pair, preceded, tuple}, |
| | IResult, |
| | }; |
| | use crate::compiler::lexer::Token; |
| | use std::str::FromStr; |
| |
|
| | pub struct Lexer; |
| |
|
| | impl Lexer { |
| | pub fn tokenize(input: &str) -> IResult<&str, Vec<Token>> { |
| | many0(preceded( |
| | |
| | alt(( |
| | multispace1, |
| | |
| | recognize(pair(tag("//"), take_while(|c| c != '\n' && c != '\r'))), |
| | |
| | recognize(delimited(tag("/*"), take_until("*/"), tag("*/"))), |
| | )), |
| | |
| | alt(( |
| | |
| | Self::parse_keyword, |
| | |
| | |
| | Self::parse_double_literal, |
| | Self::parse_int_literal, |
| | Self::parse_string_literal, |
| | Self::parse_bool_literal, |
| | |
| | |
| | Self::parse_identifier, |
| | |
| | |
| | Self::parse_operator, |
| | Self::parse_punctuation, |
| | )) |
| | ))(input) |
| | } |
| |
|
| | fn parse_keyword(input: &str) -> IResult<&str, Token> { |
| | alt(( |
| | value(Token::Int, tag("int")), |
| | value(Token::Double, tag("double")), |
| | value(Token::String, tag("string")), |
| | value(Token::Bool, tag("bool")), |
| | value(Token::Void, tag("void")), |
| | value(Token::Input, tag("input")), |
| | value(Token::If, tag("if")), |
| | value(Token::Else, tag("else")), |
| | value(Token::For, tag("for")), |
| | value(Token::While, tag("while")), |
| | value(Token::Return, tag("return")), |
| | value(Token::MqlTick, tag("MqlTick")), |
| | value(Token::MqlRates, tag("MqlRates")), |
| | ))(input) |
| | } |
| | |
| | fn parse_bool_literal(input: &str) -> IResult<&str, Token> { |
| | alt(( |
| | value(Token::BoolLiteral(true), tag("true")), |
| | value(Token::BoolLiteral(false), tag("false")), |
| | ))(input) |
| | } |
| |
|
| | fn parse_identifier(input: &str) -> IResult<&str, Token> { |
| | map( |
| | recognize(pair( |
| | alt((alpha1, tag("_"))), |
| | take_while(|c: char| c.is_alphanumeric() || c == '_') |
| | )), |
| | |s: &str| Token::Identifier(s.to_string()) |
| | )(input) |
| | } |
| |
|
| | fn parse_int_literal(input: &str) -> IResult<&str, Token> { |
| | map_res(digit1, |s: &str| s.parse::<i64>().map(Token::IntLiteral))(input) |
| | } |
| |
|
| | fn parse_double_literal(input: &str) -> IResult<&str, Token> { |
| | map_res( |
| | recognize(tuple(( |
| | digit1, |
| | char('.'), |
| | digit1 |
| | ))), |
| | |s: &str| s.parse::<f64>().map(Token::DoubleLiteral) |
| | )(input) |
| | } |
| |
|
| | fn parse_string_literal(input: &str) -> IResult<&str, Token> { |
| | map( |
| | delimited(char('"'), take_while(|c| c != '"'), char('"')), |
| | |s: &str| Token::StringLiteral(s.to_string()) |
| | )(input) |
| | } |
| |
|
| | fn parse_operator(input: &str) -> IResult<&str, Token> { |
| | alt(( |
| | value(Token::Equals, tag("==")), |
| | value(Token::NotEquals, tag("!=")), |
| | value(Token::GreaterEq, tag(">=")), |
| | value(Token::LessEq, tag("<=")), |
| | value(Token::And, tag("&&")), |
| | value(Token::Or, tag("||")), |
| | value(Token::Assign, tag("=")), |
| | value(Token::Greater, tag(">")), |
| | value(Token::Less, tag("<")), |
| | value(Token::Plus, tag("+")), |
| | value(Token::Minus, tag("-")), |
| | value(Token::Star, tag("*")), |
| | value(Token::Slash, tag("/")), |
| | value(Token::Not, tag("!")), |
| | ))(input) |
| | } |
| | |
| | fn parse_punctuation(input: &str) -> IResult<&str, Token> { |
| | alt(( |
| | value(Token::OpenParen, tag("(")), |
| | value(Token::CloseParen, tag(")")), |
| | value(Token::OpenBrace, tag("{")), |
| | value(Token::CloseBrace, tag("}")), |
| | value(Token::OpenBracket, tag("[")), |
| | value(Token::CloseBracket, tag("]")), |
| | value(Token::Comma, tag(",")), |
| | value(Token::Semicolon, tag(";")), |
| | value(Token::Dot, tag(".")), |
| | ))(input) |
| | } |
| | } |
| |
|