Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Alexandru Dura
SPPF Earley Parser
Commits
073a4a7f
Commit
073a4a7f
authored
Feb 18, 2020
by
Alexandru Dura
Browse files
Decorate each parse tree node with the corresponding rule
parent
0bfa89fe
Changes
10
Hide whitespace changes
Inline
Side-by-side
src/main/java/se/lth/sep/ParseTree.java
View file @
073a4a7f
...
...
@@ -8,13 +8,24 @@ public class ParseTree {
private
int
start
;
private
int
end
;
private
Category
cat
;
private
Rule
rule
;
private
ArrayList
<
ParseTree
>
children
;
p
ublic
ParseTree
(
Category
c
,
int
start
,
int
end
)
{
p
rivate
ParseTree
(
Category
c
,
Rule
rule
,
int
start
,
int
end
)
{
this
.
cat
=
c
;
this
.
children
=
new
ArrayList
<
ParseTree
>();
this
.
start
=
start
;
this
.
end
=
end
;
this
.
rule
=
rule
;
assert
rule
==
null
||
rule
.
getHead
()
==
c
;
}
public
ParseTree
(
Rule
r
,
int
start
,
int
end
)
{
this
(
r
.
getHead
(),
r
,
start
,
end
);
}
public
ParseTree
(
Category
c
,
int
start
,
int
end
)
{
this
(
c
,
null
,
start
,
end
);
}
public
void
addChild
(
ParseTree
t
)
{
...
...
@@ -40,4 +51,8 @@ public class ParseTree {
public
int
getEnd
()
{
return
end
;
}
public
Rule
getRule
()
{
return
rule
;
}
}
src/main/java/se/lth/sep/ParseTreeGenerator.java
View file @
073a4a7f
...
...
@@ -67,7 +67,12 @@ public class ParseTreeGenerator implements SPPFNodeVisitor {
LinkedList
<
LinkedList
<
ParseTree
>>
childAlternatives
=
familyMap
.
get
(
f
);
for
(
LinkedList
<
ParseTree
>
childAlternative
:
childAlternatives
)
{
ParseTree
pt
=
new
ParseTree
(
c
,
start
,
end
);
ParseTree
pt
;
if
(
f
.
getInfo
()
!=
null
)
{
pt
=
new
ParseTree
(
(
Rule
)
f
.
getInfo
(),
start
,
end
);
}
else
{
pt
=
new
ParseTree
(
c
,
start
,
end
);
}
pt
.
addChildren
(
childAlternative
);
result
.
add
(
pt
);
}
...
...
src/main/java/se/lth/sep/Rule.java
View file @
073a4a7f
...
...
@@ -20,6 +20,19 @@ public class Rule {
this
.
action
=
act
;
}
public
String
prettyPrint
()
{
String
s
=
head
.
getName
()
+
" -> "
;
if
(
body
.
length
==
0
)
{
s
+=
"\u03b5"
;
return
s
;
}
for
(
Category
c
:
body
)
{
s
+=
c
.
getName
()
+
" "
;
}
return
s
;
}
public
SemanticAction
getAction
()
{
return
action
;
}
...
...
src/main/java/se/lth/sep/SPPFDebinarizeVisitor.java
View file @
073a4a7f
...
...
@@ -4,11 +4,9 @@ import java.util.HashSet;
import
java.util.Set
;
/**
A visitor that removes the nodes that contain dotte
t
rules.
A visitor that removes the nodes that contain dotte
d
rules.
*/
public
class
SPPFDebinarizeVisitor
implements
SPPFNodeVisitor
{
private
HashSet
<
SPPFNode
>
visitedNodes
=
new
HashSet
<>();
private
HashSet
<
SPPFNode
.
FamilyNode
>
visitedFamNodes
=
new
HashSet
<>();
...
...
src/main/java/se/lth/sep/SPPFNode.java
View file @
073a4a7f
...
...
@@ -7,6 +7,7 @@ import java.util.Set;
public
class
SPPFNode
{
static
public
class
FamilyNode
{
private
SPPFNode
[]
child
;
private
Object
info
=
null
;
FamilyNode
(
SPPFNode
child0
)
{
assert
child0
!=
null
;
...
...
@@ -72,10 +73,19 @@ public class SPPFNode {
public
void
accept
(
SPPFNodeVisitor
visitor
)
{
visitor
.
visit
(
this
);
}
void
setInfo
(
Object
info
)
{
this
.
info
=
info
;
}
Object
getInfo
()
{
return
info
;
}
}
HashSet
<
FamilyNode
>
children
=
new
HashSet
<>();
private
NodeLabel
label
;
private
Object
info
=
null
;
public
SPPFNode
()
{
label
=
null
;
...
...
@@ -112,4 +122,12 @@ public class SPPFNode {
public
NodeLabel
getLabel
()
{
return
label
;
}
void
setInfo
(
Object
info
)
{
this
.
info
=
info
;
}
Object
getInfo
()
{
return
info
;
}
}
src/main/java/se/lth/sep/SPPFNodeDecorator.java
0 → 100644
View file @
073a4a7f
package
se.lth.sep
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
public
class
SPPFNodeDecorator
implements
SPPFNodeVisitor
{
private
HashSet
<
SPPFNode
>
visitedNodes
=
new
HashSet
<>();
private
HashSet
<
SPPFNode
.
FamilyNode
>
visitedFamNodes
=
new
HashSet
<>();
Grammar
grammar
;
public
void
visit
(
SPPFNode
.
FamilyNode
familyNode
)
{
if
(!
visitedFamNodes
.
add
(
familyNode
))
{
// node already visited
return
;
}
for
(
int
i
=
0
;
i
<
familyNode
.
getNumChildren
();
++
i
)
familyNode
.
getChild
(
i
).
accept
(
this
);
}
public
SPPFNodeDecorator
(
Grammar
grammar
)
{
this
.
grammar
=
grammar
;
}
public
void
visit
(
SPPFNode
n
)
{
if
(!
visitedNodes
.
add
(
n
))
{
// node already visited
return
;
}
Category
head
=
((
SymbolLabel
)
n
.
getLabel
()).
getSymbol
(
grammar
);
for
(
SPPFNode
.
FamilyNode
f
:
n
.
getChildren
())
{
f
.
accept
(
this
);
ArrayList
<
Category
>
body
=
new
ArrayList
<>(
f
.
getNumChildren
());
for
(
int
i
=
0
;
i
<
f
.
getNumChildren
();
++
i
)
{
Category
c
=
((
SymbolLabel
)
f
.
getChild
(
i
).
getLabel
()).
getSymbol
(
grammar
);
body
.
add
(
c
);
}
Rule
r
=
grammar
.
getRule
(
head
,
body
);
assert
f
.
getInfo
()
==
null
;
assert
head
.
isTerminal
()
||
r
!=
null
;
f
.
setInfo
(
r
);
}
}
}
src/main/java/se/lth/sep/SPPFTrivialProductionRemover.java
View file @
073a4a7f
...
...
@@ -41,9 +41,6 @@ public class SPPFTrivialProductionRemover implements SPPFNodeVisitor {
HashSet
<
SPPFNode
.
FamilyNode
>
childrenToRemove
=
new
HashSet
<>();
for
(
SPPFNode
.
FamilyNode
f
:
n
.
getChildren
())
{
if
(
f
.
getNumChildren
()
!=
1
)
continue
;
SPPFNode
[]
childArray
=
new
SPPFNode
[
f
.
getNumChildren
()];
boolean
updatedChildren
=
false
;
for
(
int
i
=
0
;
i
<
f
.
getNumChildren
();
++
i
)
{
...
...
@@ -70,9 +67,13 @@ public class SPPFTrivialProductionRemover implements SPPFNodeVisitor {
updatedChildren
=
true
;
}
}
if
(
updatedChildren
)
{
FamilyNode
newf
=
new
FamilyNode
(
childArray
);
// preserve the info
newf
.
setInfo
(
f
.
getInfo
());
childrenToRemove
.
add
(
f
);
newChildren
.
add
(
new
FamilyNode
(
childArray
)
);
newChildren
.
add
(
new
f
);
}
}
...
...
src/main/java/se/lth/sep/Util.java
View file @
073a4a7f
...
...
@@ -25,7 +25,10 @@ public class Util {
private
static
int
dumpParseTree
(
PrintStream
ps
,
ParseTree
pt
,
MutableInt
count
)
{
int
currentID
=
count
.
getAndIncrement
();
ps
.
println
(
currentID
+
" [shape=box,label=\""
+
pt
.
getCategory
().
getName
()
+
"\"];"
);
String
label
=
pt
.
getRule
()
!=
null
?
pt
.
getRule
().
prettyPrint
()
:
pt
.
getCategory
().
getName
();
ps
.
println
(
currentID
+
" [shape=box,label=\""
+
label
+
"\""
+
(
pt
.
getRule
()
==
null
?
",color=red"
:
""
)
+
"];"
);
for
(
ParseTree
c
:
pt
.
getChildren
())
{
int
childID
=
dumpParseTree
(
ps
,
c
,
count
);
ps
.
println
(
currentID
+
" -> "
+
childID
+
";"
);
...
...
src/test/java/EarleyParserTest.java
View file @
073a4a7f
...
...
@@ -186,6 +186,9 @@ public class EarleyParserTest {
SPPFDebinarizeVisitor
dbv
=
new
SPPFDebinarizeVisitor
();
dbv
.
visit
(
root
);
Util
.
dumpParseResult
(
"testJava1.dot"
,
root
,
g
);
// decorate nodes with the grammar rules
SPPFNodeDecorator
dec
=
new
SPPFNodeDecorator
(
g
);
dec
.
visit
(
root
);
// remove trivial productions
SPPFTrivialProductionRemover
tpr
=
new
SPPFTrivialProductionRemover
(
g
)
{
@Override
public
boolean
isBubleUpChild
(
Category
c
)
{
...
...
@@ -230,6 +233,9 @@ public class EarleyParserTest {
SPPFDebinarizeVisitor
dbv
=
new
SPPFDebinarizeVisitor
();
dbv
.
visit
(
root
);
Util
.
dumpParseResult
(
"testJava2.dot"
,
root
,
g
);
// decorate nodes with the grammar rules
SPPFNodeDecorator
dec
=
new
SPPFNodeDecorator
(
g
);
dec
.
visit
(
root
);
// remove trivial productions
SPPFTrivialProductionRemover
tpr
=
new
SPPFTrivialProductionRemover
(
g
)
{
@Override
public
boolean
isBubleUpChild
(
Category
c
)
{
...
...
@@ -337,4 +343,110 @@ public class EarleyParserTest {
Util
.
dumpParseResult
(
"testJava4-notr.dot"
,
root
,
g
);
}
@Test
public
void
testJava5
()
{
// This test is expected should finish in a reasonable ammount of time (~10s).
Grammar
g
=
new
Grammar
();
Java14Grammar
.
addRules
(
g
);
EarleyParser
parser
=
new
EarleyParser
(
g
);
Category
str
[]
=
{
Java14Grammar
.
t_CLASS
,
Java14Grammar
.
t_IDENTIFIER
,
Java14Grammar
.
t_LBRACE
,
// start ambigous constructor/method declaration
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_LPAREN
,
Java14Grammar
.
t_RPAREN
,
Java14Grammar
.
t_LBRACE
,
Java14Grammar
.
t_GAP
,
Java14Grammar
.
t_RBRACE
,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_LPAREN
,
Java14Grammar
.
t_RPAREN
,
Java14Grammar
.
t_LBRACE
,
Java14Grammar
.
t_GAP
,
Java14Grammar
.
t_RBRACE
,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_LPAREN
,
Java14Grammar
.
t_RPAREN
,
Java14Grammar
.
t_LBRACE
,
Java14Grammar
.
t_GAP
,
Java14Grammar
.
t_RBRACE
,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_LPAREN
,
Java14Grammar
.
t_RPAREN
,
Java14Grammar
.
t_LBRACE
,
Java14Grammar
.
t_GAP
,
Java14Grammar
.
t_RBRACE
,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_LPAREN
,
Java14Grammar
.
t_RPAREN
,
Java14Grammar
.
t_LBRACE
,
Java14Grammar
.
t_GAP
,
Java14Grammar
.
t_RBRACE
,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_METAVARID
,
Java14Grammar
.
t_LPAREN
,
Java14Grammar
.
t_RPAREN
,
Java14Grammar
.
t_LBRACE
,
Java14Grammar
.
t_GAP
,
Java14Grammar
.
t_RBRACE
,
// end ambigous constructor/method declaration
Java14Grammar
.
t_RBRACE
};
SPPFNode
root
=
parser
.
parse
(
str
,
Java14Grammar
.
n_class_declaration
);
assertNotNull
(
root
);
Util
.
dumpParseResult
(
"testJava5-bt.dot"
,
root
,
g
);
// debinarize
SPPFDebinarizeVisitor
dbv
=
new
SPPFDebinarizeVisitor
();
dbv
.
visit
(
root
);
Util
.
dumpParseResult
(
"testJava5.dot"
,
root
,
g
);
// decorate nodes with the grammar rules
SPPFNodeDecorator
dec
=
new
SPPFNodeDecorator
(
g
);
dec
.
visit
(
root
);
// remove trivial productions
SPPFTrivialProductionRemover
tpr
=
new
SPPFTrivialProductionRemover
(
g
)
{
@Override
public
boolean
isBubleUpChild
(
Category
c
)
{
if
(
c
.
getName
().
equals
(
"METAVARID"
))
return
true
;
if
(
c
.
getName
().
equals
(
"GAP"
))
return
true
;
return
false
;
}
};
tpr
.
visit
(
root
);
Util
.
dumpParseResult
(
"testJava5-notr.dot"
,
root
,
g
);
// dump the parse trees
ParseTreeGenerator
ptg
=
new
ParseTreeGenerator
(
g
,
root
);
List
<
ParseTree
>
pts
=
ptg
.
getParseTrees
();
// the parsing should produce 3^6 parse trees
assertEquals
(
3
*
3
*
3
*
3
*
3
*
3
,
pts
.
size
());
Util
.
dumpParseTrees
(
"testJava5-parse-tree"
,
pts
);
}
}
src/test/java/UtilTest.java
0 → 100644
View file @
073a4a7f
import
static
org
.
junit
.
Assert
.*;
import
java.util.Arrays
;
import
java.util.LinkedList
;
import
java.util.List
;
import
se.lth.sep.*
;
import
org.junit.Test
;
public
class
UtilTest
{
@Test
public
void
test1
()
{
LinkedList
<
Integer
>
l1
=
new
LinkedList
<>(
Arrays
.
asList
(
1
,
2
,
3
));
LinkedList
<
Integer
>
l2
=
new
LinkedList
<>(
Arrays
.
asList
(
4
,
5
,
6
));
LinkedList
<
Integer
>
l3
=
new
LinkedList
<>(
Arrays
.
asList
(
7
,
8
));
LinkedList
<
LinkedList
<
Integer
>>
ll
=
new
LinkedList
<>(
Arrays
.
asList
(
l1
,
l2
,
l3
));
LinkedList
<
LinkedList
<
Integer
>>
r
=
Util
.<
Integer
>
product
(
ll
.
iterator
());
for
(
LinkedList
<
Integer
>
li
:
r
)
{
for
(
int
i
:
li
)
{
System
.
out
.
print
(
i
+
", "
);
}
System
.
out
.
println
();
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment