2007-11-27 00:13:36 -05:00
|
|
|
! Copyright (C) 2007 Chris Double.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
|
|
!
|
2008-04-02 23:09:03 -04:00
|
|
|
USING: kernel tools.test peg peg.ebnf words math math.parser sequences ;
|
2008-03-01 17:00:45 -05:00
|
|
|
IN: peg.ebnf.tests
|
2007-11-27 00:13:36 -05:00
|
|
|
|
|
|
|
{ T{ ebnf-non-terminal f "abc" } } [
|
|
|
|
"abc" 'non-terminal' parse parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ T{ ebnf-terminal f "55" } } [
|
2007-11-27 19:05:53 -05:00
|
|
|
"'55'" 'terminal' parse parse-result-ast
|
2007-11-27 00:13:36 -05:00
|
|
|
] unit-test
|
|
|
|
|
2007-11-27 16:28:28 -05:00
|
|
|
{
|
|
|
|
T{ ebnf-rule f
|
2007-11-27 19:05:53 -05:00
|
|
|
"digit"
|
2008-03-19 10:05:40 -04:00
|
|
|
T{ ebnf-choice f
|
|
|
|
V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } }
|
2007-11-27 16:28:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} [
|
2007-11-27 19:05:53 -05:00
|
|
|
"digit = '1' | '2'" 'rule' parse parse-result-ast
|
2007-11-27 16:28:28 -05:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{
|
|
|
|
T{ ebnf-rule f
|
|
|
|
"digit"
|
2008-03-19 10:05:40 -04:00
|
|
|
T{ ebnf-sequence f
|
|
|
|
V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } }
|
2007-11-27 16:28:28 -05:00
|
|
|
}
|
2007-11-27 19:05:53 -05:00
|
|
|
}
|
2007-11-27 16:28:28 -05:00
|
|
|
} [
|
2007-11-27 19:05:53 -05:00
|
|
|
"digit = '1' '2'" 'rule' parse parse-result-ast
|
2007-11-27 21:14:11 -05:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{
|
|
|
|
T{ ebnf-choice f
|
|
|
|
V{
|
|
|
|
T{ ebnf-sequence f
|
|
|
|
V{ T{ ebnf-non-terminal f "one" } T{ ebnf-non-terminal f "two" } }
|
|
|
|
}
|
|
|
|
T{ ebnf-non-terminal f "three" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} [
|
|
|
|
"one two | three" 'choice' parse parse-result-ast
|
2007-11-27 21:26:25 -05:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{
|
|
|
|
T{ ebnf-sequence f
|
|
|
|
V{
|
|
|
|
T{ ebnf-non-terminal f "one" }
|
|
|
|
T{ ebnf-choice f
|
|
|
|
V{ T{ ebnf-non-terminal f "two" } T{ ebnf-non-terminal f "three" } }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} [
|
|
|
|
"one (two | three)" 'choice' parse parse-result-ast
|
2007-11-27 21:32:04 -05:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{
|
|
|
|
T{ ebnf-sequence f
|
|
|
|
V{
|
|
|
|
T{ ebnf-non-terminal f "one" }
|
|
|
|
T{ ebnf-repeat0 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" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} [
|
2008-03-19 08:18:09 -04:00
|
|
|
"one ((two | three) four)*" 'choice' parse parse-result-ast
|
2007-11-27 21:49:14 -05:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{
|
|
|
|
T{ ebnf-sequence f
|
|
|
|
V{
|
|
|
|
T{ ebnf-non-terminal f "one" }
|
|
|
|
T{ ebnf-optional f T{ ebnf-non-terminal f "two" } }
|
|
|
|
T{ ebnf-non-terminal f "three" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} [
|
2008-03-19 08:18:09 -04:00
|
|
|
"one ( two )? three" 'choice' parse parse-result-ast
|
2007-11-27 21:49:14 -05:00
|
|
|
] unit-test
|
2008-03-19 00:34:28 -04:00
|
|
|
|
|
|
|
{ "foo" } [
|
|
|
|
"\"foo\"" 'identifier' parse parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ "foo" } [
|
|
|
|
"'foo'" 'identifier' parse parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ "foo" } [
|
|
|
|
"foo" 'non-terminal' parse parse-result-ast ebnf-non-terminal-symbol
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ "foo" } [
|
|
|
|
"foo]" 'non-terminal' parse parse-result-ast ebnf-non-terminal-symbol
|
|
|
|
] unit-test
|
|
|
|
|
2008-03-19 09:16:30 -04:00
|
|
|
{ V{ "a" "b" } } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"ab" [EBNF foo='a' 'b' EBNF] call parse-result-ast
|
2008-03-19 09:16:30 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ 1 "b" } } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"ab" [EBNF foo=('a')[[ drop 1 ]] 'b' EBNF] call parse-result-ast
|
2008-03-19 09:16:30 -04:00
|
|
|
] unit-test
|
2008-03-19 02:15:52 -04:00
|
|
|
|
2008-03-19 09:16:30 -04:00
|
|
|
{ V{ 1 2 } } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"ab" [EBNF foo=('a') [[ drop 1 ]] ('b') [[ drop 2 ]] EBNF] call parse-result-ast
|
2008-03-19 20:55:19 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ CHAR: A } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"A" [EBNF foo=[A-Z] EBNF] call parse-result-ast
|
2008-03-19 20:55:19 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ CHAR: Z } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"Z" [EBNF foo=[A-Z] EBNF] call parse-result-ast
|
2008-03-19 20:55:19 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ f } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"0" [EBNF foo=[A-Z] EBNF] call
|
2008-03-19 20:55:19 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ CHAR: 0 } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"0" [EBNF foo=[^A-Z] EBNF] call parse-result-ast
|
2008-03-19 20:55:19 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ f } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"A" [EBNF foo=[^A-Z] EBNF] call
|
2008-03-19 20:55:19 -04:00
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ f } [
|
2008-03-20 00:13:27 -04:00
|
|
|
"Z" [EBNF foo=[^A-Z] EBNF] call
|
2008-03-27 06:54:34 -04:00
|
|
|
] unit-test
|
|
|
|
|
2008-03-30 00:17:31 -04:00
|
|
|
{ V{ "1" "+" "foo" } } [
|
|
|
|
"1+1" [EBNF foo='1' '+' '1' [[ drop "foo" ]] EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ "foo" } [
|
|
|
|
"1+1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ "foo" } [
|
|
|
|
"1+1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] | '1' '-' '1' => [[ drop "bar" ]] EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ "bar" } [
|
|
|
|
"1-1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] | '1' '-' '1' => [[ drop "bar" ]] EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
2008-03-30 21:59:22 -04:00
|
|
|
{ 6 } [
|
|
|
|
"4+2" [EBNF num=[0-9] => [[ digit> ]] foo=num:x '+' num:y => [[ drop x y + ]] EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ 6 } [
|
|
|
|
"4+2" [EBNF foo=[0-9]:x '+' [0-9]:y => [[ drop x digit> y digit> + ]] EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
2008-03-30 00:17:31 -04:00
|
|
|
|
2008-03-30 23:50:05 -04:00
|
|
|
{ 10 } [
|
|
|
|
{ 1 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ f } [
|
|
|
|
{ "a" 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ 3 } [
|
|
|
|
{ 1 2 "a" 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
2008-04-01 19:59:12 -04:00
|
|
|
{ f } [
|
|
|
|
"ab" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" " " "b" } } [
|
|
|
|
"a b" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" "\t" "b" } } [
|
|
|
|
"a\tb" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" "\n" "b" } } [
|
|
|
|
"a\nb" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" f "b" } } [
|
|
|
|
"ab" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" " " "b" } } [
|
|
|
|
"a b" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
|
|
|
|
{ V{ "a" "\t" "b" } } [
|
|
|
|
"a\tb" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" "\n" "b" } } [
|
|
|
|
"a\nb" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" "b" } } [
|
|
|
|
"ab" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" "b" } } [
|
|
|
|
"a\tb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "a" "b" } } [
|
|
|
|
"a\nb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ f } [
|
|
|
|
"axb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call
|
|
|
|
] unit-test
|
|
|
|
|
2008-03-28 09:51:49 -04:00
|
|
|
{ V{ V{ 49 } "+" V{ 49 } } } [
|
|
|
|
#! Test direct left recursion.
|
2008-03-28 07:49:39 -04:00
|
|
|
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
|
|
|
"1+1" [EBNF num=([0-9])+ expr=expr "+" num | num EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
2008-03-27 06:54:34 -04:00
|
|
|
|
2008-03-28 09:51:49 -04:00
|
|
|
{ V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [
|
|
|
|
#! Test direct left recursion.
|
2008-03-28 07:41:41 -04:00
|
|
|
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
2008-03-28 09:51:49 -04:00
|
|
|
"1+1+1" [EBNF num=([0-9])+ expr=expr "+" num | num EBNF] call parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [
|
|
|
|
#! Test indirect left recursion.
|
|
|
|
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
|
|
|
"1+1+1" [EBNF num=([0-9])+ x=expr expr=x "+" num | num EBNF] call parse-result-ast
|
2008-03-28 07:49:39 -04:00
|
|
|
] unit-test
|
2008-03-27 06:54:34 -04:00
|
|
|
|
2008-04-02 23:09:03 -04:00
|
|
|
{ t } [
|
|
|
|
"abcd='9' | ('8'):x => [[ drop x ]]" 'ebnf' parse parse-result-remaining empty?
|
|
|
|
] unit-test
|
|
|
|
|
2008-03-28 10:41:40 -04:00
|
|
|
EBNF: primary
|
|
|
|
Primary = PrimaryNoNewArray
|
2008-04-01 19:59:12 -04:00
|
|
|
PrimaryNoNewArray = ClassInstanceCreationExpression
|
2008-03-28 10:41:40 -04:00
|
|
|
| MethodInvocation
|
|
|
|
| FieldAccess
|
|
|
|
| ArrayAccess
|
|
|
|
| "this"
|
|
|
|
ClassInstanceCreationExpression = "new" ClassOrInterfaceType "(" ")"
|
|
|
|
| Primary "." "new" Identifier "(" ")"
|
|
|
|
MethodInvocation = Primary "." MethodName "(" ")"
|
|
|
|
| MethodName "(" ")"
|
|
|
|
FieldAccess = Primary "." Identifier
|
|
|
|
| "super" "." Identifier
|
2008-04-01 19:59:12 -04:00
|
|
|
ArrayAccess = Primary "[" Expression "]"
|
2008-03-28 10:41:40 -04:00
|
|
|
| ExpressionName "[" Expression "]"
|
|
|
|
ClassOrInterfaceType = ClassName | InterfaceTypeName
|
|
|
|
ClassName = "C" | "D"
|
|
|
|
InterfaceTypeName = "I" | "J"
|
|
|
|
Identifier = "x" | "y" | ClassOrInterfaceType
|
|
|
|
MethodName = "m" | "n"
|
|
|
|
ExpressionName = Identifier
|
|
|
|
Expression = "i" | "j"
|
|
|
|
main = Primary
|
|
|
|
;EBNF
|
|
|
|
|
|
|
|
{ "this" } [
|
|
|
|
"this" primary parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ "this" "." "x" } } [
|
|
|
|
"this.x" primary parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ V{ "this" "." "x" } "." "y" } } [
|
|
|
|
"this.x.y" primary parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ V{ "this" "." "x" } "." "m" "(" ")" } } [
|
|
|
|
"this.x.m()" primary parse-result-ast
|
|
|
|
] unit-test
|
|
|
|
|
|
|
|
{ V{ V{ V{ "x" "[" "i" "]" } "[" "j" "]" } "." "y" } } [
|
|
|
|
"x[i][j].y" primary parse-result-ast
|
|
|
|
] unit-test
|