Parse EBNF: Difference between revisions

Parsing EBNF pattern
(→‎{{header|Tcl}}: Add in-progress, incomplete Ruby.)
(Parsing EBNF pattern)
Line 12:
 
=={{header|PicoLisp}}==
<lang PicoLisp>(def 'expr 'ebnf '(term ((PLUS | MINUS) term) *))
{{improve|PicoLisp|This is not an EBNF parser. It never uses EBNF. It is a calculator parser, but there is already a calculator parser at [[Arithmetic evaluation#PicoLisp]]. One should adjust this solution to parse the EBNF language, not the calculator language.}}
(def 'term 'ebnf '(factor ((MULT | DIV) factor) *))
(def 'factor 'ebnf '(NUMBER))</lang>
<lang PicoLisp>(de matchEbnf (Pat)
(cond
((asoq Pat '((PLUS . +) (MINUS . -) (MULT . *) (DIV . /)))
((num?let X)Op (cdr X@)
(when (= "+" X)Op (termcar *Lst))
(let X (pop '*LLst)
X Op ) ) )
((== 'NUMBER Pat)
(cond
((= "-" X) (pack(num? "-"(car (term)*Lst))
((= "(" X) (prog1 (aggr) (pop '*L)))) ) ) Lst)
@ )
((and (= "-" (car *Lst)) (num? (cadr *Lst)))
(setq *Lst (cddr *Lst))
(- @) ) ) )
((get Pat 'ebnf) (parseLst @))
((atom Pat))
(T
(loop
(T (matchEbnf (pop 'Pat)) @)
(NIL Pat)
(NIL (== '| (pop 'Pat)))
(NIL Pat) ) ) ) )
 
<lang PicoLisp>(de parseparseLst (StrPat)
(let *L(P (strpop Str'Pat) X (matchEbnf ""P))
(aggr) ) )loop
(NIL Pat)
 
(if (n== '* (cadr Pat))
(de aggr ()
(letif X(matchEbnf (prodpop 'Pat))
(while (member (carsetq *L)X '("+"list @ "-"X))
(setq X (op (if (= "+" (pop '*L)) "PLUS" "MINUS") X (prod))throw) )
(loop
(NIL *Lst)
(NIL (matchEbnf (car Pat)))
(setq X (list @ X (or (matchEbnf P) (throw)))) )
(setq Pat (cddr Pat)) ) )
X ) )
 
(de prodparseEbnf (Str)
(let X*Lst (termstr Str "")
(catch NIL
(while (member (car *L) '("*" "/"))
(setq XparseLst (opget (if (= "*" (pop'expr '*Lebnf)) "MULT" "DIV") X (term))) )</lang>
X ) )
 
(de term ()
(let X (pop '*L)
(cond
((num? X) X)
((= "+" X) (term))
((= "-" X) (pack "-" (term)))
((= "(" X) (prog1 (aggr) (pop '*L)))) ) ) )
 
(de op (Op Ex1 Ex2)
(pack Op " " (subx Ex1) " " (subx Ex2)) )
 
(de subx (Ex)
(if (sub? " " Ex) (pack "{" Ex "}") Ex) ) )</lang>
Output:
<pre>: (parseparseEbnf "1- + 2 * -3 / 7 - 3 * (4+5)")
-> "MINUS(- {MINUS(+ 1 2}(/ {MULT(* 2 -3) {PLUS7)) 4(* 5}}"3 4))</pre>
 
: (parse "1-2 - -3 * 4+5")
-> "PLUS {MINUS {MINUS 1 2} {MULT -3 4}} 5"
 
: (parse "(1+2+3)*-4/(1+2)")
-> "DIV {MULT {PLUS {PLUS 1 2} 3} -4} {PLUS 1 2}"</pre>
 
=={{header|Ruby}}==
Anonymous user