Change ebnf-action to properly nest with attached parser

This allows removal of last-parser hack. Syntax of EBNF changes though.
Now an action must attach to a group:

  <EBNF foo = (a b c) [[ ...act on group... ]] EBNF>
db4
Chris Double 2008-03-20 03:05:40 +13:00
parent 65fabeec11
commit 92d8140d87
2 changed files with 27 additions and 40 deletions

View File

@ -15,11 +15,8 @@ IN: peg.ebnf.tests
{ {
T{ ebnf-rule f T{ ebnf-rule f
"digit" "digit"
V{ T{ ebnf-choice f
T{ ebnf-choice f V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } }
V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } }
}
f
} }
} }
} [ } [
@ -29,11 +26,8 @@ IN: peg.ebnf.tests
{ {
T{ ebnf-rule f T{ ebnf-rule f
"digit" "digit"
V{ T{ ebnf-sequence f
T{ ebnf-sequence f V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } }
V{ T{ ebnf-terminal f "1" } T{ ebnf-terminal f "2" } }
}
f
} }
} }
} [ } [
@ -119,9 +113,9 @@ IN: peg.ebnf.tests
] unit-test ] unit-test
{ V{ 1 "b" } } [ { V{ 1 "b" } } [
"foo='a' [[ drop 1 ]] 'b'" ebnf>quot with-compilation-unit "ab" foo parse parse-result-ast "foo=('a')[[ drop 1 ]] 'b'" ebnf>quot with-compilation-unit "ab" foo parse parse-result-ast
] unit-test ] unit-test
{ V{ 1 2 } } [ { V{ 1 2 } } [
"foo='a' [[ drop 1 ]] 'b' [[ drop 2 ]]" ebnf>quot with-compilation-unit "ab" foo parse parse-result-ast "foo=('a') [[ drop 1 ]] ('b') [[ drop 2 ]]" ebnf>quot with-compilation-unit "ab" foo parse parse-result-ast
] unit-test ] unit-test

View File

@ -16,7 +16,7 @@ TUPLE: ebnf-repeat0 group ;
TUPLE: ebnf-repeat1 group ; TUPLE: ebnf-repeat1 group ;
TUPLE: ebnf-optional elements ; TUPLE: ebnf-optional elements ;
TUPLE: ebnf-rule symbol elements ; TUPLE: ebnf-rule symbol elements ;
TUPLE: ebnf-action code ; TUPLE: ebnf-action parser code ;
TUPLE: ebnf rules ; TUPLE: ebnf rules ;
C: <ebnf-non-terminal> ebnf-non-terminal C: <ebnf-non-terminal> ebnf-non-terminal
@ -34,12 +34,10 @@ C: <ebnf> ebnf
SYMBOL: parsers SYMBOL: parsers
SYMBOL: non-terminals SYMBOL: non-terminals
SYMBOL: last-parser
: reset-parser-generation ( -- ) : reset-parser-generation ( -- )
V{ } clone parsers set V{ } clone parsers set
H{ } clone non-terminals set H{ } clone non-terminals set ;
f last-parser set ;
: store-parser ( parser -- number ) : store-parser ( parser -- number )
parsers get [ push ] keep length 1- ; parsers get [ push ] keep length 1- ;
@ -57,7 +55,7 @@ SYMBOL: last-parser
GENERIC: (generate-parser) ( ast -- id ) GENERIC: (generate-parser) ( ast -- id )
: generate-parser ( ast -- id ) : generate-parser ( ast -- id )
(generate-parser) dup last-parser set ; (generate-parser) ;
M: ebnf-terminal (generate-parser) ( ast -- id ) M: ebnf-terminal (generate-parser) ( ast -- id )
ebnf-terminal-symbol token sp store-parser ; ebnf-terminal-symbol token sp store-parser ;
@ -99,15 +97,12 @@ M: ebnf-rule (generate-parser) ( ast -- id )
swap [ parsers get set-nth ] keep ; swap [ parsers get set-nth ] keep ;
M: ebnf-action (generate-parser) ( ast -- id ) M: ebnf-action (generate-parser) ( ast -- id )
ebnf-action-code string-lines parse-lines [ ebnf-action-parser generate-parser get-parser ] keep
last-parser get get-parser swap action store-parser ; ebnf-action-code string-lines parse-lines action store-parser ;
M: vector (generate-parser) ( ast -- id ) M: vector (generate-parser) ( ast -- id )
[ generate-parser ] map peek ; [ generate-parser ] map peek ;
M: f (generate-parser) ( ast -- id )
drop last-parser get ;
M: ebnf (generate-parser) ( ast -- id ) M: ebnf (generate-parser) ( ast -- id )
ebnf-rules [ ebnf-rules [
generate-parser generate-parser
@ -199,6 +194,7 @@ DEFER: 'choice'
"*" token sp ensure-not , "*" token sp ensure-not ,
"+" token sp ensure-not , "+" token sp ensure-not ,
"?" token sp ensure-not , "?" token sp ensure-not ,
"[[" token sp ensure-not ,
] seq* hide grouped ; ] seq* hide grouped ;
: 'repeat0' ( -- parser ) : 'repeat0' ( -- parser )
@ -210,6 +206,19 @@ DEFER: 'choice'
: 'optional' ( -- parser ) : 'optional' ( -- parser )
[ <ebnf-optional> ] "?" syntax grouped ; [ <ebnf-optional> ] "?" syntax grouped ;
: 'factor-code' ( -- parser )
[
"]]" token ensure-not ,
[ drop t ] satisfy ,
] seq* [ first ] action repeat0 [ >string ] action ;
: 'action' ( -- parser )
[
"(" [ 'choice' sp ] delay ")" syntax-pack ,
"[[" 'factor-code' "]]" syntax-pack ,
] seq* [ first2 <ebnf-action> ] action ;
: 'ensure-not' ( -- parser ) : 'ensure-not' ( -- 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
@ -229,6 +238,7 @@ DEFER: 'choice'
'repeat0' sp , 'repeat0' sp ,
'repeat1' sp , 'repeat1' sp ,
'optional' sp , 'optional' sp ,
'action' sp ,
] choice* repeat1 [ ] choice* repeat1 [
dup length 1 = [ first ] [ <ebnf-sequence> ] if dup length 1 = [ first ] [ <ebnf-sequence> ] if
] action ; ] action ;
@ -237,29 +247,12 @@ DEFER: 'choice'
'sequence' sp "|" token sp list-of [ 'sequence' sp "|" token sp list-of [
dup length 1 = [ first ] [ <ebnf-choice> ] if dup length 1 = [ first ] [ <ebnf-choice> ] if
] action ; ] action ;
: 'factor-code' ( -- parser )
[
"]]" token ensure-not ,
[ drop t ] satisfy ,
] seq* [ first ] action repeat0 [ >string ] action ;
: 'action' ( -- parser )
"[[" 'factor-code' "]]" syntax-pack [ <ebnf-action> ] action ;
: 'rhs' ( -- parser )
[
'choice' ,
'action' sp optional ,
] seq* repeat1 [
dup length 1 = [ first ] [ <ebnf-sequence> ] if
] action ;
: 'rule' ( -- parser ) : 'rule' ( -- parser )
[ [
'non-terminal' [ ebnf-non-terminal-symbol ] action , 'non-terminal' [ ebnf-non-terminal-symbol ] action ,
"=" syntax , "=" syntax ,
'rhs' , 'choice' ,
] seq* [ first2 <ebnf-rule> ] action ; ] seq* [ first2 <ebnf-rule> ] action ;
: 'ebnf' ( -- parser ) : 'ebnf' ( -- parser )