From 2447ede937f4b3044db3ddc2d6f36ec5bee1bb45 Mon Sep 17 00:00:00 2001 From: Kia <kia@special-circumstanc.es> Date: Tue, 21 Jul 2020 22:38:44 -0600 Subject: [PATCH] starting implementation of CFG-handling/generation/sampling machinery --- cfg_utils.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++ gearbox.py | 37 ----------------------------- python_arborist.py | 5 ++++ 3 files changed, 64 insertions(+), 37 deletions(-) create mode 100644 cfg_utils.py diff --git a/cfg_utils.py b/cfg_utils.py new file mode 100644 index 0000000..2a8becb --- /dev/null +++ b/cfg_utils.py @@ -0,0 +1,59 @@ + + +class TreeNode: + def __init__(self, language_element, subnodes): + self.language_element = language_element + self.subnodes = subnodes + + def __str__(self): + return str(self.language_element) + str(self.subnodes) + + + + +# We define a context-free grammar as: +# 1. A list of nonterminal symbols +# 2. A list of terminal symbols +# 3. A list of production rules +# 4. A start symbol. + + + + + + +# Once we have a CFG's definition, we can use Boltzmann sampling in order to generate random strings +# from that CFG. + + + +# Furthermore, we also note that the description of a context-free grammar is *itself* context-free +# so if we take the CFG-description grammar (BNF or something isomorphic to it), and use Boltzmann +# sampling on *it*, we will generate candidate grammars; which will be used to test the FPGA-based +# parser generator against a reference LR parser generator implementation. Naturally, this procedure +# may not produce LR-parseable grammars or even deterministic context-free grammars; but if the grammar +# is rejected by both the FPGA parser generator and reference parser generator; this is fine, we just +# move on to the next one. + + +# Once we randomly generate a CFG, we randomly generate strings that are valid strings, but also +# generate exemplars that are potentially *invalid* strings (both by mutating valid strings but +# also by generating random sequences ab initio from the terminal symbols). The potentially invalid +# strings are tested against the reference parser, those that are accidentally valid are discarded, +# and those that are invalid are used in the automatic equivalence testing. + + +# We fail our candidate parser generator if: +# +# 1. During the generation phase, it rejects a grammar the reference generator doesn't reject, or +# accepts a grammar the reference generator rejects. + +# 2. During the execution phase, it rejects a string the reference generated parser doesn't reject, +# or accepts a string the reference generated parser rejects. + +# 3. During the execution phase, it accepts a string that the reference generated parser accepts; but +# the parse tree it generates is not identical to the parse tree that the reference generated parser +# produced. + + + diff --git a/gearbox.py b/gearbox.py index b809678..8f03f8a 100644 --- a/gearbox.py +++ b/gearbox.py @@ -19,43 +19,6 @@ class ArbitraryGearbox(Elaboratable): # non-registered write_ptr = Signal(range(len_storage)) read_ptr = Signal(range(len_storage)) - # we signal ready to upstream if and only if the skid buffer is empty - m.d.comb += self.upstream_ready_out.eq(~skid_buffer_frozen) - - - # should we capture a value in the skid buffer? - # we should if upstream has data for us *and* downstream cannot accept - - # If we want to fill our skid buffer, we need: - # 1. valid input data (upstream_valid_in == 1) - # 2. a buffer that is empty (skid_buffer_frozen == 0) - # 3. stalled downstream (downstream_ready_in == 0) - - with m.If(self.upstream_valid_in & (~skid_buffer_frozen) & (~self.downstream_ready_in)): - m.d.sync += skid_buffer_frozen.eq(1) - - # if downstream is accepting data again, we will flush our skid buffer - with m.If(self.downstream_ready_in == 1): - m.d.sync += skid_buffer_frozen.eq(0) - - - m.d.comb += self.downstream_valid_out.eq(self.upstream_valid_in | skid_buffer_frozen) - - - # data path - - # always clock data into the skid buffer as long as the buffer isn't frozen - - with m.If(skid_buffer_frozen == 0): - m.d.sync += skid_buffer.eq(self.upstream_data_in) - - with m.If(skid_buffer_frozen == 1): - m.d.comb += self.downstream_data_out.eq(skid_buffer) - - # NON registered - with m.Elif(self.upstream_valid_in == 1): - m.d.comb += self.downstream_data_out.eq(self.upstream_data_in) - return m diff --git a/python_arborist.py b/python_arborist.py index 937c616..1a540a2 100644 --- a/python_arborist.py +++ b/python_arborist.py @@ -379,6 +379,11 @@ def deserializer(serialized_array): +def string_generator(grammar): + + + +def treechecker(derivation, parse_tree): -- GitLab