;;; Hey, emacs(1), this is -*- Mode: Common-Lisp; -*-, got it?

;;;
;;; PAL --- PCFG Approximation and Parsing Library for DELPH-IN
;;;
;;; Copyright (c) 2009 -- 2012 Johan Benum Evensberget (johan.benum@gmail.com)
;;;
;;; This program is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU Lesser General Public License as published by
;;; the Free Software Foundation; either version 2.1 of the License, or (at
;;; your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful, but WITHOUT
;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
;;; License for more details.
;;; 

(in-package :pcfg)

(defun write-hash-table (hash-table path)
  (with-open-file (stream path :direction :output :if-exists :supersede)
    (maphash (lambda (k v)
	       (format stream "(~s ~s)~%" k v))
	     hash-table)))

(defun read-hash-table (path)
  (with-open-file (stream path :direction :input)
    (let (res)
      (loop
	  for pair = (read stream nil :eof)
	  until (eq pair :eof)
	  do (push pair res))
      (loop
	  with hash-table = (make-hash-table :test #'equal)
	  for (key value) in res
	  do (setf (gethash key hash-table) value)
	  finally (return hash-table)))))
 
(defun write-symbol-table (symbol-table path)
  (with-slots (forward) symbol-table
    (write-hash-table forward path)))

(defun read-symbol-table (path)
  (let ((mappings (read-hash-table path))
	(symbol-table (make-symbol-table)))
    (maphash (lambda (k v)
	       (set-symbol-and-code k v symbol-table))
	     mappings)
    symbol-table))

(defun write-grammar (grammar path)
  (with-open-file (stream path :direction :output :if-exists :supersede)
    (loop
	initially (format stream "~s~%" (cfg-samples grammar))
	for rule in (collect-rules grammar)
	for hash = (cfr-hash rule)
	do (format
            stream "(~s ~s ~s)~%"
            hash (cfr-type rule) (cfr-count rule)))))

(defun read-grammar (path symbol-table)
  (with-open-file (stream path :direction :input)
    (loop
	with samples = (read stream nil :eof)
	for rule = (read stream nil :eof)
	with cfg = (make-cfg :table symbol-table :samples samples)
	until (eq rule :eof)
	do (destructuring-bind ((lhs rhs) type count) rule
	     (record-cfr (make-cfr :type type
				   :lhs lhs
				   :rhs rhs
				   :count count)
			 cfg))
	finally (return cfg))))