Merge remote branch 'upstream/master'
commit
7337e38848
|
@ -267,7 +267,7 @@ HELP: nth-root
|
|||
|
||||
HELP: 10^
|
||||
{ $values { "x" number } { "y" number } }
|
||||
{ $description "Raises " { $snippet "x" } " to the power of 10. If " { $snippet "x" } " is an integer the answer is computed exactly, otherwise a floating point approximation is used." } ;
|
||||
{ $description "Raises 10 to the power of " { $snippet "x" } ". If " { $snippet "x" } " is an integer the answer is computed exactly, otherwise a floating point approximation is used." } ;
|
||||
|
||||
HELP: gcd
|
||||
{ $values { "x" integer } { "y" integer } { "a" integer } { "d" integer } }
|
||||
|
|
|
@ -94,6 +94,28 @@ ARTICLE: "peg.ebnf.sequence" "Sequence"
|
|||
}
|
||||
;
|
||||
|
||||
ARTICLE: "peg.ebnf.grouping" "Group"
|
||||
"Any sequence of rules may be grouped using parentheses (" { $snippet "()" } "). "
|
||||
"The parenthesized sequence can then be modified as a group. Parentheses also "
|
||||
"delimit sets of choices separated by pipe (|) characters."
|
||||
$nl
|
||||
"A group can also be delimited with curly braces (" { $snippet "{}" } "), in "
|
||||
"which case an implicit optional whitespace-matching rule will be inserted between "
|
||||
"rules sequenced within the braces."
|
||||
{ $examples
|
||||
{ $example
|
||||
"USING: prettyprint peg.ebnf ;"
|
||||
"\"abcca\" [EBNF rule=\"a\" (\"b\" | \"c\")* \"a\" EBNF] ."
|
||||
"V{ \"a\" V{ \"b\" \"c\" \"c\" } \"a\" }"
|
||||
}
|
||||
{ $example
|
||||
"USING: prettyprint peg.ebnf ;"
|
||||
"\"ab c\nd \" [EBNF rule={\"a\" \"b\" \"c\" \"d\"} EBNF] ."
|
||||
"V{ \"a\" \"b\" \"c\" \"d\" }"
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
ARTICLE: "peg.ebnf.choice" "Choice"
|
||||
"Any rule element separated by a pipe character (|) is considered a choice. Choices "
|
||||
"are matched against the input stream in order. If a match succeeds then the remaining "
|
||||
|
@ -117,6 +139,18 @@ ARTICLE: "peg.ebnf.choice" "Choice"
|
|||
}
|
||||
;
|
||||
|
||||
ARTICLE: "peg.ebnf.ignore" "Ignore"
|
||||
"Any rule element followed by a tilde (~) will be matched, and its results "
|
||||
"discarded from the AST."
|
||||
{ $examples
|
||||
{ $example
|
||||
"USING: prettyprint peg.ebnf ;"
|
||||
"\"abc\" [EBNF rule=\"a\" \"b\"~ \"c\" EBNF] ."
|
||||
"V{ \"a\" \"c\" }"
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
ARTICLE: "peg.ebnf.option" "Option"
|
||||
"Any rule element followed by a question mark (?) is considered optional. The "
|
||||
"rule is tested against the input. If it succeeds the result is stored in the AST. "
|
||||
|
@ -452,7 +486,9 @@ ARTICLE: "peg.ebnf" "EBNF"
|
|||
{ $subsections "peg.ebnf.strings"
|
||||
"peg.ebnf.any"
|
||||
"peg.ebnf.sequence"
|
||||
"peg.ebnf.grouping"
|
||||
"peg.ebnf.choice"
|
||||
"peg.ebnf.ignore"
|
||||
"peg.ebnf.option"
|
||||
"peg.ebnf.one-or-more"
|
||||
"peg.ebnf.zero-or-more"
|
||||
|
|
|
@ -84,6 +84,26 @@ IN: peg.ebnf.tests
|
|||
"one ((two | three) four)*" 'choice' parse
|
||||
] unit-test
|
||||
|
||||
{
|
||||
T{ ebnf-sequence f
|
||||
V{
|
||||
T{ ebnf-non-terminal f "one" }
|
||||
T{ ebnf-ignore f
|
||||
T{ ebnf-sequence f
|
||||
V{
|
||||
T{ ebnf-choice f
|
||||
V{ T{ ebnf-non-terminal f "two" } T{ ebnf-non-terminal f "three" } }
|
||||
}
|
||||
T{ ebnf-non-terminal f "four" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} [
|
||||
"one ((two | three) four)~" 'choice' parse
|
||||
] unit-test
|
||||
|
||||
{
|
||||
T{ ebnf-sequence f
|
||||
V{
|
||||
|
@ -304,6 +324,26 @@ main = Primary
|
|||
"abc" [EBNF a="a" "b" foo=(a "c") EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ "a" "c" } } [
|
||||
"abc" [EBNF a="a" "b"~ foo=(a "c") EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ V{ "a" V{ "b" "b" } } "c" } } [
|
||||
"abbc" [EBNF a=("a" "b"*) foo=(a "c") EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ "a" "c" } } [
|
||||
"abc" [EBNF a=("a" ("b")~) foo=(a "c") EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ "a" "c" } } [
|
||||
"abc" [EBNF a=("a" "b"~) foo=(a "c") EBNF]
|
||||
] unit-test
|
||||
|
||||
{ "c" } [
|
||||
"abc" [EBNF a=("a" "b")~ foo=(a "c") EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ V{ "a" "b" } "c" } } [
|
||||
"abc" [EBNF a="a" "b" foo={a "c"} EBNF]
|
||||
] unit-test
|
||||
|
@ -360,6 +400,14 @@ main = Primary
|
|||
"ab c ab c" [EBNF a="a" "b" foo={a "c"}* EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ V{ "a" "c" } V{ "a" "c" } } } [
|
||||
"ab c ab c" [EBNF a="a" "b"~ foo={a "c"}* EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ } } [
|
||||
"ab c ab c" [EBNF a="a" "b" foo=(a "c")* EBNF]
|
||||
] unit-test
|
||||
|
||||
{ V{ } } [
|
||||
"ab c ab c" [EBNF a="a" "b" foo=(a "c")* EBNF]
|
||||
] unit-test
|
||||
|
|
|
@ -61,6 +61,7 @@ TUPLE: ebnf-ensure group ;
|
|||
TUPLE: ebnf-ensure-not group ;
|
||||
TUPLE: ebnf-choice options ;
|
||||
TUPLE: ebnf-sequence elements ;
|
||||
TUPLE: ebnf-ignore group ;
|
||||
TUPLE: ebnf-repeat0 group ;
|
||||
TUPLE: ebnf-repeat1 group ;
|
||||
TUPLE: ebnf-optional group ;
|
||||
|
@ -81,6 +82,7 @@ C: <ebnf-ensure> ebnf-ensure
|
|||
C: <ebnf-ensure-not> ebnf-ensure-not
|
||||
C: <ebnf-choice> ebnf-choice
|
||||
C: <ebnf-sequence> ebnf-sequence
|
||||
C: <ebnf-ignore> ebnf-ignore
|
||||
C: <ebnf-repeat0> ebnf-repeat0
|
||||
C: <ebnf-repeat1> ebnf-repeat1
|
||||
C: <ebnf-optional> ebnf-optional
|
||||
|
@ -215,6 +217,7 @@ PEG: escaper ( string -- ast )
|
|||
'range-parser' ,
|
||||
'any-character' ,
|
||||
] choice*
|
||||
[ dup , "~" token hide , ] seq* [ first <ebnf-ignore> ] action ,
|
||||
[ dup , "*" token hide , ] seq* [ first <ebnf-repeat0> ] action ,
|
||||
[ dup , "+" token hide , ] seq* [ first <ebnf-repeat1> ] action ,
|
||||
[ dup , "?[" token ensure-not , "?" token hide , ] seq* [ first <ebnf-optional> ] action ,
|
||||
|
@ -257,11 +260,15 @@ DEFER: 'choice'
|
|||
: 'group' ( -- parser )
|
||||
#! A grouping with no suffix. Used for precedence.
|
||||
[ ] [
|
||||
"~" token sp ensure-not ,
|
||||
"*" token sp ensure-not ,
|
||||
"+" token sp ensure-not ,
|
||||
"?" token sp ensure-not ,
|
||||
] seq* hide grouped ;
|
||||
|
||||
: 'ignore' ( -- parser )
|
||||
[ <ebnf-ignore> ] "~" syntax grouped ;
|
||||
|
||||
: 'repeat0' ( -- parser )
|
||||
[ <ebnf-repeat0> ] "*" syntax grouped ;
|
||||
|
||||
|
@ -305,6 +312,7 @@ DEFER: 'choice'
|
|||
'ensure' sp ,
|
||||
'element' sp ,
|
||||
'group' sp ,
|
||||
'ignore' sp ,
|
||||
'repeat0' sp ,
|
||||
'repeat1' sp ,
|
||||
'optional' sp ,
|
||||
|
@ -425,6 +433,9 @@ M: ebnf-ensure (transform) ( ast -- parser )
|
|||
M: ebnf-ensure-not (transform) ( ast -- parser )
|
||||
transform-group ensure-not ;
|
||||
|
||||
M: ebnf-ignore (transform) ( ast -- parser )
|
||||
transform-group [ drop ignore ] action ;
|
||||
|
||||
M: ebnf-repeat0 (transform) ( ast -- parser )
|
||||
transform-group repeat0 ;
|
||||
|
||||
|
@ -532,7 +543,7 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
|
|||
dup remaining>> [ blank? ] trim [
|
||||
[
|
||||
"Unable to fully parse EBNF. Left to parse was: " %
|
||||
remaining>> %
|
||||
%
|
||||
] "" make throw
|
||||
] unless-empty
|
||||
] [
|
||||
|
|
Loading…
Reference in New Issue