### Integrated Lexer and Parser Example with Nimly and Patty Source: https://github.com/loloicci/nimly/blob/master/README.rst This example demonstrates defining custom tokens using `patty`, generating a lexer with `niml`, and a parser with `nimy` for a simple arithmetic expression. It showcases how to handle different token types and construct results during parsing. ```nim import unittest import patty import strutils import nimly ## variant is defined in patty variant MyToken: PLUS MULTI NUM(val: int) DOT LPAREN RPAREN IGNORE niml testLex[MyToken]: r"\(": return LPAREN() r"\)": return RPAREN() r"\+": return PLUS() r"\*": return MULTI() r"\d": return NUM(parseInt(token.token)) r"\. ": return DOT() r"\s": return IGNORE() nimy testPar[MyToken]: top[string]: plus: return $1 plus[string]: mult PLUS plus: return $1 & " + " & $3 mult: return $1 mult[string]: num MULTI mult: return "[" & $1 & " * " & $3 & "]" num: return $1 num[string]: LPAREN plus RPAREN: return "(" & $2 & ")" ## float (integer part is 0-9) or integer NUM DOT[] NUM{}: result = "" # type of `($1).val` is `int` result &= $(($1).val) if ($2).len > 0: result &= "." # type of `$3` is `seq[MyToken]` and each elements are NUM for tkn in $3: # type of `tkn.val` is `int` result &= $(tkn.val) test "test Lexer": var testLexer = testLex.newWithString("1 + 42 * 101010") ``` -------------------------------- ### Nimly Parser Generation with `nimy` Source: https://github.com/loloicci/nimly/blob/master/README.rst The `nimy` macro generates an LALR(1) parser at compile-time. It requires a token type with a `kind` field and defines grammar rules using BNF-like syntax. The `top` rule specifies the starting non-terminal. ```nim ## This makes a LexData object named myParser. ## first cloud is the top-level of the BNF. ## This lexer recieve tokens with type ``Token`` and token must have a value ## ``kind`` with type enum ``[TokenTypeName]Kind``. ## This is naturally satisfied when you use ``patty`` to define the token. nimy myParser[Token]: ## the starting non-terminal ## the return type of the parser is ``Expr`` top[Expr]: ## a pattern. expr: ## proc body that is used when parse the pattern with single ``expr``. ## $1 means first position of the pattern (expr) return $1 ## non-terminal named ``expr`` ## with returning type ``Expr`` expr[Expr]: ## first pattern of expr. ## ``LPAR`` and ``RPAR`` is TokenKind. LPAR expr RPAR: return $2 ## second pattern of expr. ## ``PLUS`` is TokenKind. expr PLUS expr return $2 ``` -------------------------------- ### Nimly Lexer Generation with `niml` Source: https://github.com/loloicci/nimly/blob/master/README.rst Use the `niml` macro to define a lexer at compile-time. It takes a name for the LexData object and the return type for found tokens. Rules are defined using regular expressions and corresponding return values. ```nim ## This makes a LexData object named myLexer. ## This lexer returns value with type ``Token`` when a token is found. niml myLexer[Token]: r"if": ## this part converted to procbody. ## the arg is (token: LToken). return TokenIf() r"else": return TokenElse() r"true": return TokenTrue() r"false": return TokenFalse() ## you can use ``..`` instead of ``-`` in ``[]``. r"[a..zA..Z0..9\-_][a..zA..Z0..9\-_]*": return TokenIdentifier(token) ## you can define ``setUp`` and ``tearDown`` function. ## ``setUp`` is called from ``open``, ``newWithString`` and ## ``initWithString``. ## ``tearDown`` is called from ``close``. ## an example is ``test/lexer_global_var.nim``. setUp: doSomething() tearDown: doSomething() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.