Merge remote branch 'upstream/master'

db4
John Benediktsson 2011-06-07 11:11:48 -07:00
commit 7337e38848
4 changed files with 97 additions and 2 deletions

View File

@ -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 } }

View File

@ -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"

View File

@ -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

View File

@ -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
] [