Skip to content

Instantly share code, notes, and snippets.

@tomoemon
Created March 4, 2016 13:52
Show Gist options
  • Save tomoemon/b0f6e44c7cb73f3904ba to your computer and use it in GitHub Desktop.
Save tomoemon/b0f6e44c7cb73f3904ba to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
import sys
import re
from pypeg2 import *
"""
漢直 Win テーブル定義ファイルパーサ (要 python3)
Option: #define で定義される値
Block: {...} で囲まれている中身
NormalWord: " " で囲まれている文字列
SpecialWord: @ から始まる文字列
"""
Keyword.regex = re.compile(r"[\w-]+")
class OptionType(Keyword):
grammar = Enum(K("prefix"), K("table-name"), K("defguide"), K("key-layout"))
class OptionValue(str):
grammar = [contiguous('"', re.compile(r".+"), '"'), re.compile(r".+")]
class Option(List):
grammar = "#define", OptionType, OptionValue
class NormalWord(str):
# " " に含まれる空白文字も取得できるようにする
# デフォルトだと " " に囲まれた文字列に含まれる空白文字もスキップしてしまう
# see: https://fdik.org/pyPEG/grammar_elements.html#contiguous
grammar = contiguous('"', re.compile(r'(\\.|[^"])+'), '"')
class SpecialWord(str):
grammar = re.compile(r"@[1-9ZKspgwbm!qBDPhHv^]")
class Word(str):
grammar = [NormalWord, SpecialWord]
class Blank(str):
# 空文字も1要素として取得可能にする
# "" 指定だけだと ,,,, がすべて無視される
grammar = re.compile(r"[ \t\n\r]*")
# python の仕様上、再帰的な定義をする場合は、先に class 定義だけを作る必要がある
class Allow(List): pass
Allow.grammar = maybe_some("-", re.compile(r"S?[0-9]+"), ">"), Word
class ShiftableWord(str):
# シフト打鍵時の文字列を取得する際は e.shift
grammar = Word, optional(ignore("/"), attr("_shift", Word))
def __repr__(self):
return str(self) + ('/{}'.format(self._shift) if hasattr(self, '_shift') else "")
@property
def shift(self):
return self._shift if hasattr(self, '_shift') else ""
class Block(List): pass
BlockElement = [Block, ShiftableWord, Allow, Blank]
Block.grammar = "{", BlockElement, 48, (",", BlockElement), "}"
class ModeBlock(List):
# ModeBlock は Block: { ... } か Allow: - .. > .. -> ...
grammar = [Block, Allow]
class KanchokuTable(List):
# テーブル全体は Option または ModeBlock が繰り返し出現するもの
grammar = maybe_some([Option, ModeBlock])
class Comment(str):
# ; から行末までコメント
# # から行末までコメント(ただし、#define のみ意味を持つため消さない)
grammar = [re.compile(r";.*"), re.compile(r"#(?!define).*")]
def main():
import fileinput
data = fileinput.FileInput(openhook=fileinput.hook_encoded("cp932"))
result = parse("".join(data),
KanchokuTable,
comment=Comment)
print(result)
def test():
testdoc = """
; test ほげほげ
#define table-name "test-table"
#define defguide "あかさたな"
; test テーブル定義
{
"坊","剖","傍","亡","乏","妨","帽","忘","忙","房",
"烹","泡","法","朋","方","砲","縫","胞","芳","萌",
"峯","峰","宝","奉","報","崩","庖","抱","捧","放",
"豊","訪","褒","蜂","蓬","邦","鋒","飽","鳳","鵬" / "X",
,,,,,,,, {"坊","剖","傍","亡","乏","妨","帽","忘","忙","房",
"烹","泡","法","朋","方","砲","縫","胞","芳","萌",
"峯","峰","宝","奉","報","崩","庖","抱","捧","放",
"豊","訪","褒","蜂","蓬","邦","鋒","飽","鳳","鵬",
,,,,,,,,}
}
"""
result = (parse(testdoc, KanchokuTable, comment=Comment))
print(result)
#print(result[2][0])
"""
KanchokuTable([Option([OptionType('table-name'), '"test-table"']), Option([OptionType('defguide'), '"あかさたな"']), Block(['坊', '剖', '傍', '亡', '乏', '妨', '帽', '忘', '忙', '房', '烹', '泡', '法', '朋', '方', '砲', '縫', '胞', '芳', '萌', '峯', '峰', '宝', '奉', '報', '崩', '庖', '抱', '捧', '放', '豊', '訪', '褒', '蜂', '蓬', '邦', '鋒', '飽', '鳳', '鵬', '', '', '', '', '', '', '', '', Block(['坊', '剖', '傍', '亡', '乏', '妨', '帽', '忘', '忙', '房', '烹', '泡', '法', '朋', '方', '砲', '縫', '胞', '芳', '萌', '峯', '峰', '宝', '奉', '報', '崩', '庖', '抱', '捧', '放', '豊', '訪', '褒', '蜂', '蓬', '邦', '鋒', '飽', '鳳', '鵬', '', '', '', '', '', '', '', '', ''])]
)])
"""
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment