peg: 'convention' -> convention-parser for Factor word names. In EBNF DSL, 'convention' is obviously still allowed.
parent
8e09ee0266
commit
be82224fe9
|
@ -14,7 +14,7 @@ IN: http.parsers
|
||||||
: tspecial? ( ch -- ? )
|
: tspecial? ( ch -- ? )
|
||||||
"()<>@,;:\\\"/[]?={} \t" member? ;
|
"()<>@,;:\\\"/[]?={} \t" member? ;
|
||||||
|
|
||||||
: 'token' ( -- parser )
|
: token-parser ( -- parser )
|
||||||
{ [ control? ] [ tspecial? ] } except-these repeat1 ;
|
{ [ control? ] [ tspecial? ] } except-these repeat1 ;
|
||||||
|
|
||||||
: case-insensitive ( parser -- parser' )
|
: case-insensitive ( parser -- parser' )
|
||||||
|
@ -23,157 +23,157 @@ IN: http.parsers
|
||||||
: case-sensitive ( parser -- parser' )
|
: case-sensitive ( parser -- parser' )
|
||||||
[ flatten >string ] action ;
|
[ flatten >string ] action ;
|
||||||
|
|
||||||
: 'space' ( -- parser )
|
: space-parser ( -- parser )
|
||||||
[ " \t" member? ] satisfy repeat0 hide ;
|
[ " \t" member? ] satisfy repeat0 hide ;
|
||||||
|
|
||||||
: one-of ( strings -- parser )
|
: one-of ( strings -- parser )
|
||||||
[ token ] map choice ;
|
[ token ] map choice ;
|
||||||
|
|
||||||
: 'http-method' ( -- parser )
|
: http-method-parser ( -- parser )
|
||||||
{ "OPTIONS" "GET" "HEAD" "POST" "PUT" "DELETE" "TRACE" "CONNECT" } one-of ;
|
{ "OPTIONS" "GET" "HEAD" "POST" "PUT" "DELETE" "TRACE" "CONNECT" } one-of ;
|
||||||
|
|
||||||
: 'url' ( -- parser )
|
: url-parser ( -- parser )
|
||||||
[ " \t\r\n" member? ] except repeat1 case-sensitive ;
|
[ " \t\r\n" member? ] except repeat1 case-sensitive ;
|
||||||
|
|
||||||
: 'http-version' ( -- parser )
|
: http-version-parser ( -- parser )
|
||||||
[
|
[
|
||||||
"HTTP" token hide ,
|
"HTTP" token hide ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
"/" token hide ,
|
"/" token hide ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
"1" token ,
|
"1" token ,
|
||||||
"." token ,
|
"." token ,
|
||||||
{ "0" "1" } one-of ,
|
{ "0" "1" } one-of ,
|
||||||
] seq* [ "" concat-as ] action ;
|
] seq* [ "" concat-as ] action ;
|
||||||
|
|
||||||
: 'full-request' ( -- parser )
|
: full-request-parser ( -- parser )
|
||||||
[
|
[
|
||||||
'space' ,
|
space-parser ,
|
||||||
'http-method' ,
|
http-method-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'url' ,
|
url-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'http-version' ,
|
http-version-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
] seq* ;
|
] seq* ;
|
||||||
|
|
||||||
: 'simple-request' ( -- parser )
|
: simple-request-parser ( -- parser )
|
||||||
[
|
[
|
||||||
'space' ,
|
space-parser ,
|
||||||
"GET" token ,
|
"GET" token ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'url' ,
|
url-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
] seq* [ "1.0" suffix! ] action ;
|
] seq* [ "1.0" suffix! ] action ;
|
||||||
|
|
||||||
PEG: parse-request-line ( string -- triple )
|
PEG: parse-request-line ( string -- triple )
|
||||||
#! Triple is { method url version }
|
#! Triple is { method url version }
|
||||||
'full-request' 'simple-request' 2array choice ;
|
full-request-parser simple-request-parser 2array choice ;
|
||||||
|
|
||||||
: 'text' ( -- parser )
|
: text-parser ( -- parser )
|
||||||
[ control? ] except ;
|
[ control? ] except ;
|
||||||
|
|
||||||
: 'response-code' ( -- parser )
|
: response-code-parser ( -- parser )
|
||||||
[ digit? ] satisfy 3 exactly-n [ string>number ] action ;
|
[ digit? ] satisfy 3 exactly-n [ string>number ] action ;
|
||||||
|
|
||||||
: 'response-message' ( -- parser )
|
: response-message-parser ( -- parser )
|
||||||
'text' repeat0 case-sensitive ;
|
text-parser repeat0 case-sensitive ;
|
||||||
|
|
||||||
PEG: parse-response-line ( string -- triple )
|
PEG: parse-response-line ( string -- triple )
|
||||||
#! Triple is { version code message }
|
#! Triple is { version code message }
|
||||||
[
|
[
|
||||||
'space' ,
|
space-parser ,
|
||||||
'http-version' ,
|
http-version-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'response-code' ,
|
response-code-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'response-message' ,
|
response-message-parser ,
|
||||||
] seq* just ;
|
] seq* just ;
|
||||||
|
|
||||||
: 'crlf' ( -- parser )
|
: crlf-parser ( -- parser )
|
||||||
"\r\n" token ;
|
"\r\n" token ;
|
||||||
|
|
||||||
: 'lws' ( -- parser )
|
: lws-parser ( -- parser )
|
||||||
[ " \t" member? ] satisfy repeat1 ;
|
[ " \t" member? ] satisfy repeat1 ;
|
||||||
|
|
||||||
: 'qdtext' ( -- parser )
|
: qdtext-parser ( -- parser )
|
||||||
{ [ CHAR: " = ] [ control? ] } except-these ;
|
{ [ CHAR: " = ] [ control? ] } except-these ;
|
||||||
|
|
||||||
: 'quoted-char' ( -- parser )
|
: quoted-char-parser ( -- parser )
|
||||||
"\\" token hide any-char 2seq ;
|
"\\" token hide any-char 2seq ;
|
||||||
|
|
||||||
: 'quoted-string' ( -- parser )
|
: quoted-string-parser ( -- parser )
|
||||||
'quoted-char' 'qdtext' 2choice repeat0 "\"" "\"" surrounded-by ;
|
quoted-char-parser qdtext-parser 2choice repeat0 "\"" "\"" surrounded-by ;
|
||||||
|
|
||||||
: 'ctext' ( -- parser )
|
: ctext-parser ( -- parser )
|
||||||
{ [ control? ] [ "()" member? ] } except-these ;
|
{ [ control? ] [ "()" member? ] } except-these ;
|
||||||
|
|
||||||
: 'comment' ( -- parser )
|
: comment-parser ( -- parser )
|
||||||
'ctext' 'comment' 2choice repeat0 "(" ")" surrounded-by ;
|
ctext-parser comment-parser 2choice repeat0 "(" ")" surrounded-by ;
|
||||||
|
|
||||||
: 'field-name' ( -- parser )
|
: field-name-parser ( -- parser )
|
||||||
'token' case-insensitive ;
|
token-parser case-insensitive ;
|
||||||
|
|
||||||
: 'field-content' ( -- parser )
|
: field-content-parser ( -- parser )
|
||||||
'quoted-string' case-sensitive
|
quoted-string-parser case-sensitive
|
||||||
'text' repeat0 case-sensitive
|
text-parser repeat0 case-sensitive
|
||||||
2choice ;
|
2choice ;
|
||||||
|
|
||||||
PEG: parse-header-line ( string -- pair )
|
PEG: parse-header-line ( string -- pair )
|
||||||
#! Pair is either { name value } or { f value }. If f, its a
|
#! Pair is either { name value } or { f value }. If f, its a
|
||||||
#! continuation of the previous header line.
|
#! continuation of the previous header line.
|
||||||
[
|
[
|
||||||
'field-name' ,
|
field-name-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
":" token hide ,
|
":" token hide ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'field-content' ,
|
field-content-parser ,
|
||||||
] seq*
|
] seq*
|
||||||
[
|
[
|
||||||
'lws' [ drop f ] action ,
|
lws-parser [ drop f ] action ,
|
||||||
'field-content' ,
|
field-content-parser ,
|
||||||
] seq*
|
] seq*
|
||||||
2choice ;
|
2choice ;
|
||||||
|
|
||||||
: 'word' ( -- parser )
|
: word-parser ( -- parser )
|
||||||
'token' 'quoted-string' 2choice ;
|
token-parser quoted-string-parser 2choice ;
|
||||||
|
|
||||||
: 'value' ( -- parser )
|
: value-parser ( -- parser )
|
||||||
'quoted-string'
|
quoted-string-parser
|
||||||
[ ";" member? ] except repeat0
|
[ ";" member? ] except repeat0
|
||||||
2choice case-sensitive ;
|
2choice case-sensitive ;
|
||||||
|
|
||||||
: 'attr' ( -- parser )
|
: attr-parser ( -- parser )
|
||||||
'token' case-sensitive ;
|
token-parser case-sensitive ;
|
||||||
|
|
||||||
: 'av-pair' ( -- parser )
|
: av-pair-parser ( -- parser )
|
||||||
[
|
[
|
||||||
'space' ,
|
space-parser ,
|
||||||
'attr' ,
|
attr-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
[ "=" token , 'space' , 'value' , ] seq* [ last ] action optional ,
|
[ "=" token , space-parser , value-parser , ] seq* [ last ] action optional ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
] seq* ;
|
] seq* ;
|
||||||
|
|
||||||
: 'av-pairs' ( -- parser )
|
: av-pairs-parser ( -- parser )
|
||||||
'av-pair' ";" token list-of optional ;
|
av-pair-parser ";" token list-of optional ;
|
||||||
|
|
||||||
PEG: (parse-set-cookie) ( string -- alist )
|
PEG: (parse-set-cookie) ( string -- alist )
|
||||||
'av-pairs' just [ sift ] action ;
|
av-pairs-parser just [ sift ] action ;
|
||||||
|
|
||||||
: 'cookie-value' ( -- parser )
|
: cookie-value-parser ( -- parser )
|
||||||
[
|
[
|
||||||
'space' ,
|
space-parser ,
|
||||||
'attr' ,
|
attr-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
"=" token hide ,
|
"=" token hide ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
'value' ,
|
value-parser ,
|
||||||
'space' ,
|
space-parser ,
|
||||||
] seq*
|
] seq*
|
||||||
[ ";,=" member? not ] satisfy repeat0 [ drop f ] action
|
[ ";,=" member? not ] satisfy repeat0 [ drop f ] action
|
||||||
2choice ;
|
2choice ;
|
||||||
|
|
||||||
PEG: (parse-cookie) ( string -- alist )
|
PEG: (parse-cookie) ( string -- alist )
|
||||||
'cookie-value' [ ";," member? ] satisfy list-of
|
cookie-value-parser [ ";," member? ] satisfy list-of
|
||||||
optional just [ sift ] action ;
|
optional just [ sift ] action ;
|
||||||
|
|
|
@ -13,44 +13,44 @@ TUPLE: log-entry date level word-name message ;
|
||||||
|
|
||||||
SYMBOL: multiline
|
SYMBOL: multiline
|
||||||
|
|
||||||
: 'date' ( -- parser )
|
: date-parser ( -- parser )
|
||||||
[ "]" member? not ] string-of [
|
[ "]" member? not ] string-of [
|
||||||
dup multiline-header =
|
dup multiline-header =
|
||||||
[ drop multiline ] [ rfc3339>timestamp ] if
|
[ drop multiline ] [ rfc3339>timestamp ] if
|
||||||
] action
|
] action
|
||||||
"[" "]" surrounded-by ;
|
"[" "]" surrounded-by ;
|
||||||
|
|
||||||
: 'log-level' ( -- parser )
|
: log-level-parser ( -- parser )
|
||||||
log-levels keys [
|
log-levels keys [
|
||||||
[ name>> token ] keep [ nip ] curry action
|
[ name>> token ] keep [ nip ] curry action
|
||||||
] map choice ;
|
] map choice ;
|
||||||
|
|
||||||
: 'word-name' ( -- parser )
|
: word-name-parser ( -- parser )
|
||||||
[ " :" member? not ] string-of ;
|
[ " :" member? not ] string-of ;
|
||||||
|
|
||||||
SYMBOL: malformed
|
SYMBOL: malformed
|
||||||
|
|
||||||
: 'malformed-line' ( -- parser )
|
: malformed-line-parser ( -- parser )
|
||||||
[ drop t ] string-of
|
[ drop t ] string-of
|
||||||
[ log-entry new swap >>message malformed >>level ] action ;
|
[ log-entry new swap >>message malformed >>level ] action ;
|
||||||
|
|
||||||
: 'log-message' ( -- parser )
|
: log-message-parser ( -- parser )
|
||||||
[ drop t ] string-of
|
[ drop t ] string-of
|
||||||
[ 1vector ] action ;
|
[ 1vector ] action ;
|
||||||
|
|
||||||
: 'log-line' ( -- parser )
|
: log-line-parser ( -- parser )
|
||||||
[
|
[
|
||||||
'date' ,
|
date-parser ,
|
||||||
" " token hide ,
|
" " token hide ,
|
||||||
'log-level' ,
|
log-level-parser ,
|
||||||
" " token hide ,
|
" " token hide ,
|
||||||
'word-name' ,
|
word-name-parser ,
|
||||||
": " token hide ,
|
": " token hide ,
|
||||||
'log-message' ,
|
log-message-parser ,
|
||||||
] seq* [ first4 log-entry boa ] action
|
] seq* [ first4 log-entry boa ] action
|
||||||
'malformed-line' 2choice ;
|
malformed-line-parser 2choice ;
|
||||||
|
|
||||||
PEG: parse-log-line ( string -- entry ) 'log-line' ;
|
PEG: parse-log-line ( string -- entry ) log-line-parser ;
|
||||||
|
|
||||||
: malformed? ( line -- ? )
|
: malformed? ( line -- ? )
|
||||||
level>> malformed eq? ;
|
level>> malformed eq? ;
|
||||||
|
|
|
@ -7,11 +7,11 @@ namespaces arrays strings eval unicode.data multiline ;
|
||||||
IN: peg.ebnf.tests
|
IN: peg.ebnf.tests
|
||||||
|
|
||||||
{ T{ ebnf-non-terminal f "abc" } } [
|
{ T{ ebnf-non-terminal f "abc" } } [
|
||||||
"abc" 'non-terminal' parse
|
"abc" non-terminal-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ T{ ebnf-terminal f "55" } } [
|
{ T{ ebnf-terminal f "55" } } [
|
||||||
"'55'" 'terminal' parse
|
"'55'" terminal-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"digit = '1' | '2'" 'rule' parse
|
"digit = '1' | '2'" rule-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"digit = '1' '2'" 'rule' parse
|
"digit = '1' '2'" rule-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one two | three" 'choice' parse
|
"one two | three" choice-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -61,7 +61,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one {two | three}" 'choice' parse
|
"one {two | three}" choice-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -81,7 +81,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one ((two | three) four)*" 'choice' parse
|
"one ((two | three) four)*" choice-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -101,7 +101,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one ((two | three) four)~" 'choice' parse
|
"one ((two | three) four)~" choice-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -113,23 +113,23 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one ( two )? three" 'choice' parse
|
"one ( two )? three" choice-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"\"foo\"" 'identifier' parse
|
"\"foo\"" identifier-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"'foo'" 'identifier' parse
|
"'foo'" identifier-parser parse
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"foo" 'non-terminal' parse symbol>>
|
"foo" non-terminal-parser parse symbol>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"foo]" 'non-terminal' parse symbol>>
|
"foo]" non-terminal-parser parse symbol>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "b" } } [
|
{ V{ "a" "b" } } [
|
||||||
|
@ -272,7 +272,7 @@ IN: peg.ebnf.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"abcd='9' | ('8'):x => [[ x ]]" 'ebnf' (parse) remaining>> empty?
|
"abcd='9' | ('8'):x => [[ x ]]" ebnf-parser (parse) remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
EBNF: primary
|
EBNF: primary
|
||||||
|
@ -431,29 +431,29 @@ main = Primary
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"number=(digit)+:n 'a'" 'ebnf' (parse) remaining>> length zero?
|
"number=(digit)+:n 'a'" ebnf-parser (parse) remaining>> length zero?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"number=(digit)+ 'a'" 'ebnf' (parse) remaining>> length zero?
|
"number=(digit)+ 'a'" ebnf-parser (parse) remaining>> length zero?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"number=digit+ 'a'" 'ebnf' (parse) remaining>> length zero?
|
"number=digit+ 'a'" ebnf-parser (parse) remaining>> length zero?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"number=digit+:n 'a'" 'ebnf' (parse) remaining>> length zero?
|
"number=digit+:n 'a'" ebnf-parser (parse) remaining>> length zero?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"foo=(name):n !(keyword) => [[ n ]]" 'rule' parse
|
"foo=(name):n !(keyword) => [[ n ]]" rule-parser parse
|
||||||
"foo=name:n !(keyword) => [[ n ]]" 'rule' parse =
|
"foo=name:n !(keyword) => [[ n ]]" rule-parser parse =
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"foo=!(keyword) (name):n => [[ n ]]" 'rule' parse
|
"foo=!(keyword) (name):n => [[ n ]]" rule-parser parse
|
||||||
"foo=!(keyword) name:n => [[ n ]]" 'rule' parse =
|
"foo=!(keyword) name:n => [[ n ]]" rule-parser parse =
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
<<
|
<<
|
||||||
|
@ -501,7 +501,7 @@ foo=<foreign any-char> 'd'
|
||||||
{ t } [
|
{ t } [
|
||||||
#! Rule lookup occurs in a namespace. This causes an incorrect duplicate rule
|
#! Rule lookup occurs in a namespace. This causes an incorrect duplicate rule
|
||||||
#! if a var in a namespace is set. This unit test is to remind me to fix this.
|
#! if a var in a namespace is set. This unit test is to remind me to fix this.
|
||||||
[ "fail" "foo" set "foo='a'" 'ebnf' parse transform drop t ] with-scope
|
[ "fail" "foo" set "foo='a'" ebnf-parser parse transform drop t ] with-scope
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
#! Tokenizer tests
|
#! Tokenizer tests
|
||||||
|
|
|
@ -103,7 +103,7 @@ C: <ebnf> ebnf
|
||||||
token sp hide ;
|
token sp hide ;
|
||||||
|
|
||||||
: syntax-pack ( begin parser end -- parser )
|
: syntax-pack ( begin parser end -- parser )
|
||||||
#! Parse 'parser' surrounded by syntax elements
|
#! Parse parser-parser surrounded by syntax elements
|
||||||
#! begin and end.
|
#! begin and end.
|
||||||
[ syntax ] 2dip syntax pack ;
|
[ syntax ] 2dip syntax pack ;
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ C: <ebnf> ebnf
|
||||||
"\r" token [ drop "\\r" ] action ,
|
"\r" token [ drop "\\r" ] action ,
|
||||||
] choice* replace ;
|
] choice* replace ;
|
||||||
|
|
||||||
: 'identifier' ( -- parser )
|
: identifier-parser ( -- parser )
|
||||||
#! Return a parser that parses an identifer delimited by
|
#! Return a parser that parses an identifer delimited by
|
||||||
#! a quotation character. The quotation can be single
|
#! a quotation character. The quotation can be single
|
||||||
#! or double quotes. The AST produced is the identifier
|
#! or double quotes. The AST produced is the identifier
|
||||||
|
@ -124,7 +124,7 @@ C: <ebnf> ebnf
|
||||||
[ CHAR: ' = not ] satisfy repeat1 "'" "'" surrounded-by ,
|
[ CHAR: ' = not ] satisfy repeat1 "'" "'" surrounded-by ,
|
||||||
] choice* [ >string unescape-string ] action ;
|
] choice* [ >string unescape-string ] action ;
|
||||||
|
|
||||||
: 'non-terminal' ( -- parser )
|
: non-terminal-parser ( -- parser )
|
||||||
#! A non-terminal is the name of another rule. It can
|
#! A non-terminal is the name of another rule. It can
|
||||||
#! be any non-blank character except for characters used
|
#! be any non-blank character except for characters used
|
||||||
#! in the EBNF syntax itself.
|
#! in the EBNF syntax itself.
|
||||||
|
@ -154,12 +154,12 @@ C: <ebnf> ebnf
|
||||||
} 1|| not
|
} 1|| not
|
||||||
] satisfy repeat1 [ >string <ebnf-non-terminal> ] action ;
|
] satisfy repeat1 [ >string <ebnf-non-terminal> ] action ;
|
||||||
|
|
||||||
: 'terminal' ( -- parser )
|
: terminal-parser ( -- parser )
|
||||||
#! A terminal is an identifier enclosed in quotations
|
#! A terminal is an identifier enclosed in quotations
|
||||||
#! and it represents the literal value of the identifier.
|
#! and it represents the literal value of the identifier.
|
||||||
'identifier' [ <ebnf-terminal> ] action ;
|
identifier-parser [ <ebnf-terminal> ] action ;
|
||||||
|
|
||||||
: 'foreign-name' ( -- parser )
|
: foreign-name-parser ( -- parser )
|
||||||
#! Parse a valid foreign parser name
|
#! Parse a valid foreign parser name
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -168,20 +168,20 @@ C: <ebnf> ebnf
|
||||||
} 1|| not
|
} 1|| not
|
||||||
] satisfy repeat1 [ >string ] action ;
|
] satisfy repeat1 [ >string ] action ;
|
||||||
|
|
||||||
: 'foreign' ( -- parser )
|
: foreign-parser ( -- parser )
|
||||||
#! A foreign call is a call to a rule in another ebnf grammar
|
#! A foreign call is a call to a rule in another ebnf grammar
|
||||||
[
|
[
|
||||||
"<foreign" syntax ,
|
"<foreign" syntax ,
|
||||||
'foreign-name' sp ,
|
foreign-name-parser sp ,
|
||||||
'foreign-name' sp optional ,
|
foreign-name-parser sp optional ,
|
||||||
">" syntax ,
|
">" syntax ,
|
||||||
] seq* [ first2 <ebnf-foreign> ] action ;
|
] seq* [ first2 <ebnf-foreign> ] action ;
|
||||||
|
|
||||||
: 'any-character' ( -- parser )
|
: any-character-parser ( -- parser )
|
||||||
#! A parser to match the symbol for any character match.
|
#! A parser to match the symbol for any character match.
|
||||||
[ CHAR: . = ] satisfy [ drop <ebnf-any-character> ] action ;
|
[ CHAR: . = ] satisfy [ drop <ebnf-any-character> ] action ;
|
||||||
|
|
||||||
: 'range-parser' ( -- parser )
|
: range-parser-parser ( -- parser )
|
||||||
#! Match the syntax for declaring character ranges
|
#! Match the syntax for declaring character ranges
|
||||||
[
|
[
|
||||||
[ "[" syntax , "[" token ensure-not , ] seq* hide ,
|
[ "[" syntax , "[" token ensure-not , ] seq* hide ,
|
||||||
|
@ -189,7 +189,7 @@ C: <ebnf> ebnf
|
||||||
"]" syntax ,
|
"]" syntax ,
|
||||||
] seq* [ first >string unescape-string <ebnf-range> ] action ;
|
] seq* [ first >string unescape-string <ebnf-range> ] action ;
|
||||||
|
|
||||||
: ('element') ( -- parser )
|
: (element-parser) ( -- parser )
|
||||||
#! An element of a rule. It can be a terminal or a
|
#! An element of a rule. It can be a terminal or a
|
||||||
#! non-terminal but must not be followed by a "=".
|
#! non-terminal but must not be followed by a "=".
|
||||||
#! The latter indicates that it is the beginning of a
|
#! The latter indicates that it is the beginning of a
|
||||||
|
@ -197,11 +197,11 @@ C: <ebnf> ebnf
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
'non-terminal' ,
|
non-terminal-parser ,
|
||||||
'terminal' ,
|
terminal-parser ,
|
||||||
'foreign' ,
|
foreign-parser ,
|
||||||
'range-parser' ,
|
range-parser-parser ,
|
||||||
'any-character' ,
|
any-character-parser ,
|
||||||
] choice*
|
] choice*
|
||||||
[ dup , "~" token hide , ] seq* [ first <ebnf-ignore> ] action ,
|
[ dup , "~" token hide , ] seq* [ first <ebnf-ignore> ] action ,
|
||||||
[ dup , "*" token hide , ] seq* [ first <ebnf-repeat0> ] action ,
|
[ dup , "*" token hide , ] seq* [ first <ebnf-repeat0> ] action ,
|
||||||
|
@ -215,19 +215,19 @@ C: <ebnf> ebnf
|
||||||
] choice* ,
|
] choice* ,
|
||||||
] seq* [ first ] action ;
|
] seq* [ first ] action ;
|
||||||
|
|
||||||
DEFER: 'action'
|
DEFER: action-parser
|
||||||
|
|
||||||
: 'element' ( -- parser )
|
: element-parser ( -- parser )
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
('element') , ":" syntax ,
|
(element-parser) , ":" syntax ,
|
||||||
"a-zA-Z_" range-pattern
|
"a-zA-Z_" range-pattern
|
||||||
"a-zA-Z0-9_-" range-pattern repeat1 2seq [ first2 swap prefix >string ] action ,
|
"a-zA-Z0-9_-" range-pattern repeat1 2seq [ first2 swap prefix >string ] action ,
|
||||||
] seq* [ first2 <ebnf-var> ] action ,
|
] seq* [ first2 <ebnf-var> ] action ,
|
||||||
('element') ,
|
(element-parser) ,
|
||||||
] choice* ;
|
] choice* ;
|
||||||
|
|
||||||
DEFER: 'choice'
|
DEFER: choice-parser
|
||||||
|
|
||||||
: grouped ( quot suffix -- parser )
|
: grouped ( quot suffix -- parser )
|
||||||
#! Parse a group of choices, with a suffix indicating
|
#! Parse a group of choices, with a suffix indicating
|
||||||
|
@ -235,15 +235,15 @@ DEFER: 'choice'
|
||||||
#! an quot that is the action that produces the AST.
|
#! an quot that is the action that produces the AST.
|
||||||
2dup
|
2dup
|
||||||
[
|
[
|
||||||
"(" [ 'choice' sp ] delay ")" syntax-pack
|
"(" [ choice-parser sp ] delay ")" syntax-pack
|
||||||
swap 2seq
|
swap 2seq
|
||||||
[ first ] rot compose action ,
|
[ first ] rot compose action ,
|
||||||
"{" [ 'choice' sp ] delay "}" syntax-pack
|
"{" [ choice-parser sp ] delay "}" syntax-pack
|
||||||
swap 2seq
|
swap 2seq
|
||||||
[ first <ebnf-whitespace> ] rot compose action ,
|
[ first <ebnf-whitespace> ] rot compose action ,
|
||||||
] choice* ;
|
] choice* ;
|
||||||
|
|
||||||
: 'group' ( -- parser )
|
: group-parser ( -- parser )
|
||||||
#! A grouping with no suffix. Used for precedence.
|
#! A grouping with no suffix. Used for precedence.
|
||||||
[ ] [
|
[ ] [
|
||||||
"~" token sp ensure-not ,
|
"~" token sp ensure-not ,
|
||||||
|
@ -252,115 +252,115 @@ DEFER: 'choice'
|
||||||
"?" token sp ensure-not ,
|
"?" token sp ensure-not ,
|
||||||
] seq* hide grouped ;
|
] seq* hide grouped ;
|
||||||
|
|
||||||
: 'ignore' ( -- parser )
|
: ignore-parser ( -- parser )
|
||||||
[ <ebnf-ignore> ] "~" syntax grouped ;
|
[ <ebnf-ignore> ] "~" syntax grouped ;
|
||||||
|
|
||||||
: 'repeat0' ( -- parser )
|
: repeat0-parser ( -- parser )
|
||||||
[ <ebnf-repeat0> ] "*" syntax grouped ;
|
[ <ebnf-repeat0> ] "*" syntax grouped ;
|
||||||
|
|
||||||
: 'repeat1' ( -- parser )
|
: repeat1-parser ( -- parser )
|
||||||
[ <ebnf-repeat1> ] "+" syntax grouped ;
|
[ <ebnf-repeat1> ] "+" syntax grouped ;
|
||||||
|
|
||||||
: 'optional' ( -- parser )
|
: optional-parser ( -- parser )
|
||||||
[ <ebnf-optional> ] "?" syntax grouped ;
|
[ <ebnf-optional> ] "?" syntax grouped ;
|
||||||
|
|
||||||
: 'factor-code' ( -- parser )
|
: factor-code-parser ( -- parser )
|
||||||
[
|
[
|
||||||
"]]" token ensure-not ,
|
"]]" token ensure-not ,
|
||||||
"]?" token ensure-not ,
|
"]?" token ensure-not ,
|
||||||
[ drop t ] satisfy ,
|
[ drop t ] satisfy ,
|
||||||
] seq* repeat0 [ "" concat-as ] action ;
|
] seq* repeat0 [ "" concat-as ] action ;
|
||||||
|
|
||||||
: 'ensure-not' ( -- parser )
|
: ensure-not-parser ( -- parser )
|
||||||
#! Parses the '!' syntax to ensure that
|
#! Parses the '!' syntax to ensure that
|
||||||
#! something that matches the following elements do
|
#! something that matches the following elements do
|
||||||
#! not exist in the parse stream.
|
#! not exist in the parse stream.
|
||||||
[
|
[
|
||||||
"!" syntax ,
|
"!" syntax ,
|
||||||
'group' sp ,
|
group-parser sp ,
|
||||||
] seq* [ first <ebnf-ensure-not> ] action ;
|
] seq* [ first <ebnf-ensure-not> ] action ;
|
||||||
|
|
||||||
: 'ensure' ( -- parser )
|
: ensure-parser ( -- parser )
|
||||||
#! Parses the '&' syntax to ensure that
|
#! Parses the '&' syntax to ensure that
|
||||||
#! something that matches the following elements does
|
#! something that matches the following elements does
|
||||||
#! exist in the parse stream.
|
#! exist in the parse stream.
|
||||||
[
|
[
|
||||||
"&" syntax ,
|
"&" syntax ,
|
||||||
'group' sp ,
|
group-parser sp ,
|
||||||
] seq* [ first <ebnf-ensure> ] action ;
|
] seq* [ first <ebnf-ensure> ] action ;
|
||||||
|
|
||||||
: ('sequence') ( -- parser )
|
: (sequence-parser) ( -- parser )
|
||||||
#! A sequence of terminals and non-terminals, including
|
#! A sequence of terminals and non-terminals, including
|
||||||
#! groupings of those.
|
#! groupings of those.
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
'ensure-not' sp ,
|
ensure-not-parser sp ,
|
||||||
'ensure' sp ,
|
ensure-parser sp ,
|
||||||
'element' sp ,
|
element-parser sp ,
|
||||||
'group' sp ,
|
group-parser sp ,
|
||||||
'ignore' sp ,
|
ignore-parser sp ,
|
||||||
'repeat0' sp ,
|
repeat0-parser sp ,
|
||||||
'repeat1' sp ,
|
repeat1-parser sp ,
|
||||||
'optional' sp ,
|
optional-parser sp ,
|
||||||
] choice*
|
] choice*
|
||||||
[ dup , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , ] seq* [ first2 <ebnf-var> ] action ,
|
[ dup , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , ] seq* [ first2 <ebnf-var> ] action ,
|
||||||
,
|
,
|
||||||
] choice* ;
|
] choice* ;
|
||||||
|
|
||||||
: 'action' ( -- parser )
|
: action-parser ( -- parser )
|
||||||
"[[" 'factor-code' "]]" syntax-pack ;
|
"[[" factor-code-parser "]]" syntax-pack ;
|
||||||
|
|
||||||
: 'semantic' ( -- parser )
|
: semantic-parser ( -- parser )
|
||||||
"?[" 'factor-code' "]?" syntax-pack ;
|
"?[" factor-code-parser "]?" syntax-pack ;
|
||||||
|
|
||||||
: 'sequence' ( -- parser )
|
: sequence-parser ( -- parser )
|
||||||
#! A sequence of terminals and non-terminals, including
|
#! A sequence of terminals and non-terminals, including
|
||||||
#! groupings of those.
|
#! groupings of those.
|
||||||
[
|
[
|
||||||
[ ('sequence') , 'action' , ] seq*
|
[ (sequence-parser) , action-parser , ] seq*
|
||||||
[ first2 <ebnf-action> ] action ,
|
[ first2 <ebnf-action> ] action ,
|
||||||
|
|
||||||
[ ('sequence') , 'semantic' , ] seq*
|
[ (sequence-parser) , semantic-parser , ] seq*
|
||||||
[ first2 <ebnf-semantic> ] action ,
|
[ first2 <ebnf-semantic> ] action ,
|
||||||
|
|
||||||
('sequence') ,
|
(sequence-parser) ,
|
||||||
] choice* repeat1 [
|
] choice* repeat1 [
|
||||||
dup length 1 = [ first ] [ <ebnf-sequence> ] if
|
dup length 1 = [ first ] [ <ebnf-sequence> ] if
|
||||||
] action ;
|
] action ;
|
||||||
|
|
||||||
: 'actioned-sequence' ( -- parser )
|
: actioned-sequence-parser ( -- parser )
|
||||||
[
|
[
|
||||||
[ 'sequence' , "=>" syntax , 'action' , ] seq*
|
[ sequence-parser , "=>" syntax , action-parser , ] seq*
|
||||||
[ first2 <ebnf-action> ] action ,
|
[ first2 <ebnf-action> ] action ,
|
||||||
'sequence' ,
|
sequence-parser ,
|
||||||
] choice* ;
|
] choice* ;
|
||||||
|
|
||||||
: 'choice' ( -- parser )
|
: choice-parser ( -- parser )
|
||||||
'actioned-sequence' sp repeat1 [
|
actioned-sequence-parser sp repeat1 [
|
||||||
dup length 1 = [ first ] [ <ebnf-sequence> ] if
|
dup length 1 = [ first ] [ <ebnf-sequence> ] if
|
||||||
] action "|" token sp list-of [
|
] action "|" token sp list-of [
|
||||||
dup length 1 = [ first ] [ <ebnf-choice> ] if
|
dup length 1 = [ first ] [ <ebnf-choice> ] if
|
||||||
] action ;
|
] action ;
|
||||||
|
|
||||||
: 'tokenizer' ( -- parser )
|
: tokenizer-parser ( -- parser )
|
||||||
[
|
[
|
||||||
"tokenizer" syntax ,
|
"tokenizer" syntax ,
|
||||||
"=" syntax ,
|
"=" syntax ,
|
||||||
">" token ensure-not ,
|
">" token ensure-not ,
|
||||||
[ "default" token sp , 'choice' , ] choice* ,
|
[ "default" token sp , choice-parser , ] choice* ,
|
||||||
] seq* [ first <ebnf-tokenizer> ] action ;
|
] seq* [ first <ebnf-tokenizer> ] action ;
|
||||||
|
|
||||||
: 'rule' ( -- parser )
|
: rule-parser ( -- parser )
|
||||||
[
|
[
|
||||||
"tokenizer" token ensure-not ,
|
"tokenizer" token ensure-not ,
|
||||||
'non-terminal' [ symbol>> ] action ,
|
non-terminal-parser [ symbol>> ] action ,
|
||||||
"=" syntax ,
|
"=" syntax ,
|
||||||
">" token ensure-not ,
|
">" token ensure-not ,
|
||||||
'choice' ,
|
choice-parser ,
|
||||||
] seq* [ first2 <ebnf-rule> ] action ;
|
] seq* [ first2 <ebnf-rule> ] action ;
|
||||||
|
|
||||||
: 'ebnf' ( -- parser )
|
: ebnf-parser ( -- parser )
|
||||||
[ 'tokenizer' sp , 'rule' sp , ] choice* repeat1 [ <ebnf> ] action ;
|
[ tokenizer-parser sp , rule-parser sp , ] choice* repeat1 [ <ebnf> ] action ;
|
||||||
|
|
||||||
GENERIC: (transform) ( ast -- parser )
|
GENERIC: (transform) ( ast -- parser )
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
|
||||||
] [ ] make box ;
|
] [ ] make box ;
|
||||||
|
|
||||||
: transform-ebnf ( string -- object )
|
: transform-ebnf ( string -- object )
|
||||||
'ebnf' parse transform ;
|
ebnf-parser parse transform ;
|
||||||
|
|
||||||
ERROR: unable-to-fully-parse-ebnf remaining ;
|
ERROR: unable-to-fully-parse-ebnf remaining ;
|
||||||
|
|
||||||
|
@ -546,7 +546,7 @@ ERROR: could-not-parse-ebnf ;
|
||||||
] if* ;
|
] if* ;
|
||||||
|
|
||||||
: parse-ebnf ( string -- hashtable )
|
: parse-ebnf ( string -- hashtable )
|
||||||
'ebnf' (parse) check-parse-result ast>> transform ;
|
ebnf-parser (parse) check-parse-result ast>> transform ;
|
||||||
|
|
||||||
: ebnf>quot ( string -- hashtable quot )
|
: ebnf>quot ( string -- hashtable quot )
|
||||||
parse-ebnf dup dup parser [ main of compile ] with-variable
|
parse-ebnf dup dup parser [ main of compile ] with-variable
|
||||||
|
|
|
@ -12,7 +12,7 @@ HELP: 1token
|
||||||
"Calls 1string on a character and returns a parser that matches that character."
|
"Calls 1string on a character and returns a parser that matches that character."
|
||||||
} { $examples
|
} { $examples
|
||||||
{ $example "USING: peg peg.parsers prettyprint ;" "\"a\" CHAR: a 1token parse ." "\"a\"" }
|
{ $example "USING: peg peg.parsers prettyprint ;" "\"a\" CHAR: a 1token parse ." "\"a\"" }
|
||||||
} { $see-also 'string' } ;
|
} { $see-also string-parser } ;
|
||||||
|
|
||||||
HELP: (list-of)
|
HELP: (list-of)
|
||||||
{ $values
|
{ $values
|
||||||
|
@ -124,7 +124,7 @@ HELP: pack
|
||||||
} { $description
|
} { $description
|
||||||
"Returns a parser that parses the begin, body, and end parsers in order. The begin and end parsers are hidden."
|
"Returns a parser that parses the begin, body, and end parsers in order. The begin and end parsers are hidden."
|
||||||
} { $examples
|
} { $examples
|
||||||
{ $example "USING: peg peg.parsers prettyprint ;" "\"hi123bye\" \"hi\" token 'integer' \"bye\" token pack parse ." "123" }
|
{ $example "USING: peg peg.parsers prettyprint ;" "\"hi123bye\" \"hi\" token integer-parser \"bye\" token pack parse ." "123" }
|
||||||
} { $see-also surrounded-by } ;
|
} { $see-also surrounded-by } ;
|
||||||
|
|
||||||
HELP: surrounded-by
|
HELP: surrounded-by
|
||||||
|
@ -136,29 +136,29 @@ HELP: surrounded-by
|
||||||
} { $description
|
} { $description
|
||||||
"Calls token on begin and end to make them into string parsers. Returns a parser that parses the begin, body, and end parsers in order. The begin and end parsers are hidden."
|
"Calls token on begin and end to make them into string parsers. Returns a parser that parses the begin, body, and end parsers in order. The begin and end parsers are hidden."
|
||||||
} { $examples
|
} { $examples
|
||||||
{ $example "USING: peg peg.parsers prettyprint ;" "\"hi123bye\" 'integer' \"hi\" \"bye\" surrounded-by parse ." "123" }
|
{ $example "USING: peg peg.parsers prettyprint ;" "\"hi123bye\" integer-parser \"hi\" \"bye\" surrounded-by parse ." "123" }
|
||||||
} { $see-also pack } ;
|
} { $see-also pack } ;
|
||||||
|
|
||||||
HELP: 'digit'
|
HELP: digit-parser
|
||||||
{ $values
|
{ $values
|
||||||
{ "parser" "a parser" }
|
{ "parser" "a parser" }
|
||||||
} { $description
|
} { $description
|
||||||
"Returns a parser that matches a single digit as defined by the " { $link digit? } " word."
|
"Returns a parser that matches a single digit as defined by the " { $link digit? } " word."
|
||||||
} { $see-also 'integer' } ;
|
} { $see-also integer-parser } ;
|
||||||
|
|
||||||
HELP: 'integer'
|
HELP: integer-parser
|
||||||
{ $values
|
{ $values
|
||||||
{ "parser" "a parser" }
|
{ "parser" "a parser" }
|
||||||
} { $description
|
} { $description
|
||||||
"Returns a parser that matches an integer composed of digits, as defined by the " { $link 'digit' } " word."
|
"Returns a parser that matches an integer composed of digits, as defined by the " { $link digit-parser } " word."
|
||||||
} { $see-also 'digit' 'string' } ;
|
} { $see-also digit-parser string-parser } ;
|
||||||
|
|
||||||
HELP: 'string'
|
HELP: string-parser
|
||||||
{ $values
|
{ $values
|
||||||
{ "parser" "a parser" }
|
{ "parser" "a parser" }
|
||||||
} { $description
|
} { $description
|
||||||
"Returns a parser that matches an string composed of a \", anything that is not \", and another \"."
|
"Returns a parser that matches an string composed of a \", anything that is not \", and another \"."
|
||||||
} { $see-also 'integer' } ;
|
} { $see-also integer-parser } ;
|
||||||
|
|
||||||
HELP: range-pattern
|
HELP: range-pattern
|
||||||
{ $values
|
{ $values
|
||||||
|
|
|
@ -62,18 +62,18 @@ PRIVATE>
|
||||||
[ flatten-vectors ] action ;
|
[ flatten-vectors ] action ;
|
||||||
|
|
||||||
: pack ( begin body end -- parser )
|
: pack ( begin body end -- parser )
|
||||||
[ hide ] 2dip hide 3seq [ first ] action ;
|
[ hide ] [ ] [ hide ] tri* 3seq [ first ] action ;
|
||||||
|
|
||||||
: surrounded-by ( parser begin end -- parser' )
|
: surrounded-by ( parser begin end -- parser' )
|
||||||
[ token ] bi@ swapd pack ;
|
[ token ] bi@ swapd pack ;
|
||||||
|
|
||||||
: 'digit' ( -- parser )
|
: digit-parser ( -- parser )
|
||||||
[ digit? ] satisfy [ digit> ] action ;
|
[ digit? ] satisfy [ digit> ] action ;
|
||||||
|
|
||||||
: 'integer' ( -- parser )
|
: integer-parser ( -- parser )
|
||||||
[ digit? ] satisfy repeat1 [ string>number ] action ;
|
[ digit? ] satisfy repeat1 [ string>number ] action ;
|
||||||
|
|
||||||
: 'string' ( -- parser )
|
: string-parser ( -- parser )
|
||||||
[
|
[
|
||||||
[ CHAR: " = ] satisfy hide ,
|
[ CHAR: " = ] satisfy hide ,
|
||||||
[ CHAR: " = not ] satisfy repeat0 ,
|
[ CHAR: " = not ] satisfy repeat0 ,
|
||||||
|
|
|
@ -24,8 +24,8 @@ HELP: search
|
||||||
"parser."
|
"parser."
|
||||||
}
|
}
|
||||||
|
|
||||||
{ $example "USING: peg.parsers peg.search prettyprint ;" "\"one 123 two 456\" 'integer' search ." "V{ 123 456 }" }
|
{ $example "USING: peg.parsers peg.search prettyprint ;" "\"one 123 two 456\" integer-parser search ." "V{ 123 456 }" }
|
||||||
{ $example "USING: peg peg.parsers peg.search prettyprint ;" "\"one 123 \\\"hello\\\" two 456\" 'integer' 'string' 2choice search ." "V{ 123 \"hello\" 456 }" }
|
{ $example "USING: peg peg.parsers peg.search prettyprint ;" "\"one 123 \\\"hello\\\" two 456\" integer-parser string-parser 2choice search ." "V{ 123 \"hello\" 456 }" }
|
||||||
{ $see-also replace } ;
|
{ $see-also replace } ;
|
||||||
|
|
||||||
HELP: replace
|
HELP: replace
|
||||||
|
@ -39,5 +39,5 @@ HELP: replace
|
||||||
"successfully parse with the given parser replaced with "
|
"successfully parse with the given parser replaced with "
|
||||||
"the result of that parser."
|
"the result of that parser."
|
||||||
}
|
}
|
||||||
{ $example "USING: math math.parser peg peg.parsers peg.search prettyprint ;" "\"one 123 two 456\" 'integer' [ 2 * number>string ] action replace ." "\"one 246 two 912\"" }
|
{ $example "USING: math math.parser peg peg.parsers peg.search prettyprint ;" "\"one 123 two 456\" integer-parser [ 2 * number>string ] action replace ." "\"one 246 two 912\"" }
|
||||||
{ $see-also search } ;
|
{ $see-also search } ;
|
||||||
|
|
|
@ -6,13 +6,13 @@ peg.search ;
|
||||||
IN: peg.search.tests
|
IN: peg.search.tests
|
||||||
|
|
||||||
{ V{ 123 456 } } [
|
{ V{ 123 456 } } [
|
||||||
"abc 123 def 456" 'integer' search
|
"abc 123 def 456" integer-parser search
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ 123 "hello" 456 } } [
|
{ V{ 123 "hello" 456 } } [
|
||||||
"one 123 \"hello\" two 456" 'integer' 'string' 2array choice search
|
"one 123 \"hello\" two 456" integer-parser string-parser 2array choice search
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "abc 246 def 912" } [
|
{ "abc 246 def 912" } [
|
||||||
"abc 123 def 456" 'integer' [ 2 * number>string ] action replace
|
"abc 123 def 456" integer-parser [ 2 * number>string ] action replace
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
Loading…
Reference in New Issue