2009-10-10 20 views
9

はPythonの文法のサブセットです:pyparsingでインデントと献辞を解析するにはどうすればよいですか?ここ

single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE 

stmt: simple_stmt | compound_stmt 
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE 

small_stmt: pass_stmt 
pass_stmt: 'pass' 

compound_stmt: if_stmt 
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] 

suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT 

(あなたはPythonのSVNリポジトリで完全な文法読むことができます:http://svn.python.org/.../Grammar)を

私はPython用のパーサを生成するには、この文法を使用しようとしています、Pythonで。私が問題を抱えているのは、INDENTDEDENTのトークンをpyparsingオブジェクトとして表現する方法です。ここで

は、私は他の端末を実装している方法です。

import pyparsing as p 

string_start = (p.Literal('"""') | "'''" | '"' | "'") 
string_token = ('\\' + p.CharsNotIn("",exact=1) | p.CharsNotIn('\\',exact=1)) 
string_end = p.matchPreviousExpr(string_start) 

terminals = { 
    'NEWLINE': p.Literal('\n').setWhitespaceChars(' \t') 
     .setName('NEWLINE').setParseAction(terminal_action('NEWLINE')), 
    'ENDMARKER': p.stringEnd.copy().setWhitespaceChars(' \t') 
     .setName('ENDMARKER').setParseAction(terminal_action('ENDMARKER')), 
    'NAME': (p.Word(p.alphas + "_", p.alphanums + "_", asKeyword=True)) 
     .setName('NAME').setParseAction(terminal_action('NAME')), 
    'NUMBER': p.Combine(
      p.Word(p.nums) + p.CaselessLiteral("l") | 
      (p.Word(p.nums) + p.Optional("." + p.Optional(p.Word(p.nums))) | "." + p.Word(p.nums)) + 
       p.Optional(p.CaselessLiteral("e") + p.Optional(p.Literal("+") | "-") + p.Word(p.nums)) + 
       p.Optional(p.CaselessLiteral("j")) 
     ).setName('NUMBER').setParseAction(terminal_action('NUMBER')), 
    'STRING': p.Combine(
      p.Optional(p.CaselessLiteral('u')) + 
      p.Optional(p.CaselessLiteral('r')) + 
      string_start + p.ZeroOrMore(~string_end + string_token) + string_end 
     ).setName('STRING').setParseAction(terminal_action('STRING')), 

    # I can't find a good way of parsing indents/dedents. 
    # The Grammar just has the tokens NEWLINE, INDENT and DEDENT scattered accross the rules. 
    # A single NEWLINE would be translated to NEWLINE + PEER (from pyparsing.indentedBlock()), unless followed by INDENT or DEDENT 
    # That NEWLINE and IN/DEDENT could be spit across rule boundaries. (see the 'suite' rule) 
    'INDENT': (p.LineStart() + p.Optional(p.Word(' '))).setName('INDENT'), 
    'DEDENT': (p.LineStart() + p.Optional(p.Word(' '))).setName('DEDENT') 
} 

terminal_actionは、その引数に応じて、対応する解析するアクションを返す関数です。

私はpyparsing.indentedBlockヘルパー機能を認識していますが、PEERトークンを使用せずに文法にどのように採用するのか分かりません。

(私が何を言っているか確認するためにpyparsing souce codeを見てください)

あなたがここに私の完全なソースコードを見ることができます:http://pastebin.ca/1609860

答えて

10

あなたを与えることができるpyparsingウィキExamples page上の例のカップルがあります。いくつかの洞察:

pyparsingのindentedBlockを使用するには、私はあなたのようにsuiteを定義するだろうと思う:pyparsingでindentedBlockindentedGrammarExample.py前の日付を含めること

indentstack = [1] 
suite = indentedBlock(stmt, indentstack, True) 

注ので、インデント解析の独自のimplementionはありません。

関連する問題