1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
#----------------------------------------------------------------------
#
# aycock-debug.tcl --
#
# Procedures needed to debug an Aycock-Horspool-Earley parser.
#
# Copyright (c) 2006 by Kevin B. Kenny. All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: aycock-debug.tcl,v 1.2 2011/01/13 02:47:47 andreas_kupries Exp $
#
#----------------------------------------------------------------------
package provide grammar::aycock::debug 1.0
package require Tcl 8.4
# Bring in the runtime library
package require grammar::aycock::runtime 1.0
# grammar::aycock::Terminals --
#
# List the terminal symbols used in a parser's grammar
#
# Usage:
# $parser terminals
#
# Results:
# Returns a list of the terminal symbols
proc ::grammar::aycock::Terminals {parser} {
namespace upvar $parser RuleSet RuleSet
set t [dict create]
dict for {lhs rules} $RuleSet {
dict for {rhs action} $rules {
foreach sym $rhs {
if {$sym ne "\u22a2"} {
if {![dict exists $RuleSet $sym]} {
dict set t $sym {}
}
}
}
}
}
return [lsort -dictionary [dict keys $t]]
}
# grammar::aycock::Nonterminals --
#
# List the nonterminal symbols used in a parser's grammar
#
# Usage:
# $parser nonterminals
#
# Results:
# Returns a list of the nonterminal symbols
proc ::grammar::aycock::Nonterminals {parser} {
namespace upvar $parser RuleSet RuleSet
set t [dict create]
dict for {lhs rules} $RuleSet {
dict for {rhs action} $rules {
foreach sym $rhs {
if {$sym ne "\u22a2"} {
if {[dict exists $RuleSet $sym]} {
dict set t $sym {}
}
}
}
}
}
return [lsort -dictionary [dict keys $t]]
}
# grammar::aycock::NeverReduced --
#
# Checks a parser's grammar for rules that cannot be reduced.
#
# Parameters:
# parser -- Name of the parser
#
# Results:
# Return a list of the left-hand sides of rules never reduced.
proc ::grammar::aycock::NeverReduced {parser} {
namespace upvar $parser RuleSet RuleSet
set t [dict create]
foreach {lhs rules} $RuleSet {
dict set t $lhs {}
}
foreach s [Nonterminals $parser] {
dict unset t $s
}
dict unset t {}
return [lsort [dict keys $t]]
}
# grammar::aycock::Save --
#
# Produces a script that will load an Aycock-Earley parser without
# needing to do all the state analysis.
#
# Usage:
# $parser save
#
# Results:
# Returns a script that when evaluated will reload the parser.
proc ::grammar::aycock::Save {parser} {
namespace upvar $parser \
RuleSet RuleSet \
Completions Completions \
Edges Edges
set actions [dict create]
set rex1 {}
dict for {lhs rules} $RuleSet {
set rex2 {}
foreach {rhs action} $rules {
dict set actions $action {}
append rex2 \n \t [list $rhs $action]
}
append rex2 \n " "
append rex1 \n " " [list $lhs $rex2]
}
append rex1 \n
set i 0
set sex1 {}
foreach {completions} $Completions {
set nc 0
append sex1 \n " " [list $completions [dict get $Edges $i]]
incr i
}
append sex1 \n
set retval [list [namespace current]::Restore $rex1 $sex1]
foreach action [lsort -dictionary [dict keys $actions]] {
lappend retval $action \
[string trimright [info body ${parser}::$action]]\n
}
return $retval
}
# grammar::aycock::DumpItemSet --
#
# Displays a representation of an LRE(0) item set on a channel
#
# Parameters:
# parser - Name of the parser
# s - Item set to display
# chan - Channel to use
#
# Results:
# None
#
# Side effects:
# Writes the LRE(0) item set on the given channel
proc ::grammar::aycock::DumpItemSet {parser s {chan stdout}} {
foreach {lhs prodIndex pos} $s {
DumpItem $parser $lhs $prodIndex $pos $chan
}
return
}
# grammar::aycock::DumpItem --
#
# Displays a representation of an LRE(0) item on a channel
#
# Parameters:
# parser - Name of the parser
# lhs - Left-hand side of the reduction
# prodIndex - Ordinal position of the right-hand side among
# all right-hand sides for that LHS
# pos - Position of the dot on the right-hand side
# chan - Channel to use
#
# Results:
# None
#
# Side effects:
# Writes the LRE(0) item on the given channel
proc ::grammar::aycock::DumpItem {parser lhs prodIndex pos {chan stdout}} {
namespace upvar $parser RuleSet RuleSet
set rhs [lindex [dict get $RuleSet $lhs] $prodIndex]
puts $chan " $lhs ::= [linsert $rhs $pos \u00b7]"
return
}
|