Last active
August 29, 2015 14:13
-
-
Save lnznt/004a9c7844d55b9993b4 to your computer and use it in GitHub Desktop.
Ruby: ミニ Prolog パーサ (改) ref: http://qiita.com/lnznt/items/016210e1121cc9219190
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ make | |
racc -g -o prolog_parser.rb prolog_parser.ry |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
: | |
: 実行例 (コマンドライン引数に渡す文字列には最後の「.」は含めません) | |
: | |
$ ruby prolog_parser.rb "abc" | |
:abc | |
$ ruby prolog_parser.rb "a(abc)" | |
{:a=>[:abc]} | |
$ ruby prolog_parser.rb "[1,2,3]" | |
[1, 2, 3] | |
$ ruby prolog_parser.rb "a(X) :- b(X),!" | |
{:":-"=>[{:a=>[{nil=>:X}]}, {:","=>[{:b=>[{nil=>:X}]}, :!]}]} | |
$ ruby prolog_parser.rb ",(,,,),,(,,,,,)" | |
{:","=>[{:","=>[:",", :","]}, {:","=>[:",", :",", :","]}]} | |
$ ruby prolog_parser.rb -v "a(abc)" | |
[:FUNCTOR, "a"] | |
[:ATOM, "abc"] | |
[")", ")"] | |
[".", "."] | |
nil | |
{:a=>[:abc]} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# $ ruby prolog_parser.rb [options] | |
# | |
# options are: | |
# -v トークンキューをダンプ出力する | |
# -d パーサデバッグコードを出力する | |
# |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# パーサへのソースの指定の仕方 (同時に指定した場合、下の方が優先) | |
# | |
# parse メソッドに指定する方法 | |
# | |
# parser.parse(term: str) .... 項(文字列、最後のピリオド(.)不要) | |
# parser.parse(line: str) .... 行(文字列、最後のピリオド(.)必要) | |
# parser.parse(file: path) ... ファイル名(文字列) | |
# parser.parse(io: io) ....... read により入力文字列を読み出せる IO | |
# parser.parse(enum: enum) ... next により入力文字列を読み出せる Enumerator | |
# parser.parse(reader: pr) ... call により入力文字列を取得できる Proc | |
# parser.parse(&pr) .......... (上と同じ) | |
# | |
# アクセサで指定する方法 | |
# | |
# parser.term = str | |
# parser.line = str | |
# parser.file = path | |
# parser.io = io | |
# parser.enum = enum | |
# parser.reader = reader | |
# | |
# parser.parse | |
# | |
# ---- | |
# | |
# parse の戻り値は、解析結果を出力する Enumerator である | |
# | |
# (I) ワンショット(解析結果を1回のみ取り出す) | |
# | |
# (例) | |
# pp result = parser.parse(line: str).first | |
# | |
# (II) イテレート(解析結果を繰り返し取り出す) | |
# | |
# (例) | |
# parser.parse(io: f).each {|result| pp result } | |
# | |
# pp results = parser.parse(io: f).entries | |
# | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ swipl -l server.pro -g 'create_server(3333).' | |
# サーバは起動したままになる... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ruby ../prolog_proxy.rb | |
"[assert(person(socrates))]" | |
"[assert(:-(mortal(_G61),person(_G61)))]" | |
"[mortal(socrates)]" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'socket' | |
module Prolog | |
class Proxy | |
attr_accessor :host, :port | |
def initialize(port:, host:'localhost', &block) | |
tap {|my| my.host, my.port = host, port } | |
instance_eval(&block) if block | |
end | |
# Prolog サーバのデータベースに節を問い合わせをする | |
def inquire(query, &conv) | |
conv ||= -> q { q } | |
TCPSocket.open(host, port) do |s| | |
###s.puts "#{conv.(query)}." | |
###s.gets | |
# SWI-Prolog 決め打ちでサーバが EUC-JP として処理する | |
s.puts "#{conv.(query.encode('EUC-JP'))}." | |
s.gets.encode('UTF-8', 'EUC-JP') | |
end | |
end | |
# Prolog サーバのデータベースに節を追加する | |
def insert(clause) | |
query = | |
clause =~ /-->/ ? "dcg_translate_rule((#{clause}),X),assert(X)" : | |
"assert((#{clause}))" | |
inquire(query) | |
end | |
end | |
end | |
if __FILE__ == $0 | |
require 'pp' | |
require 'prolog_parser' | |
prolog = Prolog::Proxy.new port:3333 | |
pp Prolog.to_prolog Prolog.to_ruby term:prolog.insert("person(socrates)") | |
pp Prolog.to_prolog Prolog.to_ruby term:prolog.insert("mortal(X) :- person(X)") | |
pp Prolog.to_prolog Prolog.to_ruby term:prolog.inquire("mortal(Who)") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment