Hatena::Groupfukuoka-py

ikikko.py このページをアンテナに追加 RSSフィード

2009-03-16

Pygmentsの自作字句解析(入門)

01:32 |  Pygmentsの自作字句解析(入門) - ikikko.py を含むブックマーク はてなブックマーク -  Pygmentsの自作字句解析(入門) - ikikko.py  Pygmentsの自作字句解析(入門) - ikikko.py のブックマークコメント

(追記:構文解析と字句解析を間違えていたので、タイトルその他を修正)


最近、読書の割合が多くなってきて、あまりアウトプットができていない。もちろん読書(インプット)も大事だけど、やっぱりアウトプットしてこそなんぼ…てのはあるので、もっと意識してやっていかんと!


下記のプラグインの追加

(中略)

Trac Lightning2.1alpha1リリース - almost nearly dead

上記のように、Trac Lightning2.1からシンタックスハイライトPygmentsが追加されています。ですが、Pygmentsには今仕事で扱っているABAP言語には対応していません。

大丈夫、ご安心ください。Pygmentsでは、字句解析プログラムを自作して拡張することができます。というわけで、PygmentsをABAPでもハイライトできるようにしてみましょう*1

なお、ここではABAPを取り上げていますが、どの言語に対応させるときでも基本は一緒なはずです。


サンプルコード

対象とするコードは、SAP Help Portalを使います。highlight関数を用いて「abap.txt」のソースコードを「abap.html」にハイライトした形で出力できます。

from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter


if __name__ == '__main__':
    code = ''
    for line in file('abap.txt', 'r').readlines():
        code += line

    highlight(code, AbapLexer(), HtmlFormatter(full=True), file('abap.html', 'w'))

何もハイライトをしてないデフォルトの状態は↓な感じです。

f:id:ikikko:20090317005230p:image

第1ステップ:lexerクラスの作成

さぁ、ここから自作のlexerを作っていきましょう♪

import re

from pygments.lexer import RegexLexer, bygroups
from pygments.token import *


class AbapLexer(RegexLexer):
    name = 'ABAP'

    flags = re.IGNORECASE | re.MULTILINE
    tokens = {
        'root': [
            (r'\s+', Text),
            (r'.', Text),
        ],
    }
  • RegexLexerクラスを継承して、正規表現で字句解析を行うことができるようにします。
  • name属性は無くても構いません。設定しておくと、組み込みのlexer機能側で何かいいことをしてくれるみたいですw
  • ABAPでは大文字小文字の区別が無いので、正規表現フラグ「re.IGNORECASE」をセットしておきます。
  • tokensでは「root」の上から順にマッチングをしていきます。まずは、空白をText形式で表示するようにしておきます。で、最初はとりあえず全てText形式で表示するようにしておきましょう。

これだけでは結局何もハイライトはされませんが、うまくコンパイルできていることは確認できると思います。

第2ステップ:コメントのハイライト

ABAPでのコメントは、行頭が「*」で始まる行か「"」以降の文字列です*2。サンプルコードには「*」が出てきているので、とりあえずそちらに対応してみましょう。

    tokens = {
        'root': [
            (r'\s+', Text),
            (r'^\*(.*)$', Comment),
            (r'.', Text),
        ],
    }
  • 先ほどの「root」中に、「*」で始まる行はCommentとみなすように設定します。

結果は↓な感じ。ちょっと色が出ました。

f:id:ikikko:20090317005232p:image

第3ステップ:キーワード文字列リテラルハイライト

さぁ、この調子でどんどん色をつけていきましょう。続いては、キーワード文字列リテラルハイライト

    tokens = {
        'root': [
            (r'\s+', Text),
            (r'^\*(.*)$', Comment),
            (r'(call screen|default|parameters|position|report|skip to line|write)', Keyword),
            (r"'[^']*'", String),
            (r'.', Text),
        ],
    }

最終的な結果は↓な感じ。キーワードが緑色に、リテラルが赤色にハイライトされています。とりあえず、サンプルコードに対しては、こんなものでしょう。

f:id:ikikko:20090317005233p:image


で、当初の目的である「ABAPのPygments対応」ですが、実は404 Not Foundにまんまあります。知らない内に誰か作ってくれてたみたい…orz

けど、前ぐぐった時にはこんなの見つからなかったよな?って見てみると、2009/02/25にチケット発行か。一応、

pygmentのABAP拡張できないかな?ちょっと調べてみよう。

Shibuya.trac新年会 感想 - @ikikko のはてなブログ

と、2009/01/15@Shibuya.trac新年会でアイデアは頭にあったので、さっさと行動しておけば。くやしいです・・・><


今回の教訓:考えるだけじゃ意味がない、すぐに行動に移そう。

*1:念のため補足しておくと、仕事でTracを使える可能性は限りなく0に近いですが、興味をそそられたのでまずはやってみることに。エンジニアとして、好奇心は大事なことですよねw

*2:残念ながら、ABAPにはマルチラインコメントはありません

*3:もちろん、ABAPキーワードはこれだけではないので、まじめにやるならば全てを列挙しておく必要があります

GeorgesGeorges2012/02/21 05:27Please keep throniwg these posts up they help tons.

JasonerumpJasonerump2017/01/25 04:26книга на заказ http://wkrolik.com.ua/products/konverty