You are on page 1of 3

rebol [

autor: Pep Diz


description: a simple logo parser
]

sp: charset reduce [tab newline #" "]


s: [ opt "a" opt "b"]
sq: [ s opt [";" sq]]
b: [sq "."]
b: [":" sq "."]
c: [ "t" ]
ifr: ["if" c "then" b opt ["else" b]]
ifr: ["if" c "then" sq opt ["else" sq] "."]

----
/* antes de parsear se prepara la entrada:
- reduciendo todas las newline a una: s/\nl+/\nl/g
- reduciendo todos los espacios a uno: s/ +/ /g
*/
digito: charset "0123456789"
letra: charset [#"a" - #"z" #"A" - #"Z"]
especial: charset "-"
chars: union especial union digito letra
c: [ "t" | "f" ]
s: ["a" | "b" ]
ssep: charset reduce [";" newline]
sq: [ s opt [ssep sq]]
bdef: charset reduce [":" newline]
b: [opt bdef sq opt ssep]
ifr: ["if" c "then" b opt ["else" b] "."]
prog: [b "."]
; como no se pueden usar tipos parseando strings hay que usar reglas
; param: [string! opt ["," param]]
; proc: ["para" string! opt ["con" param] b "."]
param: [id opt ["," param]]
id: [some [chars]]
proc: ["para" id opt ["con" param] b "."]

;---- version red ---------------------------------------------


;-- en red hay que definir explicitamente los espacios
;-- en lugar de considerar tantos espacios solo para comerselos
;-- seria mejor un preprocesado que eliminase espacios y newlines
;-- para dejar solo un espacio y solo una newline

sp: [ some [" "]]


digito: charset "0123456789"
letra: charset [#"a" - #"z" #"A" - #"Z"]
especial: charset "-"
chars: union especial union digito letra
c: [ "t" | "f" ]
s: ["a" | "b" ]
ssep: charset reduce [";" newline]
sq: [opt sp s opt [opt sp ssep sq]]
bdef: charset reduce [":" newline]
b: [opt sp opt bdef sq opt sp opt ssep]
ifr: ["if" sp c sp "then" b opt ["else" b] "."]
finprg: [ any [opt sp newline] opt sp "."]
prog: [b finprg]
param: [id opt [opt sp "," opt sp param]]
id: [some [chars]]
proc: ["para" sp copy n thru id (print n) opt [sp "con" sp param] prog]
fn: [ param sp "->" sp exp ]
exp: [ factor opt sp ["+" | "-"] opt sp exp | factor ]
factor: [ num opt sp ["*" | "/"] opt sp factor | num ]
num: [some digito | "(" opt sp exp opt sp ")" ]

/*
expr: [term ["+" | "-"] expr | term]
term: [factor ["*" | "/"] term | factor]
factor: [primary "**" factor | primary]
primary: [some digit | "(" expr ")"]
digit: charset "0123456789"
*/
; aplicando algunas transformaciones se puede simplificar la gramatica
; - reducir multiples " " a uno
; - reducir multiples newline a una
; - reducir " ;" a ";"
; - reducir "; " a ";"
; - reducir " :" a ":"
; - reducir ": " a ":"
; - reducir " ." a "."

; funcion para eliminar newline y espacios superfluos


unique: func [s [string!] x [string!] /local ls][ls: copy "" parse copy s [some
[copy n thru x (append ls n) any x] copy m to end (append ls m)] copy ls]
reduce: func [s e r /local t] [t: copy s replace/all t e r copy t]
reduce-i: func [s] [reduce s " ;" ";"]
reduce-f: func [s] [reduce s "; " ";"]
reduce-p: func [s] [reduce s " ." "."]
reduce-di: func [s] [reduce s " :" ":"]
reduce-df: func [s] [reduce s ": " ":"]
reduce-ci: func [s] [reduce s " ," ","]
reduce-cf: func [s] [reduce s ", " ","]
clearcode: func [s] [trim/tail/head reduce-p reduce-cf reduce-ci reduce-df reduce-
di reduce-f reduce-i unique unique s " " "^/"]

; se pueden simplificar las reglas de la gramatica


sp: [" "]
digito: charset "0123456789"
letra: charset [#"a" - #"z" #"A" - #"Z"]
especial: charset "-"
chars: union especial union digito letra
c: [ "t" | "f" ]
s: ["a" | "b" ]
ssep: charset reduce [";" newline]
sq: [s opt [ssep sq]]
bdef: charset reduce [":" newline]
b: [ [bdef | sp] sq [ssep | sp]]
ifr: ["if" sp c sp "then" b opt ["else" b] "."]
prog: [b "."]
param: [id opt ["," param]]
id: [some [chars]]
proc: ["para" sp copy n thru id (print n) opt [sp "con" sp param] prog]
fn: [ param sp "->" sp exp ]
exp: [ factor opt sp ["+" | "-"] opt sp exp | factor ]
factor: [ num opt sp ["*" | "/"] opt sp factor | num ]
num: [some digito | "(" opt sp exp opt sp ")" ]
;------------------------------------------------------------------
;------------ una gramatica basica para un mini logo sin variables
;------------------------------------------------------------------
reduce-di: func [s] [reduce s " [" "["]
reduce-df: func [s] [reduce s "] " "]"]

sp: [" "]


digito: charset "0123456789"
letra: charset [#"a" - #"z" #"A" - #"Z"]
especial: charset "-"
chars: union especial union digito letra
c: [ "v" | "f" ]
s: ["avanza" sp exp | "esquerda" | "dereita" | "xira" sp exp | "adiante" sp exp |
"atras" sp exp | "repite" sp exp b]
ssep: charset reduce [";" newline sp]
sq: [s opt [ssep sq]]
b: [ "[" sq "]"]
;ifr: ["if" sp c sp "then" b opt ["else" b]]
prog: [some b]
param: [id opt ["," param]]
id: [some [chars]]
proc: ["para" sp copy n thru id (print n) opt [sp "con" sp param] prog]
fn: [ param sp "->" sp exp ]
exp: [ factor opt sp ["+" | "-"] opt sp exp | factor ]
factor: [ num opt sp ["*" | "/"] opt sp factor | num | id]
num: [some digito | "(" opt sp exp opt sp ")" ]

; con f programa a parsear, primero hacer: parse clearcode f prog

You might also like