-
I'm testing PEG and I want to replicate EBNF of PL/0
EBNF example on wikipedia:
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Welcome to parsing - it just is like this. To this end, EBNF is a way to document the language. So, to answer your questions more accurately:
I would recommend:
|
Beta Was this translation helpful? Give feedback.
-
Not really an answer, but sharing a sketch of an approach. I tried gradually building up a series of smaller grammars (though I didn't finish), and made use of earlier ones via # program = block "." ;
# block = [ "const" ident "=" number {"," ident "=" number} ";"]
# [ "var" ident {"," ident} ";"]
# { "procedure" ident ";" block ";" } statement ;
# statement = [ ident ":=" expression | "call" ident
# | "?" ident | "!" expression
# | "begin" statement {";" statement } "end"
# | "if" condition "then" statement
# | "while" condition "do" statement ];
# condition = "odd" expression |
# expression ("="|"#"|"<"|"<="|">"|">=") expression ;
# expression = [ "+"|"-"] term { ("+"|"-") term};
# term = factor {("*"|"/") factor};
# factor = ident | number | "(" expression ")";
(def number-grammar
~@{:main (sequence :number -1)
:number (choice "0"
(sequence (range "19") :d*))})
(comment
(peg/match number-grammar "0")
# =>
@[]
(peg/match number-grammar "1")
# =>
@[]
(peg/match number-grammar "1209")
# =>
@[]
(peg/match number-grammar "a")
# =>
nil
)
(def ident-grammar
~@{:main (sequence :ident -1)
:ident (sequence :a (any :w))})
(comment
(peg/match ident-grammar "a")
# =>
@[]
(peg/match ident-grammar "bee")
# =>
@[]
(peg/match ident-grammar "0")
# =>
nil
)
(def expression-grammar
(merge number-grammar
ident-grammar
~@{:main (sequence :expression -1)
:expression (sequence (opt (sequence (choice "+" "-") :s*))
:term
(any (sequence :s+
(choice "+" "-") :s*
:term)))
:term (sequence :factor
(any (sequence :s+
(choice "*" "/") :s+
:factor)))
:factor (choice :ident
:number
(sequence "(" :s* :expression :s* ")"))}))
(comment
(peg/match expression-grammar "0")
# =>
@[]
(peg/match expression-grammar "a")
# =>
@[]
(peg/match expression-grammar "( x )")
# =>
@[]
(peg/match expression-grammar "(y)")
# =>
@[]
(peg/match expression-grammar "a * b / c")
# =>
@[]
(peg/match expression-grammar "a * (b / c)")
# =>
@[]
(peg/match expression-grammar "1 + 2 - 3")
# =>
@[]
(peg/match expression-grammar "-789")
# =>
@[]
)
(def condition-grammar
(merge expression-grammar
~@{:main (sequence :condition -1)
:condition
(choice (sequence "odd" :s+ :expression)
(sequence :expression :s+
(choice "=" "#" "<=" "<" ">=" ">") :s+
:expression))}))
(comment
(peg/match condition-grammar "a = 0")
# =>
@[]
(peg/match condition-grammar "x >= 0")
# =>
@[]
(peg/match condition-grammar "i < -j")
# =>
@[]
(peg/match condition-grammar "(1 + 2 - a) <= b")
# =>
@[]
)
(def statement-grammar
(merge condition-grammar
~@{:main (sequence :statement -1)
:statement
(choice (sequence :ident :s+ ":=" :s+ :expression)
(sequence "call" :s+ :ident)
(sequence "?" :s* :ident)
(sequence "!" :s* :ident)
(sequence "begin" :s+
:statement
(any (sequence ";" :s+ :statement)) :s+
"end")
(sequence "if" :s+
:condition :s+
"then" :s+
:statement)
(sequence "while" :s+
:condition :s+
"do" :s+
:statement))}))
(comment
(peg/match statement-grammar "call a")
# =>
@[]
(peg/match statement-grammar "?b")
# =>
@[]
(peg/match statement-grammar "!c")
# =>
@[]
(peg/match statement-grammar
``
begin
call x
end
``)
# =>
@[]
(peg/match statement-grammar
``
begin
call x;
begin
!b
end
end
``)
# =>
@[]
(peg/match statement-grammar
``
if a < b then
x := y
``)
# =>
@[]
(peg/match statement-grammar
``
while x > 0 do
x := x - 1
``)
# =>
@[]
) |
Beta Was this translation helpful? Give feedback.
Not really an answer, but sharing a sketch of an approach.
I tried gradually building up a series of smaller grammars (though I didn't finish), and made use of earlier ones via
merge
: