ããã°ã©ãã³ã°èšèªã®æ§é ãç ç©¶ãã人ã¯ã ãã§ããã®ä»çµã¿ã倧ãŸãã«æ³åã§ããŸããããŒãµãŒã¯ãJPã®æ£åŒãªææ³ã«åŸã£ãŠãå
¥åããã¹ããããªãŒãã¥ãŒã«å€æããŸãã
Pythonã§ã¯ãç©äºã¯ããå°ãè€éã§ãã2ã€ã®ããŒãµãŒããããŸãã æåã®ããŒãµãŒã¯ãæ£èŠè¡šçŸã®åœ¢åŒã§
Grammar/Grammar
ãã¡ã€ã«ã«æå®ããã
Grammar/Grammar
ïŒéåžžãšã¯ç°ãªãæ§æïŒã«ãã£ãŠã¬ã€ããããŸãã ãã®ææ³ã«ãããšã
Parser/pgen
ã䜿çšããŠã
python
ã³ã³ãã€ã«äžã«ãç¹å®ã®æ£èŠè¡šçŸãèªèãã
æéç¶æ
ãã·ã³ã®ã»ããå
šäœ
ãçæãããŸãïŒéçµç«¯èšå·ããšã«1 KAïŒã çµæãšããŠåŸãããå®å®è¹ã®ã»ããã®åœ¢åŒã¯ã
Include/grammar.h
ã§èª¬æãããŠãããå®å®è¹èªäœã¯ãã°ããŒãã«æ§é
_PyParser_Grammar
圢åŒã§
Python/graminit.c
èšå®ãããŠããŸãã çµç«¯èšå·ã¯ã
Include/token.h
ã§å®çŸ©ãããŠããã0..56ã®æ°åã«å¯Ÿå¿ããŠããŸãã é端æ«çªå·ã¯256ããå§ãŸããŸãã
æåã®ããŒãµãŒã®åäœã説æããæãç°¡åãªæ¹æ³ã¯ãäŸã䜿çšããããšã§ãã
if 42: print("Hello world")
ãŸãã
ããã«ãããã°ã©ã ã®åæã«å¯Ÿå¿ããææ³ã®äžéšããããŸã single_inputïŒNEWLINE | simple_stmt | compound_stmt NEWLINE
compound_stmtïŒif_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | è£
食ããã| async_stmt
if_stmtïŒ 'if'ãã¹ã 'ïŒ'ã¹ã€ãŒãïŒ 'elif'ãã¹ã 'ïŒ'ã¹ã€ãŒãïŒ* ['else' 'ïŒ'ã¹ã€ãŒã]
ã¹ã€ãŒãïŒsimple_stmt | NEWLINE INDENT stmt + DEDENT
simple_stmtïŒsmall_stmtïŒ ';' small_stmtïŒ* [';'] NEWLINE
small_stmtïŒexpr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt
expr_stmtïŒtestlist_star_exprïŒannassign | augassignïŒyield_expr | testlistïŒ|ïŒ '='ïŒyield_expr | testlist_star_exprïŒïŒ*ïŒ
testlist_star_exprïŒïŒãã¹ã| star_exprïŒïŒ 'ã'ïŒãã¹ã| star_exprïŒïŒ* ['ã']
ãã¹ãïŒor_test ['if' or_test 'else' test] | ã©ã ãã
or_testïŒand_testïŒ 'or' and_testïŒ*
and_testïŒnot_testïŒ 'and' not_testïŒ*
not_testïŒ 'not' not_test | æ¯èŒ
æ¯èŒïŒexprïŒcomp_op exprïŒ*
exprïŒxor_exprïŒ '|' xor_exprïŒ*
xor_exprïŒand_exprïŒ '^' and_exprïŒ*
and_exprïŒshift_exprïŒ 'ïŒ' shift_exprïŒ*
shift_exprïŒarith_exprïŒïŒ '<<' | '>>'ïŒarith_exprïŒ*
arith_exprïŒtermïŒïŒ '+' | '-'ïŒtermïŒ*
termïŒfactorïŒïŒ '*' | '@' | '/' | 'ïŒ
' | '//'ïŒãã¡ã¯ã¿ãŒïŒ*
ãã¡ã¯ã¿ãŒïŒïŒ '+' | '-' | 'ã'ïŒãã¡ã¯ã¿ãŒ| å
ãã¯ãŒïŒatom_expr ['**' factor]
atom_exprïŒ[AWAIT]ã¢ãã ãã¬ãŒã©ãŒ*
ã¢ãã ïŒ 'ïŒ' [yield_expr | testlist_comp] 'ïŒ' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING + | '...' | ããªãã| ãçã| ãFalseã
äºåç·šïŒ 'ïŒ' [arglist] 'ïŒ' | '[' subscriptlist ']' | ããã NAME
arglistïŒåŒæ°ïŒ 'ã'åŒæ°ïŒ* ['ã']
åŒæ°ïŒãã¹ã[comp_for] | ãã¹ã '='ãã¹ã| '**'ãã¹ã| ã*ããã¹ã
ãããŠãããã¯_PyParser_Grammaræ§é ã®è峿·±ãéšåãPython / graminit.cã§ã©ã®ããã«å®çŸ©ããããã§ã static arc arcs_0_0[3] = { {2, 1}, {3, 1}, {4, 2}, }; static arc arcs_0_1[1] = { {0, 1}, }; static arc arcs_0_2[1] = { {2, 1}, }; static state states_0[3] = { {3, arcs_0_0}, {1, arcs_0_1}, {1, arcs_0_2}, }; //... static arc arcs_39_0[9] = { {91, 1}, {92, 1}, {93, 1}, {94, 1}, {95, 1}, {19, 1}, {18, 1}, {17, 1}, {96, 1}, }; static arc arcs_39_1[1] = { {0, 1}, }; static state states_39[2] = { {9, arcs_39_0}, {1, arcs_39_1}, }; //... static arc arcs_41_0[1] = { {97, 1}, }; static arc arcs_41_1[1] = { {26, 2}, }; static arc arcs_41_2[1] = { {27, 3}, }; static arc arcs_41_3[1] = { {28, 4}, }; static arc arcs_41_4[3] = { {98, 1}, {99, 5}, {0, 4}, }; static arc arcs_41_5[1] = { {27, 6}, }; static arc arcs_41_6[1] = { {28, 7}, }; static arc arcs_41_7[1] = { {0, 7}, }; static state states_41[8] = { {1, arcs_41_0}, {1, arcs_41_1}, {1, arcs_41_2}, {1, arcs_41_3}, {3, arcs_41_4}, {1, arcs_41_5}, {1, arcs_41_6}, {1, arcs_41_7}, }; //... static dfa dfas[85] = { {256, "single_input", 0, 3, states_0, "\004\050\340\000\002\000\000\000\012\076\011\007\262\004\020\002\000\300\220\050\037\102"}, //... {270, "simple_stmt", 0, 4, states_14, "\000\040\200\000\002\000\000\000\012\076\011\007\000\000\020\002\000\300\220\050\037\100"}, //... {295, "compound_stmt", 0, 2, states_39, "\000\010\140\000\000\000\000\000\000\000\000\000\262\004\000\000\000\000\000\000\000\002"}, {296, "async_stmt", 0, 3, states_40, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {297, "if_stmt", 0, 8, states_41, "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, // ^^^ //... }; static label labels[176] = { {0, "EMPTY"}, {256, 0}, {4, 0}, // â2 {270, 0}, // â3 {295, 0}, // â4 //... {305, 0}, // â26 {11, 0}, // â27 //... {297, 0}, // â91 {298, 0}, {299, 0}, {300, 0}, {301, 0}, {296, 0}, {1, "if"}, // â97 //... }; grammar _PyParser_Grammar = { 86, dfas, {176, labels}, 256 };
ïŒãã®ãªã¹ãã§ã®ããŒãµãŒã®äœæ¥ã«é¢ããæ¬¡ã®èª¬æã«åŸããšäŸ¿å©ã§ããããšãã°ã次ã®ã¿ãã§éããŸããïŒ
ããŒãµãŒã¯ã
single_input
ã®SCããè§£æãéå§ããŸãã ãã®å®å®è¹ã¯ã3ã€ã®ç¶æ
ã®
states_0
é
åã«ãã£ãŠå®çŸ©ãããŸãã å
¥å
NEWLINE
æåïŒã©ãã«çªå·2ãã·ã³ãã«çªå·4ïŒã
simple_stmt
ïŒã©ãã«çªå·3ãã·ã³ãã«çªå·270ïŒã
compound_stmt
ïŒã©ãã«çªå·4ãã·ã³ãã«çªå·295ïŒã«å¯Ÿå¿ããŠã3ã€ã®ã¢ãŒã¯ïŒ
arcs_0_0
ïŒãåæç¶æ
ããå€ããŸãã å
¥å端å
"if"
ïŒã·ã³ãã«No. 1ãã©ãã«No. 97ïŒã¯
d_first
ã»ããã«å«ãŸããŠããŸããã
d_first
ã¯å«ãŸããŠããŸãã-ã»ããã®13çªç®ã®ãã€ãã®ããã\ 002ã«å¯Ÿå¿ããŠããŸãã ïŒè§£æäžã«ã次ã®ç«¯æ«ãè€æ°ã®çºä¿¡ã¢ãŒã¯ã®
d_first
ã»ããã«äžåºŠã«å«ãŸããŠããããšã倿ããå ŽåãããŒãµãŒã¯ãææ³ããããŸãã§ãããè§£æã®ç¶è¡ãæåŠãããšããã¡ãã»ãŒãžã衚瀺ããŸããïŒãããã£ãŠãããŒãµãŒã¯ã¢ãŒã¯
{4, 2}
d_first
{4, 2}
ã«æ²¿ã£ãŠç¶æ
ã«é²ã¿ãŸãNo. 2ãåæã«ã
states_39
é
åã§æå®ããã
compound_stmt
å®å®è¹ã«åãæ¿ããŸãã ãã®å®å®è¹ã§ã¯ã9ã€ã®ã¢ãŒã¯ãããã«åæç¶æ
ïŒ
arcs_39_0
ïŒãé¢ããŸãã ãã®äžã§ãå
¥åã·ã³ãã«
if_stmt
ïŒNo. 297ïŒã«å¯Ÿå¿ââããã¢ãŒã¯
{91, 1}
if_stmt
{91, 1}
ãéžæããŸãã ããŒãµãŒã¯ç¶æ
1ã«åãæ¿ããã
states_41
é
åã§æå®ããã
states_41
å®å®è¹ã«åãæ¿ãããŸãã
ãã®å®å®è¹ã®åæç¶æ
ããã¯ãå
¥å端å
"if"
察å¿ãã1ã€ã®ã¢ãŒã¯
{97, 1}
ã®ã¿ãåºçŸããŸãã ãã®äžã§ãããŒãµãŒã¯ç¶æ
No. 1ã«åãæ¿ãããããããå¯äžã®ã¢ãŒã¯
{26, 2}
26ã2
{26, 2}
ãåºãŸããããã¯ãéçµç«¯
test
ïŒNo. 305ïŒã«å¯Ÿå¿ããŸãã ãã®ã¢ãŒã¯ã§ã¯ãããŒãµãŒã¯ç¶æ
2ã«åãæ¿ããã
test
å®å®è¹ã«åãæ¿ãããŸãã çªå·
42
ã®
test
éçµç«¯èšå·ãžã®é·ãé·ã倿ã®åŸãããŒãµãŒã¯ç¶æ
2ã«æ»ããããããå¯äžã®ã¢ãŒã¯
{27, 3}
if_stmt
{27, 3}
COLON
ãã
COLON
端æ«ïŒèšå·çªå·11ïŒã«å¯Ÿå¿ãã
if_stmt
éçµç«¯èšå·ã®è§£æãç¶è¡ããŸãã åæã®çµæãããŒãµãŒã¯
ç¹å®ã®æ§æããªãŒ ïŒ
node
æ§é ïŒã®ããŒããäœæããŸããããŒãã¯ãããŒãã¿ã€ã297ãããã³4
NAME
ïŒã¿ã€ãNo. 1ïŒ
NAME
ïŒãNoã305ïŒ
test
ïŒãNoã11ïŒ
COLON
ïŒããã³No. 304ïŒ
suite
ïŒã ç¶æ
çªå·4ã§
if_stmt
ã®ããŒãã®äœæ
if_stmt
å®äºãããšãããŒãµãŒã¯ã¹ããŒã¹ã¯ã©ãã
compound_stmt
ç¶æ
çªå·1ã«æ»ãã
if_stmt
æ°ããäœæãããããŒãã
if_stmt
察å¿ããããŒãã®å¯äžã®åã«ãªããŸãã ããã°ã©ã ã®KSDå
šäœã¯ãå³ã®å³ã®ããã«ãªããŸãã 7ã€ã®ç«¯æ«ã®çãããã°ã©ã
NAME NUMBER COLON NAME LPAR STRING RPAR
ãã©ã®ããã«ã竹ãã«ãªã£ããã«æ³šç®ããŠãã ãããããã¯ã
NAME NUMBER COLON NAME LPAR STRING RPAR
64ããŒãã®å·šå€§ã§åå²ã®ãªãè§£æããªãŒã§ãã ãã€ãåäœã§ã«ãŠã³ããããšãå
ã®ããã°ã©ã ã¯27ãã€ããæ¶è²»ãããã®KSDã¯2æ¡å€§ãããªããŸãã32ãããã·ã¹ãã ã§ã¯1.5ãããã€ãã64ãããã·ã¹ãã ã§ã¯3ãããã€ãã§ãã ïŒãããã24ãŸãã¯48ãã€ãã®64ããŒãïŒã ããã¯ããµã€ãºãæ°åã¡ã¬ãã€ãã®
python
ãœãŒã¹ãã¡ã€ã«ãééããããšããCSDã®ç¡å¶éã®ã¹ãã¬ãããåå ã§ãèŽåœçãª
MemoryError
ã§ãã
Pythonã§KSDã䜿çšããå Žåãæšæºã®
parser
ã¢ãžã¥ãŒã«ããããŸãã
$ python Python 3.7.0a0 (default:98c078fca8e0, Oct 31 2016, 08:33:23) [GCC 4.7.3] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import parser >>> parser.suite('if 42: print("Hello world")').tolist() [257, [269, [295, [297, [1, 'if'], [305, [309, [310, [311, [312, [315, [316, [317, [318, [319, [320, [321, [322, [323, [324, [2, '42']]]]]]]]]]]]]]]], [11, ':'], [304, [270, [271, [272, [274, [305, [309, [310, [311, [312, [315, [316, [317, [318, [319, [320, [321, [322, [323, [324, [1, 'print']], [326, [7, '('], [334, [335, [305, [309, [310, [311, [312, [315, [316, [317, [318, [319, [320, [321, [322, [323, [324, [3, '"Hello world"']]]]]]]]]]]]]]]]]], [8, ')']]]]]]]]]]]]]]]]]]], [4, '']]]]]], [4, ''], [0, '']] >>>
ãã®ãœãŒã¹ã³ãŒãïŒ
Modules/parsermodule.c
ïŒã§ãCSDãPythonã®ææ³ã«æºæ ããŠãããã©ããã確èªããããã«ã次ã®ãããªææžãè¡ã2000è¡ä»¥äžãããŸããã
//... /* simple_stmt | compound_stmt * */ static int validate_stmt(node *tree) { int res = (validate_ntype(tree, stmt) && validate_numnodes(tree, 1, "stmt")); if (res) { tree = CHILD(tree, 0); if (TYPE(tree) == simple_stmt) res = validate_simple_stmt(tree); else res = validate_compound_stmt(tree); } return (res); } static int validate_small_stmt(node *tree) { int nch = NCH(tree); int res = validate_numnodes(tree, 1, "small_stmt"); if (res) { int ntype = TYPE(CHILD(tree, 0)); if ( (ntype == expr_stmt) || (ntype == del_stmt) || (ntype == pass_stmt) || (ntype == flow_stmt) || (ntype == import_stmt) || (ntype == global_stmt) || (ntype == nonlocal_stmt) || (ntype == assert_stmt)) res = validate_node(CHILD(tree, 0)); else { res = 0; err_string("illegal small_stmt child type"); } } else if (nch == 1) { res = 0; PyErr_Format(parser_error, "Unrecognized child node of small_stmt: %d.", TYPE(CHILD(tree, 0))); } return (res); } /* compound_stmt: * if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated */ static int validate_compound_stmt(node *tree) { int res = (validate_ntype(tree, compound_stmt) && validate_numnodes(tree, 1, "compound_stmt")); int ntype; if (!res) return (0); tree = CHILD(tree, 0); ntype = TYPE(tree); if ( (ntype == if_stmt) || (ntype == while_stmt) || (ntype == for_stmt) || (ntype == try_stmt) || (ntype == with_stmt) || (ntype == funcdef) || (ntype == async_stmt) || (ntype == classdef) || (ntype == decorated)) res = validate_node(tree); else { res = 0; PyErr_Format(parser_error, "Illegal compound statement type: %d.", TYPE(tree)); } return (res); } //...
ãã®ãããªåäžãªã³ãŒãã¯ãæ£åŒãªææ³ã䜿çšããŠèªåçã«çæã§ãããšæšæž¬ããã®ã¯ç°¡åã§ãã ãã®ãããªã³ãŒãã
ãã§ã«èªåçã«çæãããŠãããšæšæž¬ããã®ã¯å°ãé£ããã§ã-ããããŸãã«ãæåã®ããŒãµãŒã§äœ¿çšããããã·ã³ã®åäœã§ãïŒ äžèšã§ãä»å¹Žã®3æã«ãææ³ã倿Žããããã³ã«ç·šéããå¿
èŠãããææžãã³ãŒãã®ããããã¹ãŠã®ã·ãŒããã䜿çšããåãèªåçæããããã¹ãŠã®å®å®è¹ã®å®è¡ã§çœ®ãæããããšã
ææ¡ããæ¹æ³ã説æããããã«ããã®æ§é ã詳现ã«èª¬æããŸããããŒãµãŒèªäœã ããã¯ãããã°ã©ããã¢ã«ãŽãªãºã ãç¥ãå¿
èŠããããã©ããã«ã€ããŠ
話ãããšã§ãã
6æã«ç§ã®ããããåãå
¥ãããããããPython 3.6以éã§ã¯ãäžèšã®
Modules/parsermodule.c
ã·ãŒãã¯ãªããªããŸããããæ°åè¡ã®ã³ãŒãããããŸãã
äžèšã®ããã«ããã®ãããªããã°ã£ãŠéå°ãªKSDãæ±ãã®ã¯éåžžã«äžäŸ¿ã§ãã ãããã£ãŠãå®å
šã«ææžãã§èšè¿°ããã2çªç®ã®ããŒãµãŒïŒ
Python/ast.c
ïŒã¯KSDããã€ãã¹ãã
ããããæœè±¡æ§æããªãŒãäœæã
ãŸã ã SDAã®ææ³ã¯
Parser/Python.asdl
èšè¿°ãããŠã
Parser/Python.asdl
ã ãã®ããã°ã©ã ã®å ŽåãSDAã¯å³ã®ããã«ãªããŸãã
parser
ã¢ãžã¥ãŒã«ã䜿çšããŠKSDãæäœãã代ããã«ãããã¥ã¡ã³ãã§ã¯ã
ast
ã¢ãžã¥ãŒã«ã䜿çšããŠæœè±¡ããªãŒãæäœããããšã
ast
ãŸãã
$ python Python 3.7.0a0 (default:98c078fca8e0, Oct 31 2016, 08:33:23) [GCC 4.7.3] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import ast >>> ast.dump(ast.parse('if 42: print("Hello world")')) "Module(body=[If(test=Num(n=42), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Str(s='Hello world')], keywords=[]))], orelse=[])])" >>>
ASDãäœæããããšããã«ãKSDã¯äžèŠã«ãªããKSDãå æããŠãããã¹ãŠã®ã¡ã¢ãªãè§£æŸãããŸãã ãããã£ãŠãPythonã®ãé·æéåçãããã°ã©ã ã®å ŽåãKSDãã©ãã ãã®ã¡ã¢ãªã䜿çšãããã¯å®éã«ã¯é¢ä¿ãããŸããã äžæ¹ãå€§èŠæš¡ã§ã¯ããããé«é
dict
ãã¹ã¯ãªããïŒããšãã°ã巚倧ãª
dict
ãªãã©ã«ã§å€ãæ€çŽ¢ããïŒã®å ŽåãRDCã®ãµã€ãºã«ãã£ãŠã¹ã¯ãªããã«ããã¡ã¢ãªæ¶è²»ã決ãŸããŸãã KSDã®ãµã€ãºã«ãã£ãŠãããã°ã©ã ãããŠã³ããŒãããŠå®è¡ããããã«ååãªã¡ã¢ãªããããã©ãããæ±ºãŸããšããäºå®ã«å ããŠããã®ãã¹ãŠã
é·ããç«¹ã®æãã«æ²¿ã£ãŠæ©ãå¿
èŠãããããã
Python/ast.c
åã«ããããããŸãã
static expr_ty ast_for_expr(struct compiling *c, const node *n) { //... loop: switch (TYPE(n)) { case test: case test_nocond: if (TYPE(CHILD(n, 0)) == lambdef || TYPE(CHILD(n, 0)) == lambdef_nocond) return ast_for_lambdef(c, CHILD(n, 0)); else if (NCH(n) > 1) return ast_for_ifexpr(c, n); /* Fallthrough */ case or_test: case and_test: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } // case not_test: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } // not_test case comparison: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } // comparison case star_expr: return ast_for_starred(c, n); /* The next five cases all handle BinOps. The main body of code is the same in each case, but the switch turned inside out to reuse the code for each type of operator. */ case expr: case xor_expr: case and_expr: case shift_expr: case arith_expr: case term: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } return ast_for_binop(c, n); // case yield_expr: case factor: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } return ast_for_factor(c, n); case power: return ast_for_power(c, n); default: PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n)); return NULL; } /* should never get here unless if error is set */ return NULL; }
if (NCH(n) == 1) n = CHILD(n, 0);
2çªç®ã®ããŒãµãŒå
šäœã§ç¹°ãè¿ãç¹°ãè¿ãã
if (NCH(n) == 1) n = CHILD(n, 0);
-æã
ããã®é¢æ°ã®ããã«ããµã€ã¯ã«å
ã§-ãçŸåšã®KSDããŒãã«åã1ã€ãããªãå ŽåãçŸåšã®ããŒãã®ä»£ããã«ãã®åãèæ
®ããå¿
èŠããããããšãæå³ããŸãã
ããããKSDã®äœæäžã«ã1åãããŒããåé€ãããã®åããããã®ä»£ããã«äœ¿çšããããšãããã«é²ãããšã¯ã§ããŸããïŒ çµå±ã®ãšãããããã«ããå€ãã®ã¡ã¢ãªãç¯çŽããã2çªç®ã®ããŒãµãŒãç°¡çŽ åããã
goto loop;
è€æ°ã®ç¹°ãè¿ããåãé€ãããšãã§ããŸã
goto loop;
ã³ãŒãå
šäœã§ã
ãã€ã¯ã¹ãã©ã圌ã®topã§ãããã
åããšãã芳ç¹ããïŒ
3æã«ãåè¿°ã®
Modules/parsermodule.c
ããããšãšãã«ã
å¥ã®ããããææ¡ããŸããã
- éåå²ãµãããªãŒã®èªåãå§çž®ããæåã®ããŒãµãŒã«è¿œå ããŸã- æãããã¿ ïŒKSDããŒããäœæããçŸåšã®å®å®è¹ããåã®å®å®è¹ã«æ»ãïŒæã«ãé©åãªã¿ã€ãã®ã1ã€ã®åãããŒãããã®åã«çœ®ãæããããŸãïŒ
diff -r ffc915a55a72 Parser/parser.c --- a/Parser/parser.c Mon Sep 05 00:01:47 2016 -0400 +++ b/Parser/parser.c Mon Sep 05 08:30:19 2016 +0100 @@ -52,16 +52,16 @@ #ifdef Py_DEBUG static void s_pop(stack *s) { if (s_empty(s)) Py_FatalError("s_pop: parser stack underflow -- FATAL"); - s->s_top++; + PyNode_Compress(s->s_top++->s_parent); } #else /* !Py_DEBUG */ -#define s_pop(s) (s)->s_top++ +#define s_pop(s) PyNode_Compress((s)->s_top++->s_parent) #endif diff -r ffc915a55a72 Python/ast.c --- a/Python/ast.c Mon Sep 05 00:01:47 2016 -0400 +++ b/Python/ast.c Mon Sep 05 08:30:19 2016 +0100 @@ -5070,3 +5056,24 @@ FstringParser_Dealloc(&state); return NULL; } + +void PyNode_Compress(node* n) { + if (NCH(n) == 1) { + node* ch; + switch (TYPE(n)) { + case suite: case comp_op: case subscript: case atom_expr: + case power: case factor: case expr: case xor_expr: + case and_expr: case shift_expr: case arith_expr: case term: + case comparison: case testlist_star_expr: case testlist: + case test: case test_nocond: case or_test: case and_test: + case not_test: case stmt: case dotted_as_name: + if (STR(n) != NULL) + PyObject_FREE(STR(n)); + ch = CHILD(n, 0); + *n = *ch; + // All grandchildren are now adopted; don't need to free them, + // so no need for PyNode_Free + PyObject_FREE(ch); + } + } +}
- ãbambooãã©ã³ããããã€ãã¹ããããšãé€ããŠã2çªç®ã®ããŒãµãŒãæ£ããä¿®æ£ããŸããããšãã°ãäžèšã®é¢æ°
ast_for_expr
ã¯æ¬¡ã®ããã«çœ®ãæããããŸãã
static expr_ty ast_for_expr(struct compiling *c, const node *n) { //... switch (TYPE(n)) { case lambdef: case lambdef_nocond: return ast_for_lambdef(c, n); case test: case test_nocond: assert(NCH(n) > 1); return ast_for_ifexpr(c, n); case or_test: case and_test: assert(NCH(n) > 1); // case not_test: assert(NCH(n) > 1); // not_test case comparison: assert(NCH(n) > 1); // comparison case star_expr: return ast_for_starred(c, n); /* The next five cases all handle BinOps. The main body of code is the same in each case, but the switch turned inside out to reuse the code for each type of operator. */ case expr: case xor_expr: case and_expr: case shift_expr: case arith_expr: case term: assert(NCH(n) > 1); return ast_for_binop(c, n); // case yield_expr: case factor: assert(NCH(n) > 1); return ast_for_factor(c, n); case power: return ast_for_power(c, n); case atom: return ast_for_atom(c, n); case atom_expr: return ast_for_atom_expr(c, n); default: PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n)); return NULL; } /* should never get here unless if error is set */ return NULL; }
äžæ¹ãå€ãã®ããŒãã§ã¯ãããã©ã³ãå§çž®ãã®çµæãšããŠãåã¯æ°ããã¿ã€ãã«ãªãå¯èœæ§ããããããã³ãŒãã®å€ãã®å Žæã§æ°ããæ¡ä»¶ã远å ããå¿
èŠããããŸãã
- ã
Modules/parsermodule.c
ãããKSDãã¯Pythonã®ææ³ã«å¯Ÿå¿ããŠããªãããããrawã _PyParser_Grammar
代ããã«Modules/parsermodule.c
ãã®æ£ç¢ºæ§ã確èªããããã«ãããšãã°ããããã¯ã·ã§ã³ã®ãã¢ã®ãæšç§»çéå
ãã«å¯Ÿå¿ãããªãŒãããã³ã䜿çšããå¿
èŠããã_PyParser_Grammar
or_test :: = and_test
ãã¹ã:: = or_test 'if' or_test 'else'ãã¹ã
-次ã®ãæšç§»çãªã補åã远å ãããŸããã
test :: = or_test 'if' and_test 'else' test
ãã¹ã:: = and_test 'if' or_test 'else'ãã¹ã
ãã¹ã:: = and_test 'if' and_test 'else' test
parser
ã¢ãžã¥ãŒã«ã®åæåäžã Init_ValidationGrammar
颿°ã¯Init_ValidationGrammar
ã§_PyParser_Grammar
çæãããå®å®è¹ããã€ãã¹ãããããã«åºã¥ããŠãæšç§»çã«éãããå®å®è¹ãäœæãã ValidationGrammar
æ§é ã«ä¿åããŸãã ValidationGrammar
ãKSDã®æ£ç¢ºæ§ãæ€èšŒããããã«äœ¿çšãããŸãã
ãµã³ãã«ã³ãŒãã®å§çž®ãããKSDã«ã¯ãåèš21åã®ããŒããå«ãŸããŠããŸãã
$ python Python 3.7.0a0 (default:98c078fca8e0+, Oct 31 2016, 09:00:27) [GCC 4.7.3] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import parser >>> parser.suite('if 42: print("Hello world")').tolist() [257, [295, [297, [1, 'if'], [324, [2, '42']], [11, ':'], [270, [271, [272, [323, [324, [1, 'print']], [326, [7, '('], [334, [335, [324, [3, '"Hello world"']]]], [8, ')']]]]], [4, '']]]], [4, ''], [0, '']] >>>
ç§ã®ãããã§ã¯
ããã³ãããŒã¯ã®
æšæºã»ãã㯠ã python
ããã»ã¹ã«ããã¡ã¢ãªæ¶è²»éãæå€§30ïŒ
åæžãããåäœæéã¯å€ãããªãããšã瀺ããŠããŸãã çž®éããäŸã§ã¯ãã¡ã¢ãªæ¶è²»ã®åæžã¯
3åã«éããŸãïŒ
ããããæ®å¿µãªãããããããææ¡ããŠããå幎éãã¡ã³ããã¯èª°ããããæ¹èšããããšã¯ããŸããã§ãã-ãšãŠã倧ãããŠæãã§ãã 9æã
Guido van Rossumèªèº«
ãç§ã«çããŸãã ã
ã以æ¥ããã®ãããã«ã¯èª°ãé¢å¿ã瀺ããŠããŸãããã€ãŸããããŒãµãŒã¯ä»ã®äººã®ã¡ã¢ãªæ¶è²»ãæ°ã«ããŸããã ãã®ãããã¡ã³ãããŒã®ã¬ãã¥ãŒã«æéãæµªè²»ããŠãæå³ããããŸãããããã®èšäºã§ãç§ã®å€§ãããŠæãããããããå®éã«å¿
èŠã§äŸ¿å©ãªçç±ã説æããŠãããããšãæåŸ
ããŠããŸãã ãã®èª¬æã®åŸãPythonã³ãã¥ããã£ããããæã«å
¥ããããšãé¡ã£ãŠããŸãã