! Copyright (C) 2007 Chris Double. ! See http://factorcode.org/license.txt for BSD license. ! USING: kernel tools.test peg peg.ebnf words ; IN: peg.ebnf.tests { T{ ebnf-non-terminal f "abc" } } [ "abc" 'non-terminal' parse parse-result-ast ] unit-test { T{ ebnf-terminal f "55" } } [ "'55'" 'terminal' parse parse-result-ast ] unit-test { T{ ebnf-rule f "digit" T{ ebnf-choice f V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } } } } } [ "digit = '1' | '2'" 'rule' parse parse-result-ast ] unit-test { T{ ebnf-rule f "digit" T{ ebnf-sequence f V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } } } } } [ "digit = '1' '2'" 'rule' parse parse-result-ast ] 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 ] 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 ] 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" } } } } } } } [ "one ((two | three) four)*" 'choice' parse parse-result-ast ] 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" } } } } [ "one ( two )? three" 'choice' parse parse-result-ast ] unit-test { "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 { V{ "a" "b" } } [ "ab" [EBNF foo='a' 'b' EBNF] call parse-result-ast ] unit-test { V{ 1 "b" } } [ "ab" [EBNF foo=('a')[[ drop 1 ]] 'b' EBNF] call parse-result-ast ] unit-test { V{ 1 2 } } [ "ab" [EBNF foo=('a') [[ drop 1 ]] ('b') [[ drop 2 ]] EBNF] call parse-result-ast ] unit-test { CHAR: A } [ "A" [EBNF foo=[A-Z] EBNF] call parse-result-ast ] unit-test { CHAR: Z } [ "Z" [EBNF foo=[A-Z] EBNF] call parse-result-ast ] unit-test { f } [ "0" [EBNF foo=[A-Z] EBNF] call ] unit-test { CHAR: 0 } [ "0" [EBNF foo=[^A-Z] EBNF] call parse-result-ast ] unit-test { f } [ "A" [EBNF foo=[^A-Z] EBNF] call ] unit-test { f } [ "Z" [EBNF foo=[^A-Z] EBNF] call ] unit-test { V{ V{ 49 } "+" V{ 49 } } } [ #! Test direct left recursion. #! 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 { V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [ #! Test direct left recursion. #! Using packrat, so first part of expr fails, causing 2nd choice to be used "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 ] unit-test EBNF: primary Primary = PrimaryNoNewArray PrimaryNoNewArray = ClassInstanceCreationExpression | MethodInvocation | FieldAccess | ArrayAccess | "this" ClassInstanceCreationExpression = "new" ClassOrInterfaceType "(" ")" | Primary "." "new" Identifier "(" ")" MethodInvocation = Primary "." MethodName "(" ")" | MethodName "(" ")" FieldAccess = Primary "." Identifier | "super" "." Identifier ArrayAccess = Primary "[" Expression "]" | 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