Last active
January 28, 2018 06:47
-
-
Save 9214/cd41fa91c83511e78e1ad31b04e5c02d to your computer and use it in GitHub Desktop.
👽
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Red [ | |
Title: "crudely hacked together example DSL" | |
Link: https://stackoverflow.com/questions/48454538/how-to-parse-and-translate-dsl-using-red-or-rebol | |
Author: 9214 | |
] | |
;;; example input | |
DSL: [ | |
RULE TooYoung | |
IF [Person.Age < 15] | |
WRITE MESSAGE TO LOG "too young to earn an income" | |
SET DATA Person.Income = 0 | |
ELSE | |
WRITE MESSAGE TO LOG "old enough" | |
ENDIF | |
ENDRULE | |
] | |
;;; expected output | |
TooYoung: function [][ | |
either Person.Age < 15 [ | |
WriteMessageToLog "too young to earn an income" | |
Person.Income: 0 | |
][ | |
WriteMessageToLog "old enough" | |
] | |
] | |
;;; PEG | |
parser: context [ | |
func-name: | |
if-expr: true-block: false-block: | |
word: expr: | |
none | |
rule: [ | |
'rule set func-name word! | |
any statement | |
'endrule | |
] | |
statement: [if* | log | set*] ; * is used to avoid clash with parse keywords | |
if*: [ | |
'if set if-expr expression | |
collect set true-block any statement | |
[ | |
'else collect set false-block any statement | |
| (false-block: none) | |
] | |
thru 'endif | |
] | |
log: [ | |
'write 'message 'to 'log set expr expression | |
keep ('write-to-log) | |
keep (expr) | |
] | |
set*: [ | |
'set 'data set word data '= set expr expression | |
keep (to set-word! word) | |
keep (expr) | |
] | |
expression: [block! | string! | integer!] | |
data: ['person.income | 'person.age] | |
;;; code emitter | |
emit-rule: does [ | |
compose/deep [ | |
(to set-word! func-name) function [][ | |
either (if-expr) [ | |
(true-block) | |
][ | |
(false-block) | |
] | |
] | |
] | |
] | |
] | |
;;; release the kraken | |
probe code: parse DSL bind [ | |
collect any [ | |
rule keep (emit-rule) | |
| statement ; tbd if necessary | |
] | |
] parser | |
;;; is it working? | |
reduce first code | |
write-to-log: :print | |
person.age: 0 tooyoung | |
person.age: 1337 tooyoung |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment