luaparse 0.2.0

A Lua 5.3 parser
Documentation
//! The symbol tokens.

use std::fmt::{self, Display};

use phf::{phf_map, Map};

macro_rules! define_symbol {
    (lengths = $lengths:expr, $( $group:ident: { $( $string:literal => $name:ident, )+ }, )*) => {
        /// A symbol.
        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
        pub enum Symbol {
            $( $( $name, )+ )*
        }

        /// A symbol group.
        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
        pub enum SymbolGroup {
            $( $group, )*
        }

        impl Symbol {
            pub(crate) const SYMBOLS: Map<&'static str, Self> = phf_map! {
                $( $($string => Self::$name,)+ )*
            };

            /// Attempts to parse the beginning of the string as a symbol.
            ///
            /// Returns `Some((symbol, byte_length))` if succeeds, or `None`.
            pub fn parse(input: &str) -> Option<(Symbol, usize)> {
                for &len in $lengths.iter().rev() {
                    let symbol = input.get(0..len).and_then(|start| Self::SYMBOLS.get(start));
                    if let Some(&v) = symbol {
                        return Some((v, len));
                    }
                }
                None
            }

            /// Returns the string associated with the symbol.
            pub fn as_str(self) -> &'static str {
                match self {
                    $( $( Self::$name => $string, )+ )*
                }
            }

            /// Returns the symbol group.
            pub fn group(self) -> SymbolGroup {
                match self {
                    $(
                        $( Self::$name => SymbolGroup::$group, )+
                    )*
                }
            }
        }

        impl Display for Symbol {
            fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(formatter, "`{}`", self.as_str())
            }
        }
    }
}

define_symbol! {
    lengths = [1, 2, 3, 4, 5, 6, 8],

    // operators
    Operator: {
        "+" => Add,
        "-" => Sub,
        "*" => Mul,
        "/" => Div,
        "%" => Rem,
        "^" => Pow,
        "#" => Len,
        "&" => BitAnd,
        "~" => BitXor,
        "|" => BitOr,
        "<" => Less,
        ">" => Greater,
        "=" => Assign,
        "(" => RoundBracketLeft,
        ")" => RoundBracketRight,
        "{" => CurlyBracketLeft,
        "}" => CurlyBracketRight,
        "[" => SquareBracketLeft,
        "]" => SquareBracketRight,
        ":" => Colon,
        ";" => Semicolon,
        "," => Comma,
        "." => Period,
        "<<" => ShiftLeft,
        ">>" => ShiftRight,
        "//" => IntDiv,
        "==" => Equal,
        "~=" => NotEqual,
        "<=" => LessEqual,
        ">=" => GreaterEqual,
        "::" => DoubleColon,
        ".." => DoublePeriod,
        "..." => TriplePeriod,
    },

    // keywords
    Keyword: {
        "do" => Do,
        "if" => If,
        "in" => In,
        "or" => Or,
        "and" => And,
        "end" => End,
        "for" => For,
        "not" => Not,
        "else" => Else,
        "goto" => Goto,
        "then" => Then,
        "break" => Break,
        "local" => Local,
        "until" => Until,
        "while" => While,
        "elseif" => ElseIf,
        "repeat" => Repeat,
        "return" => Return,
        "function" => Function,
    },

    Value: {
        "nil" => Nil,
        "false" => False,
        "true" => True,
    },
}