Created
March 4, 2016 13:52
-
-
Save tomoemon/b0f6e44c7cb73f3904ba to your computer and use it in GitHub Desktop.
This file contains 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
# -*- 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