nimly

repository·master·Indexed 41 days ago

https://github.com/loloicci/nimly

A macro-based library for Nim that generates lexers and LALR(1) parsers at compile-time using syntax similar to lex/yacc. It provides the `niml` macro for lexer generation and the `nimy` macro for parser generation, eliminating the need for an external build step.

Tokens
885
Snippets
4
Records
5
Agent score
50%

What's inside nimly

  1. Debug lexer and parser generation

    master

    To inspect debug information during the compilation of lexers and parsers, you can use the conditional symbols nimldebug and nimydebug.

    Compile your code with the following flags:

    nim c -d:nimldebug -d:nimydebug -r <your_file>.nim
    nim c -d:nimldebug -d:nimydebug -r tests/test_readme_example.nim
  2. Troubleshoot 'interpretation requires too many iterations' error

    master

    If you encounter the error interpretation requires too many iterations during compilation, it means the macro expansion is exceeding the compiler's default limits.

    You can resolve this by increasing the limit using the Nim compiler option --maxLoopIterationsVM:N (available since Nim v1.0.6).

  3. Generate a lexer with the niml macro

    master

    The niml macro generates a lexer at compile-time. You provide a type (e.g., a variant or enum) that the lexer will return when a token is matched.

    Usage Pattern

    • Define the macro with niml LexDataName[TokenType]:.
    • Use raw string literals (prefixed with r"...") to define regex patterns.
    • Each pattern block must return an instance of the specified TokenType.
    • The argument token (of type LToken) is available within the pattern blocks to access the raw text of the matched token.
    • You can define setUp and tearDown blocks to run code during the lexer's lifecycle (open/newWithString/initWithString calls setUp; close calls tearDown).

    Regex Meta-characters

    • ```: escape character
    • .: match any character
    • [: start of character class
    • |: OR operator
    • ( / ): subpattern grouping
    • ?: 0 or 1 quantifier
    • *: 0 or more quantifier
    • +: 1 or more quantifier
    • {n,m}: n to m quantifier

    In character classes []:

    • ^: negate (only at the start)
    • -: range (or use ..)

    Supported character sets:

    • \d: [0..9]
    • \D: [^0..9]
    • \s: [ \t\n\r\f\v]
    • \S: [^ \t\n\r\f\v]
    • \w: [a..zA..Z0..9_]
    • \W: [^a..zA..Z0..9_]
    niml myLexer[Token]:
      r"if":
        return TokenIf()
      r"else":
        return TokenElse()
      r"[a..zA..Z][a-zA-Z0-9]*":
        return TokenIdentifier(token)
      setUp:
        doSomething()
      tearDown:
        doSomething()
  4. Generate a LALR(1) parser with the nimy macro

    master

    The nimy macro generates a LALR(1) parser at compile-time. The parser consumes tokens produced by a lexer.

    Usage Pattern

    • Define the macro with nimy ParserName[TokenType]:.
    • The first block is the top level of the BNF. It must specify a return type: top[ReturnType]:.
    • Define non-terminals with their return types: nonTerminalName[ReturnType]:.
    • Inside a pattern block, use $n to refer to the $n$-th position in the pattern (e.g., $1 is the first element).

    EBNF Functions

    • XXX[]: Option (0 or 1 occurrence of XXX). The resulting type is seq[xxx].
    • XXX{}: Repeat (0 or more occurrences of XXX). The resulting type is seq[xxx].

    Example

    nimy myParser[Token]:
      top[Expr]:
        expr:
          return $1
    
      expr[Expr]:
        LPAR expr RPAR:
          return $2
        expr PLUS expr:
          return $2