Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Rebol/Red parse is great. Has it been re-implemented in other languages?
15 points by macmac on Dec 26, 2017 | hide | past | favorite | 9 comments



You won't find anything quite like it in any other language, and there's a reason for that. Like Lisp, Redbol langs are homoiconic. Rebol was initially designed as a messaging language, and has a lot of datatypes with literal forms that don't exist in other languages. That's important because the `parse` function can operate at 2 levels: `string` parsing (what you find in other parser toolkits), and `block` parsing. Block parsing means the data has been loaded and tokenized already, and you can parse by high level datatype. I'll try not to get too carried away, but that's tough for me. :^)

Example 1. Red's infix operator precedence is strictly left to right. But Red has a built in `math` function that can take an expression like `2 + 4 * 3` and produce the result you expect from many other languages.

    >> 2 + 4 * 3
    == 18
    >> math [2 + 4 * 3]
    == 14
You can see how it works by using `source math` in the REPL. It's about 7 lines of `parse` rules.

OK, I got carried away. Here's a little dialect I just whipped up as an example (error handling omitted for brevity). It has some supporting funcs at the top, to show how you trigger actions while parsing. If you look at the rules, you can see that some literal words are used as keywords, then different datatypes are matched according to their action.

    ; Actions
    call-phone: func [number [issue!] time][
        print ["Call" mold number "at" time]
    ]
    send-email: func [dest [email!] data [string!]][
        print ["Send" dest length? data "bytes"]
    ]
    post-data:  func [dest [url!] data [string!] time][
        print [
            "Post" length? data "bytes to" dest
            either time? time ['at]['on]
            time
        ]
    ]

    ; Rules
    when=:  [['at | 'on] set when [date! | time!]]
    call=:  ['call set dest issue! opt when= (call-phone dest any [when now])]
    email=: ['email set dest email! content= (send-email dest content)]
    post=:  ['post content= 'to set dest url! when= (post-data dest content when)]
    content=: [
        set content [string! | file! | url!]
        (if not string? content [content: attempt [read content]])
    ]
    contact=: [call= | email= | post=]
    rules=: [any contact=]

    ; Entry point (dialected function)
    contactor: func [input [block!]][
        parse input rules=
    ]

    ; Sample call
    contactor [
        call #000.555.1212 at 12:34
        email user@host.dom "On for lunch?"
        post %news.txt to http://all-the-news.com/news.txt on 1-jan-2018
    ]

    ; Test run output
    Call #000.555.1212 at 12:34:00
    Send user@host.dom 13 bytes
    Post 1815 bytes to http://all-the-news.com/news.txt on 1-Jan-2018
Other langs can implement something like it, but the fact that Redbol langs were designed to solve this very problem--the exchange of information between people and machines--provides a big advantage.


I mean, how can you not love:

  expr:    [term ["+" | "-"] expr | term]
  term:    [factor ["*" | "/"] term | factor]
  factor:  [primary "**" factor | primary]
  primary: [some digit | "(" expr ")"]
  digit:   charset "0123456789"


Instaparse in Clojure (https://github.com/Engelberg/instaparse) seems similar (although I don't know Rebol/Red so I'm purely guessing from looking at parse examples).

You can get close-ish results with parser combinator libraries as well.


I think you can find these advertised as PEGs, or Parser Expression Grammars. The first I learned about was Lua's LPeg: http://www.inf.puc-rio.br/~roberto/lpeg/


What is this? A std library function?


Quoting from the red docs:

  So, in short, what is Parse? It is an embedded DSL (we 
  call them "dialects" in the Rebol world) for parsing 
  input series using grammar rules.


Its different from antlr and co in the sense that there is no code generation step?


Because parse is a embedded DSL you have access to all of rebol/red which lets you easily generate/interpret code. As an example here is a BF interpreter: https://gist.github.com/dockimbel/7713170


Correct. The grammar is interpreted directly.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: