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
0bfa89fe
Commit
0bfa89fe
authored
Feb 17, 2020
by
Alexandru Dura
Browse files
Enumerate parse trees from the SPPF
parent
9d220f4a
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/main/java/se/lth/sep/Grammar.java
View file @
0bfa89fe
...
...
@@ -2,6 +2,7 @@ package se.lth.sep;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.TreeSet
;
public
class
Grammar
{
...
...
@@ -122,4 +123,15 @@ public class Grammar {
throw
new
EarleyException
(
"Rule not preset in the grammar"
);
return
r
;
}
public
Rule
getRule
(
Category
head
,
List
<
Category
>
body
)
{
List
<
Rule
>
ruleList
=
grammarRules
.
get
(
head
);
if
(
ruleList
==
null
)
return
null
;
for
(
Rule
r
:
ruleList
)
{
if
(
r
.
getBody
().
equals
(
body
))
return
r
;
}
return
null
;
}
}
src/main/java/se/lth/sep/ParseTree.java
0 → 100644
View file @
0bfa89fe
package
se.lth.sep
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
public
class
ParseTree
{
private
int
start
;
private
int
end
;
private
Category
cat
;
private
ArrayList
<
ParseTree
>
children
;
public
ParseTree
(
Category
c
,
int
start
,
int
end
)
{
this
.
cat
=
c
;
this
.
children
=
new
ArrayList
<
ParseTree
>();
this
.
start
=
start
;
this
.
end
=
end
;
}
public
void
addChild
(
ParseTree
t
)
{
children
.
add
(
t
);
}
public
void
addChildren
(
Collection
<
ParseTree
>
ts
)
{
children
.
addAll
(
ts
);
}
public
List
<
ParseTree
>
getChildren
()
{
return
children
;
}
public
Category
getCategory
()
{
return
cat
;
}
public
int
getStart
()
{
return
start
;
}
public
int
getEnd
()
{
return
end
;
}
}
src/main/java/se/lth/sep/ParseTreeGenerator.java
0 → 100644
View file @
0bfa89fe
package
se.lth.sep
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.List
;
import
se.lth.sep.SPPFNode.FamilyNode
;
public
class
ParseTreeGenerator
implements
SPPFNodeVisitor
{
private
HashMap
<
SPPFNode
,
LinkedList
<
ParseTree
>>
nodeMap
=
new
HashMap
<>();
private
HashMap
<
SPPFNode
.
FamilyNode
,
LinkedList
<
LinkedList
<
ParseTree
>>>
familyMap
=
new
HashMap
<>();
private
Grammar
grammar
;
private
SPPFNode
root
;
public
ParseTreeGenerator
(
Grammar
grammar
,
SPPFNode
root
)
{
this
.
grammar
=
grammar
;
this
.
root
=
root
;
}
public
List
<
ParseTree
>
getParseTrees
()
{
root
.
accept
(
this
);
return
nodeMap
.
get
(
root
);
}
@Override
public
void
visit
(
FamilyNode
f
)
{
if
(
familyMap
.
containsKey
(
f
))
return
;
for
(
int
i
=
0
;
i
<
f
.
getNumChildren
();
++
i
)
{
f
.
getChild
(
i
).
accept
(
this
);
}
LinkedList
<
LinkedList
<
ParseTree
>>
childrenTrees
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
f
.
getNumChildren
();
++
i
)
{
childrenTrees
.
add
(
nodeMap
.
get
(
f
.
getChild
(
i
)));
}
LinkedList
<
LinkedList
<
ParseTree
>>
childrenCombinations
=
Util
.<
ParseTree
>
product
(
childrenTrees
.
iterator
());
familyMap
.
put
(
f
,
childrenCombinations
);
}
@Override
public
void
visit
(
SPPFNode
n
)
{
if
(
nodeMap
.
containsKey
(
n
))
{
return
;
}
int
start
=
n
.
getLabel
().
getStart
();
int
end
=
n
.
getLabel
().
getEnd
();
Category
c
=
((
SymbolLabel
)
n
.
getLabel
()).
getSymbol
(
grammar
);
LinkedList
<
ParseTree
>
result
=
new
LinkedList
<>();
if
(
n
.
getChildren
().
isEmpty
())
{
// handle the empty case
result
.
add
(
new
ParseTree
(
c
,
start
,
end
));
}
for
(
FamilyNode
f
:
n
.
getChildren
())
{
f
.
accept
(
this
);
LinkedList
<
LinkedList
<
ParseTree
>>
childAlternatives
=
familyMap
.
get
(
f
);
for
(
LinkedList
<
ParseTree
>
childAlternative
:
childAlternatives
)
{
ParseTree
pt
=
new
ParseTree
(
c
,
start
,
end
);
pt
.
addChildren
(
childAlternative
);
result
.
add
(
pt
);
}
}
nodeMap
.
put
(
n
,
result
);
}
}
src/main/java/se/lth/sep/Rule.java
View file @
0bfa89fe
...
...
@@ -4,13 +4,24 @@ import java.util.Arrays;
import
java.util.List
;
public
class
Rule
{
private
Category
head
;
private
Category
[]
body
;
private
final
Category
head
;
private
final
Category
[]
body
;
private
final
SemanticAction
action
;
public
Rule
(
Category
head
,
Category
...
body
)
{
this
.
head
=
head
;
// assert body.length > 0;
this
.
body
=
body
;
this
.
action
=
SemanticAction
.
NULL
;
}
public
Rule
(
SemanticAction
act
,
Category
head
,
Category
...
body
)
{
this
.
head
=
head
;
this
.
body
=
body
;
this
.
action
=
act
;
}
public
SemanticAction
getAction
()
{
return
action
;
}
public
Category
getHead
()
{
...
...
@@ -20,4 +31,33 @@ public class Rule {
public
List
<
Category
>
getBody
()
{
return
Arrays
.
asList
(
body
);
}
@Override
public
int
hashCode
()
{
final
int
prime
=
47
;
int
result
=
1
;
result
=
prime
*
result
+
Arrays
.
hashCode
(
body
);
result
=
prime
*
result
+
((
head
==
null
)
?
0
:
head
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
Rule
other
=
(
Rule
)
obj
;
if
(!
Arrays
.
equals
(
body
,
other
.
body
))
return
false
;
if
(
head
==
null
)
{
if
(
other
.
head
!=
null
)
return
false
;
}
else
if
(!
head
.
equals
(
other
.
head
))
return
false
;
return
true
;
}
}
src/main/java/se/lth/sep/SemanticAction.java
0 → 100644
View file @
0bfa89fe
package
se.lth.sep
;
import
java.util.List
;
public
abstract
class
SemanticAction
{
public
abstract
Object
act
(
List
<
Object
>
children
);
public
static
SemanticAction
NULL
=
new
SemanticAction
()
{
@Override
public
Object
act
(
List
<
Object
>
children
)
{
return
null
;
}
};
public
static
SemanticAction
PASSTROUGH
=
new
SemanticAction
()
{
@Override
public
Object
act
(
List
<
Object
>
children
)
{
return
children
.
get
(
0
);
}
};
}
src/main/java/se/lth/sep/Util.java
View file @
0bfa89fe
...
...
@@ -3,7 +3,12 @@ package se.lth.sep;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.PrintStream
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
org.apache.commons.lang3.mutable.MutableInt
;
public
class
Util
{
public
static
void
dumpParseResult
(
String
dotFileName
,
SPPFNode
node
,
Grammar
grammar
)
{
...
...
@@ -17,6 +22,65 @@ public class Util {
e
.
printStackTrace
();
}
}
private
static
int
dumpParseTree
(
PrintStream
ps
,
ParseTree
pt
,
MutableInt
count
)
{
int
currentID
=
count
.
getAndIncrement
();
ps
.
println
(
currentID
+
" [shape=box,label=\""
+
pt
.
getCategory
().
getName
()
+
"\"];"
);
for
(
ParseTree
c
:
pt
.
getChildren
())
{
int
childID
=
dumpParseTree
(
ps
,
c
,
count
);
ps
.
println
(
currentID
+
" -> "
+
childID
+
";"
);
}
return
currentID
;
}
public
static
void
dumpParseTree
(
String
dotFileName
,
ParseTree
pt
)
{
try
{
PrintStream
out
=
new
PrintStream
(
new
File
(
dotFileName
));
out
.
println
(
"digraph G {"
);
dumpParseTree
(
out
,
pt
,
new
MutableInt
(
0
));
out
.
println
(
"}"
);
}
catch
(
FileNotFoundException
e
)
{
e
.
printStackTrace
();
}
}
public
static
void
dumpParseTrees
(
String
dotFilePrefix
,
Collection
<
ParseTree
>
pts
)
{
int
index
=
0
;
for
(
ParseTree
pt
:
pts
)
{
index
++;
dumpParseTree
(
dotFilePrefix
+
"_"
+
index
+
".dot"
,
pt
);
}
}
public
static
<
T
>
LinkedList
<
LinkedList
<
T
>>
product
(
Iterator
<
LinkedList
<
T
>>
children
)
{
if
(!
children
.
hasNext
())
{
return
new
LinkedList
<>();
}
LinkedList
<
T
>
head
=
children
.
next
();
LinkedList
<
LinkedList
<
T
>>
tail
=
product
(
children
);
LinkedList
<
LinkedList
<
T
>>
result
=
new
LinkedList
<>();
if
(
tail
.
isEmpty
())
{
for
(
T
t
:
head
)
{
LinkedList
<
T
>
singleton
=
new
LinkedList
<
T
>();
singleton
.
add
(
t
);
result
.
add
(
singleton
);
}
return
result
;
}
for
(
T
t
:
head
)
{
for
(
LinkedList
<
T
>
tt
:
tail
)
{
LinkedList
<
T
>
childList
=
new
LinkedList
<>();
childList
.
add
(
t
);
childList
.
addAll
(
tt
);
result
.
add
(
childList
);
}
}
return
result
;
}
}
class
DotVisitor
implements
SPPFNodeVisitor
{
...
...
src/test/java/EarleyParserTest.java
View file @
0bfa89fe
import
static
org
.
junit
.
Assert
.*;
import
java.util.List
;
import
se.lth.sep.*
;
import
org.junit.Test
;
...
...
@@ -195,7 +198,10 @@ public class EarleyParserTest {
};
tpr
.
visit
(
root
);
Util
.
dumpParseResult
(
"testJava1-notr.dot"
,
root
,
g
);
// dump the parse trees
ParseTreeGenerator
ptg
=
new
ParseTreeGenerator
(
g
,
root
);
List
<
ParseTree
>
pts
=
ptg
.
getParseTrees
();
Util
.
dumpParseTrees
(
"testJava1-parse-tree"
,
pts
);
}
@Test
public
void
testJava2
()
{
...
...
@@ -236,6 +242,11 @@ public class EarleyParserTest {
};
tpr
.
visit
(
root
);
Util
.
dumpParseResult
(
"testJava2-notr.dot"
,
root
,
g
);
// dump the parse trees
ParseTreeGenerator
ptg
=
new
ParseTreeGenerator
(
g
,
root
);
List
<
ParseTree
>
pts
=
ptg
.
getParseTrees
();
Util
.
dumpParseTrees
(
"testJava2-parse-tree"
,
pts
);
}
@Test
public
void
testJava3
()
{
...
...
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