Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
NPEG
https://github.com/zevv/npeg
Admin
PEGs for Nim, another take
Tokens:
7,987
Snippets:
63
Trust Score:
9.1
License:
MIT
Update:
1 year ago
Context
Chat
Benchmark
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Nim: JSON Parser Example using NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Provides an example of a complete JSON parser implemented using NPeg in Nim. This showcases NPeg's capability to handle complex, recursive grammars required for formats like JSON. ```nim import npeg grammar JsonParser: value = object | array | string | number | "true" | "false" | "null" object = "{" [members] "}" members = pair ("," pair)* pair = string ":" value array = "[" [elements] "]" elements = value ( "," value )* # ... (rest of the grammar definitions for string, number, etc.) let parser = JsonParser() let jsonString = "{\"name\": \"Example\", \"value\": 123}" let result = parser.match(jsonString) ``` -------------------------------- ### NPeg Runtime Execution Trace Example Source: https://github.com/zevv/npeg/blob/master/README.md This example displays a runtime trace generated by NPeg during the matching process. It provides detailed information about the execution flow, including instruction pointers, subject indices, rule names, instructions, and stack depth, useful for debugging. ```plaintext 0| 0|one two |line |call -> word:6 | 6| 0|one two |word |set {'a'..'z'} | 7| 1|ne two |word |span {'a'..'z'} | 8| 3| two | |return | 1| 3| two |line |choice -> 5 | 2| 3| two | space |chr " " |* 3| 4|two |line |call -> word:6 |* 6| 4|two |word |set {'a'..'z'} |* 7| 5|wo |word |span {'a'..'z'} |* 8| 7| | |return |* 4| 7| |line |pcommit -> 2 |* 2| 7| | space |chr " " |* | 7| | |fail |* 5| 7| | |return (done) | ``` -------------------------------- ### Example VM Instruction Sequence (String Matching) Source: https://github.com/zevv/npeg/blob/master/INTERNALS.md This snippet shows a simple sequence of VM instructions generated for matching the string 'foo'. It involves a single instruction to perform the string comparison. ```text 1: line opStr "foo" ``` -------------------------------- ### Nim Code Block Capture Example Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates basic usage of code block captures in NPeg with Nim. Captured strings are accessed using `$n` syntax, which is a shorthand for `capture[n].s`. The example prints the captured substrings. ```nim let p = peg foo: foo <- >(1 * >1) * 1: echo "$0 = ", $0 echo "$1 = ", $1 echo "$2 = ", $2 echo p.match("abc").ok ``` -------------------------------- ### Example VM Instruction Sequence (Ordered Choice) Source: https://github.com/zevv/npeg/blob/master/INTERNALS.md Illustrates the VM instructions for an ordered choice (PEG's '|' operator). It attempts to match the first pattern ('foo'), commits if successful, otherwise tries the second pattern ('bar'). ```text 0: line opChoice 3 1: line opStr "foo" 2: line opCommit 4 3: line opStr "bar" 4: opReturn ``` -------------------------------- ### Nim NPeg Parser Example Source: https://github.com/zevv/npeg/blob/master/README.md This Nim code defines a simple PEG grammar for matching lines and words, then demonstrates its usage by parsing the string 'one two'. It showcases the basic structure of defining a parser and matching input. ```nim let parser = peg "line": space <- ' ' line <- word * *(space * word) word <- +{'a'..'z'} discard parser.match("one two") ``` -------------------------------- ### NPeg Backreference Operator (R) Example Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates the NPeg 'R' operator for creating named references and matching previously captured content. 'R(name, P)' creates a named reference for pattern 'P', and 'R(name)' matches the content of that reference. This example matches a string where the first and last characters are identical. ```NPeg patt R("c", 1) * *(1 - R("c")) * R("c") * !1 ``` -------------------------------- ### NPeg Grammar Complexity - Optimized Example Source: https://github.com/zevv/npeg/blob/master/README.md Shows the same grammar as the unoptimized example, but with rules reordered to force NPeg to use a calling mechanism instead of inlining. This prevents the parser from becoming too complex and exceeding the rule limit, improving compilation and performance. ```Nim let p = peg "z": z <- a * a * a * a a <- b * b * b * b b <- c * c * c * c c <- d * d * d * d d <- e * e * e * e e <- f * f * f * f f <- 1 ``` -------------------------------- ### NPeg Templates - Basic List Example Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates a simple NPeg template named 'commaList' that parameterizes a common list-matching pattern. The template takes an 'item' argument and matches 'item' followed by zero or more occurrences of a comma and 'item'. This avoids repeating the pattern for number lists and word lists. ```Nim commaList(item) <- item * *( ',' * item ) numberList <- commaList(+Digit) wordList <- commaList(+Alpha) ``` -------------------------------- ### Nim: String Captures in PEG Parsing Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates how to use the string capture prefix '>' in Nim's NPeg to capture specific matched parts of a PEG. This example modifies the key-value pair parser to capture the 'word' and 'number' components, resulting in a sequence of captured strings. ```nim let parser = peg "pairs": pairs <- pair * *(',' * pair) * !1 word <- +Alpha number <- +Digit pair <- >word * '=' * >number let r = parser.match(data) ``` -------------------------------- ### NPeg Templates - Generalized List Example Source: https://github.com/zevv/npeg/blob/master/README.md Shows a more generalized NPeg template structure where 'list' takes both an 'item' and a 'sep' (separator) argument. This template can then be used to define specific list types like 'commaList', further reducing code duplication and increasing flexibility. ```Nim list(item, sep) <- item * *( sep * item ) commaList(item) <- list(item, ',') numberList <- commaList(+Digit) wordList <- commaList(+Alpha) ``` -------------------------------- ### HTTP Response Parsing with NPeg Captures Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates using code block captures in NPeg to parse an HTTP response document and extract structured data into a Nim object. This example defines a `Request` object to hold the parsed information. ```nim import npeg, strutils, tables type Request = object proto: string version: string code: int message: string headers: Table[string, string] ``` -------------------------------- ### NPeg Intermediate Representation (IR) Example Source: https://github.com/zevv/npeg/blob/master/README.md This output shows the intermediate representation generated by NPeg at compile time after processing a grammar. It details the structure of rules like 'line' and 'word', including inlining and subroutine calls, which aids in understanding the compiled grammar's logic. ```plaintext line: 0: line opCall 6 word word 1: line opChoice 5 *(space * word) 2: space opStr " " ' ' 3: line opCall 6 word word 4: line opPartCommit 2 *(space * word) 5: opReturn word: 6: word opSet '{'a'..'z'}' {'a' .. 'z'} 7: word opSpan '{'a'..'z'}' +{'a' .. 'z'} 8: opReturn ``` -------------------------------- ### Nim: Create Parser from Single Pattern and Split String by Whitespace Source: https://github.com/zevv/npeg/blob/master/README.md This example shows how to create a parser from a single anonymous pattern using the `patt` macro. The pattern is designed to split a string by whitespace characters, and the captured parts are then echoed. It utilizes the `*` operator for repetition and `+` for one or more occurrences. ```nim let parser = patt *(*' ' * > +(1- ' ')) echo parser.match(" one two three ").captures ``` -------------------------------- ### Nim: Define Recursive Grammar with Named Patterns Source: https://github.com/zevv/npeg/blob/master/README.md This example demonstrates defining a recursive grammar using the `peg` macro in Nim. It sets an initial pattern named 'ident' and defines sub-patterns `lower` and `ident`. The `ident` pattern matches zero or more lowercase characters, showcasing recursive pattern definition. ```nim let parser = peg "ident": lower <- {'a'..'z'} ident <- *lower doAssert parser.match("lowercaseword").ok ``` -------------------------------- ### NPeg Grammar Complexity - Unoptimized Example Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates a grammar that will not compile due to excessive recursive inlining, leading to a parser exceeding the 4096 rule limit. NPeg attempts to inline small patterns, but deep recursion can cause performance and size issues. ```Nim let p = peg "z": f <- 1 e <- f * f * f * f d <- e * e * e * e c <- d * d * d * d b <- c * c * c * c a <- b * b * b * b z <- a * a * a * a ``` -------------------------------- ### Parse UTF-8 Document into Characters with NPeg (Nim) Source: https://github.com/zevv/npeg/blob/master/README.md This snippet demonstrates how to parse a UTF-8 encoded string into individual characters or glyphs using NPeg's provided UTF-8 grammar library. It defines a grammar where 'char' rule uses 'utf8.any' to match a single Unicode code point. The example shows matching a Greek string and capturing each character. ```nim import npeg/lib/utf8 let p = peg "line": line <- +char char <- >utf8.any let r = p.match("γνωρίζω") echo r.captures() # --> @["γ", "ν", "ω", "ρ", "ί", "ζ", "ω"] ``` -------------------------------- ### Import and Use Pre-defined NPeg Libraries Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates how to import pre-defined NPeg libraries using Nim's 'import' statement. This makes the rules defined in the imported library available for use in the current grammar. ```nim import npeg/lib/uri ``` -------------------------------- ### Nim: Simple Pattern Matching with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates basic pattern matching using NPeg macros in Nim. It shows how to define simple patterns and apply them to strings. This is useful for basic text manipulation and validation. ```nim import npeg let pattern = re"[a-z]+" let result = pattern.match("hello world") if result.isOk: echo "Matched: ", result.get else: echo "No match." ``` -------------------------------- ### VM Program to C Case Statement Translation Source: https://github.com/zevv/npeg/blob/master/INTERNALS.md Illustrates the compilation of the npeg VM program into a C-style 'case' statement. This represents the executable logic for the parser, handling different VM opcodes. ```c while true: case ip of 0: opChoiceFn(3, "lines") of 1: opCallFn("line", 3, "lines") of 2: opPartCommitFn(1, "lines") of 3: opReturnFn("") of 4: opChoiceFn(7, "line") of 5: opStrFn("foo", "line") of 6: opCommitFn(8, "line") of 7: opStrFn("bar", "line") of 8: opReturnFn("") else: opFailFn() ``` -------------------------------- ### Nim: Compile Grammar to Parser and Match String with Key-Value Pairs Source: https://github.com/zevv/npeg/blob/master/README.md This snippet demonstrates compiling a grammar definition using the `peg` macro into a `parser` object. The parser is then used to match a string, extracting key-value pairs into a Nim table. It shows defining grammar rules for pairs, words, numbers, and storing parsed data. ```nim import npeg, strutils, tables type Dict = Table[string, int] let parser = peg("pairs", d: Dict): pairs <- pair * *(',' * pair) * !1 word <- +Alpha number <- +Digit pair <- >word * '=' * >number: d[$1] = parseInt($2) var words: Dict doAssert parser.match("one=1,two=2,three=3,four=4", words).ok echo words ``` -------------------------------- ### npeg Grammar to VM Program Translation Source: https://github.com/zevv/npeg/blob/master/INTERNALS.md Shows the transformation of a simple npeg grammar into its corresponding virtual machine instructions. This process is fundamental to how npeg processes input strings based on defined rules. ```npeg lines <- *line line <- "foo" | "bar" ``` ```vm-assembly lines: 0: lines opChoice 3 1: lines opCall 4 line 2: lines opPartCommit 1 3: opReturn line: 4: line opChoice 7 5: line opStr "foo" 6: line opCommit 8 7: line opStr "bar" 8: opReturn ``` -------------------------------- ### Parse HTTP Data with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md This code snippet demonstrates how to use the defined NPeg HTTP grammar to parse a sample HTTP data string. It initializes a `Request` object, matches the data against the grammar, and prints the resulting parsed structure. ```nim const data = """ HTTP/1.1 301 Moved Permanently Content-Length: 162 Content-Type: text/html Location: https://nim.org/ """ var request: Request let res = parser.match(data, request) echo request ``` -------------------------------- ### Nim: Grammar Definition and Parsing with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates defining and using grammars with NPeg in Nim. Grammars allow for more complex parsing structures than simple patterns. This enables parsing structured data like configuration files or simple languages. ```nim import npeg grammar MyGrammar: start = "hello" number number = digit+ digit = "0" .. "9" let p = MyGrammar() p.match("hello 123") ``` -------------------------------- ### Enable NPeg Compile-Time and Run-Time Tracing Source: https://github.com/zevv/npeg/blob/master/README.md Enables compile-time and run-time tracing for NPeg. This flag is primarily for debugging NPeg itself and is usually not needed by end-users. Refer to the 'Tracing' section for more details. ```nim -d:npegTrace ``` -------------------------------- ### Parse Arithmetic Expressions with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates parsing arithmetic expressions using NPeg. The grammar defines rules for expressions, terms, factors, and lines. It includes an assertion to verify a sample expression. ```nim let parser = peg "line": exp <- term * *( ('+'|'-') * term) term <- factor * *( ('*'|'/') * factor) factor <- +{'0'..'9'} | ('(' * exp * ')') line <- exp * !1 doAssert parser.match("3*(4+15)+2").ok ``` -------------------------------- ### Define Grammar Templates with Qualified Rules in NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Shows how to define grammar templates in NPeg. Templates can reference rules from other grammars using qualified names (e.g., 'foo.open'), ensuring correct rule resolution even when templates are defined separately. ```nim grammar "foo": open <- "(" close <- ")" inBrackets(body): foo.open * body * foo.close ``` -------------------------------- ### NPeg Grammar for Anchoring and Searching Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates a common pattern in PEG grammars for searching within a subject string. It shows how to define a pattern and then use alternation with recursion to repeatedly attempt matching or consume a character if the pattern doesn't match at the current position. ```peg p <- "bar" search <- p | 1 * search ``` -------------------------------- ### Nim: Create Parser with Code Block Capture for Pattern Matching Source: https://github.com/zevv/npeg/blob/master/README.md This snippet illustrates using the `patt` macro with an optional code block to capture parsed data. The pattern matches digits followed by an equals sign and then alphabetic characters. The associated code block assigns the captured digit string to `key` and the alphabetic string to `val`. ```nim var key, val: string let p = patt >+Digit * "=" * >+Alpha: (key, val) = ($1, $2) assert p.match("15=fifteen").ok echo key, " = ", val ``` -------------------------------- ### NPeg Built-in Shortcuts for POSIX Character Classes in Nim Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates NPeg's built-in shortcuts that correspond to common POSIX character classes. These shortcuts simplify grammar definitions by providing pre-defined character sets for common patterns like alphanumeric, alphabetic, and digit characters. ```nim Alnum <- {'A'..'Z','a'..'z','0'..'9'}, # Alphanumeric characters Alpha <- {'A'..'Z','a'..'z'}, # Alphabetic characters Blank <- {' ','\t'}, # Space and tab Cntrl <- {'\x00'..'\x1f','\x7f'}, # Control characters Digit <- {'0'..'9'}, # Digits Graph <- {'\x21'..'\x7e'}, # Visible characters Lower <- {'a'..'z'}, # Lowercase characters Print <- {'\x21'..'\x7e',' '}, # Visible characters and spaces Space <- {'\9'..'\13',' '}, # Whitespace characters Upper <- {'A'..'Z'}, # Uppercase characters Xdigit <- {'A'..'F','a'..'f','0'..'9'} # Hexadecimal digits ``` -------------------------------- ### Define HTTP Grammar in NPeg Source: https://github.com/zevv/npeg/blob/master/README.md This snippet defines a simplified HTTP grammar using the NPeg library. It specifies rules for parsing HTTP requests and responses, including protocols, versions, status codes, messages, and headers. The grammar utilizes capture actions to populate a `Request` userdata object. ```nim let parser = peg("http", userdata: Request): space <- ' ' crlf <- '\n' * ?'\r' url <- +(Alpha | Digit | '/' | '_' | '.') eof <- !1 header_name <- +(Alpha | '-') header_val <- +(1-{'\n'}-{'\r'}) proto <- >+Alpha: (userdata.proto = $1) version <- >(+Digit * '.' * +Digit): (userdata.version = $1) code <- >+Digit: (userdata.code = parseInt($1)) msg <- >(+(1 - '\r' - '\n')): userdata.message = $1 header <- >header_name * ": " * >header_val: userdata.headers[$1] = $2 response <- proto * '/' * version * space * code * space * msg headers <- *(header * crlf) http <- response * crlf * headers * eof ``` -------------------------------- ### Character Sets in NPeg Nim Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates how to define character sets in NPeg using the `{}` notation, similar to native Nim. Character sets can include individual characters or ranges of characters for flexible pattern matching. ```nim {'x'..'y'} # matches any character in the range from 'x'..'y' {'x','y','z'} # matches any character from the set 'x', 'y', and 'z' ``` -------------------------------- ### Nim: Basic PEG Structure for Key-Value Pairs Source: https://github.com/zevv/npeg/blob/master/README.md Defines a basic PEG structure in Nim to parse a comma-separated list of key-value pairs. It sets up rules for pairs, words, and numbers, demonstrating a simple parsing scenario before applying capture mechanisms. ```nim const data = "one=1,two=2,three=3,four=4" let parser = peg "pairs": pairs <- pair * *(',' * pair) * !1 word <- +Alpha number <- +Digit pair <- word * '=' * number let r = parser.match(data) ``` -------------------------------- ### Dump Syntax Diagrams with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Dumps syntax diagrams of all parsed rules at compile time. This flag is intended for debugging NPeg's internal workings. ```nim -d:npegGraph ``` -------------------------------- ### Nim Table Population with Code Block Captures Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates using code block captures to populate a Nim table with key-value pairs parsed from input. It defines rules for pairs, words, and numbers, and uses `parseInt` for type conversion. The `words` table is updated within the `pair` rule's code block. ```nim from strutils import parseInt var words = initTable[string, int]() let parser = peg "pairs": pairs <- pair * *(',' * pair) * !1 word <- +Alpha number <- +Digit pair <- >word * '=' * >number: words[$1] = parseInt($2) let r = parser.match(data) ``` -------------------------------- ### Enable NPeg Debug Information Source: https://github.com/zevv/npeg/blob/master/README.md Enables additional debug information. This flag is intended strictly for NPeg development and debugging purposes. ```nim -d:npegDebug ``` -------------------------------- ### Nim: String Captures in NPeg Patterns Source: https://github.com/zevv/npeg/blob/master/README.md Shows how to capture specific parts of a matched string using NPeg's string capture syntax in Nim. This is essential for extracting data from parsed text. Captured strings can be accessed via the result object. ```nim import npeg let pattern = re"name: @name" # '@name' captures the following characters let result = pattern.match("name: Alice") if result.isOk: echo "Captured name: ", result.captures["name"] ``` -------------------------------- ### Nim: Code Block Captures with State Passing in NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates using Nim code blocks within NPeg patterns to perform custom validations or actions during parsing, including passing state. This allows for complex logic integrated directly into the grammar. ```nim import npeg let pattern = re"value: { let v = parseInt(capture) }; v > 0" let result = pattern.match("value: 42") if result.isOk: echo "Valid positive value parsed." ``` -------------------------------- ### Enable NPeg Stacktrace on Exception Source: https://github.com/zevv/npeg/blob/master/README.md When enabled, NPeg will dump a stack trace at the current parser position when an exception is thrown. This applies to exceptions from NPeg itself or from Nim code within code block captures. ```nim -d:npegStacktrace ``` -------------------------------- ### NPeg Optional Operator (?) Source: https://github.com/zevv/npeg/blob/master/README.md The optional operator matches pattern P zero or more times. It succeeds whether P matches or not, effectively making P optional. ```NPeg ?P ``` -------------------------------- ### NPeg Grammar Components in Nim Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates various components of NPeg grammar including atoms, operators, precedence operators, string captures, back references, and error handling. These components are used to define complex parsing rules within NPeg. ```nim Atoms: 0 # matches always and consumes nothing 1 # matches any character n # matches exactly n characters 'x' # matches literal character 'x' "xyz" # matches literal string "xyz" i"xyz" # matches literal string, case insensitive {'x'..'y'} # matches any character in the range from 'x'..'y' {'x','y','z'} # matches any character from the set Operators: P1 * P2 # concatenation P1 | P2 # ordered choice P1 - P2 # matches P1 if P2 does not match (P) # grouping !P # matches everything but P &P # matches P without consuming input ?P # matches P zero or one times *P # matches P zero or more times +P # matches P one or more times @P # search for P P[n] # matches P n times P[m..n] # matches P m to n times Precedence operators: P ^ N # P is left associative with precedence N P ^^ N # P is right associative with precedence N String captures: >P # Captures the string matching P Back references: R("tag", P) # Create a named reference for pattern P R("tag") # Matches the given named reference Error handling: E"msg" # Raise an `NPegParseError` exception ``` -------------------------------- ### Handle NPegParseError in Nim Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates how to catch and handle NPegParseError exceptions in Nim. This involves using a try-except block to catch the specific exception type and access its error message and position. This is useful for providing user-friendly feedback on parsing failures. ```nim let parser = peg "list": list <- word * *(comma * word) * !1 word <- +Alpha | E"expected word" comma <- ',' | E"expected comma" try: echo parser.match("one,two;three") except NPegParseError as e: echo "Parsing failed at position ", e.matchMax, ": ", e.msg ``` -------------------------------- ### Dump Generated Nim Code with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Dumps the generated Nim code for all parsers defined within the program. This is for NPeg development debugging purposes only. ```nim -d:npegExpand ``` -------------------------------- ### Nim Passing State to NPeg Parser Source: https://github.com/zevv/npeg/blob/master/README.md Explains and demonstrates how to pass external state to an NPeg parser using the `peg(name, identifier: Type)` syntax. The `pairs` parser is redefined to accept a `Dict` (table) named `userdata`, which is then modified within the `pair` rule's code block, eliminating the need for global variables. ```nim type Dict = Table[string, int] let parser = peg("pairs", userdata: Dict): pairs <- pair * *(',' * pair) * !1 word <- +Alpha number <- +Digit pair <- >word * '=' * >number: userdata[$1] = parseInt($2) var words: Dict let r = parser.match(data, words) ``` -------------------------------- ### Define and Use Number Grammars in NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Defines three rules (decimal, hexadecimal, octal) within a 'number' grammar library. These rules are then used in another grammar 'line' to parse integers, demonstrating qualified name referencing for library patterns. ```nim grammar "number": dec <- {'1'..'9'} * *{'0'..'9'} hex <- i"0x" * +{'0'..'9','a'..'f','A'..'F'} oct <- '0' * *{'0'..'9'} let p = peg "line": line <- int * *( R"," * int) int <- number.dec | number.hex | number.oct let r = p.match("123,0x42,0644") ``` -------------------------------- ### Override Library Rules for Custom Captures in NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Illustrates how to override or shadow rules from an imported NPeg library. This allows for customization, such as capturing specific parts of a URI into a Nim object during parsing. ```nim import npeg/lib/uri type Uri = object host: string scheme: string path: string port: int var myUri: Uri let parser = peg "line": line <- uri.URI uri.scheme <- >uri.scheme: myUri.scheme = $1 uri.host <- >uri.host: myUri.host = $1 uri.port <- >uri.port: myUri.port = parseInt($1) uri.path <- >uri.path: myUri.path = $1 echo parser.match("http://nim-lang.org:8080/one/two/three") echo myUri # --> (host: "nim-lang.org", scheme: "http", path: "/one/two/three", port: 8080) ``` -------------------------------- ### Complete JSON Parser with NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Defines a complete parser for the JSON language using NPeg. This parser focuses on traversal and validation without producing captures. It includes rules for numbers, strings, objects, arrays, and basic types. ```nim let s = peg "doc": S <- *Space jtrue <- "true" jfalse <- "false" jnull <- "null" unicodeEscape <- 'u' * Xdigit[4] escape <- '\\' * ({ '{', '"', '|', '\\', 'b', 'f', 'n', 'r', 't' } | unicodeEscape) stringBody <- ?escape * *( +( {'\x20'..'\xff'} - {'"'} - {'\\' } ) * *escape) jstring <- ?S * '"' * stringBody * '"' * ?S minus <- '-' intPart <- '0' | (Digit-'0') * *Digit fractPart <- "." * +Digit expPart <- ( 'e' | 'E' ) * ?( '+' | '-' ) * +Digit jnumber <- ?minus * intPart * ?fractPart * ?expPart doc <- JSON * !1 JSON <- ?S * ( jnumber | jobject | jarray | jstring | jtrue | jfalse | jnull ) * ?S jobject <- '{' * ( jstring * ":" * JSON * *( "," * jstring * ":" * JSON ) | ?S ) * '}' jarray <- '[' * ( JSON * *( "," * JSON ) | ?S ) * ']' doAssert s.match(json).ok let doc = """ {\"jsonrpc\": \"2.0\", \"method\": \"subtract\", \"params\": [42, 23], \"id\": 1} """ doAssert parser.match(doc).ok ``` -------------------------------- ### NPeg Ordered Choice Operator (|) Source: https://github.com/zevv/npeg/blob/master/README.md The ordered choice operator allows trying pattern P1 first. If P1 fails, NPeg backtracks and tries pattern P2. This choice is final once either P1 or P2 matches. ```NPeg P1 | P2 ``` -------------------------------- ### NPeg Difference Operator (-) Source: https://github.com/zevv/npeg/blob/master/README.md The difference operator matches P1 only if P2 does not match. This is equivalent to '!P2 * P1'. It is optimized for characters and character sets. ```NPeg P1 - P2 ``` -------------------------------- ### Nim Grammar Failure with Code Block Captures Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates how to force a grammar parse to fail using a code block capture. The `error` rule explicitly calls `fail()`, which causes the entire parsing process to halt with a failure. ```nim error <- 0: fail() ``` -------------------------------- ### NPeg Match One or More Times Operator (+) Source: https://github.com/zevv/npeg/blob/master/README.md The match one or more times operator greedily matches pattern P at least once, and potentially more times. It is equivalent to 'P * *P'. ```NPeg +P ``` -------------------------------- ### Check Parsing Success and Error Position in NPeg Source: https://github.com/zevv/npeg/blob/master/README.md Demonstrates how to inspect the MatchResult object to determine if a parse was successful ('ok' field) and to identify the position of a parsing error ('matchMax' field). This is a basic method for error handling in NPeg. ```nim let a = patt 4 let r = a.match("123") if not r.ok: echo "Parsing failed at position ", r.matchMax ``` -------------------------------- ### Nim: Pratt Parser with Precedence Operators Source: https://github.com/zevv/npeg/blob/master/README.md Implements a Pratt parser in Nim using NPeg's precedence operators ('^' for left-associative, '^^' for right-associative). This allows for parsing arithmetic expressions with standard precedence and associativity rules. It defines rules for expressions, parenthesized expressions, prefixes, and infix operators. ```nim exp <- prefix * *infix parenExp <- ( "(" * exp * ")" ) ^ 0 prefix <- number | parenExp infix <- {'+"-"} * exp ^ 1 | {'*','/'} * exp ^ 2 | {'^'} * exp ^^ 3 ``` -------------------------------- ### NPeg And-Predicate Operator (&) Source: https://github.com/zevv/npeg/blob/master/README.md The and-predicate operator matches if the input matches pattern P, without consuming any input. This is equivalent to '!!P'. ```NPeg &P ``` -------------------------------- ### NPeg Search Operator (@) Source: https://github.com/zevv/npeg/blob/master/README.md The search operator finds pattern P within the input using an optimized implementation. It is equivalent to 's <- *(1 - P) * P'. It does not capture skipped data. ```NPeg @P ``` -------------------------------- ### NPeg Grouping Operator (()) Source: https://github.com/zevv/npeg/blob/master/README.md Parentheses are used to group patterns, similar to arithmetic expressions, to control the order of operations and the scope of other operators. ```NPeg (P) ``` -------------------------------- ### NPeg Match Zero or More Times Operator (*) Source: https://github.com/zevv/npeg/blob/master/README.md The match zero or more times operator greedily matches as many occurrences of pattern P as possible. It is denoted by '*P'. ```NPeg *P ``` -------------------------------- ### NPeg MatchResult Object Structure Source: https://github.com/zevv/npeg/blob/master/README.md Defines the structure of the MatchResult object returned by NPeg's match() procedure. It includes fields to indicate parsing success, the length of the match, and the maximum offset reached. ```nim type MatchResult = object ok: bool matchLen: int matchMax: int ``` -------------------------------- ### NPeg Match M to N Times Operator ([m..n]) Source: https://github.com/zevv/npeg/blob/master/README.md The match m to n times operator matches pattern P at least m times and at most n times consecutively. ```NPeg P[m..n] ``` -------------------------------- ### NPeg Match Exactly N Times Operator ([n]) Source: https://github.com/zevv/npeg/blob/master/README.md The match exactly n times operator matches pattern P precisely n times consecutively. ```NPeg P[n] ``` -------------------------------- ### Nim Custom Validation with Code Block Captures Source: https://github.com/zevv/npeg/blob/master/README.md Shows how to implement custom validation within NPeg grammar rules using code blocks. The `uint8` rule captures digits and then uses `validate` to check if the parsed integer falls within the valid `uint8` range (0-255). ```nim uint8 <- >Digit[1..3]: let v = parseInt($a) validate v>=0 and v<=255 ``` -------------------------------- ### NPeg Concatenation Operator (* or ∙) Source: https://github.com/zevv/npeg/blob/master/README.md The concatenation operator combines two patterns, P1 and P2, to match P1 followed immediately by P2. This operator is denoted by '*' or the unicode character '∙'. ```NPeg P1 * P2 ``` ```NPeg P1 ∙ P2 ``` -------------------------------- ### NPeg Not-Predicate Operator (!) Source: https://github.com/zevv/npeg/blob/master/README.md The not-predicate operator returns a pattern that succeeds only if the input does not match pattern P. This pattern does not consume any input. ```NPeg !P ```