Skip to content

Instantly share code, notes, and snippets.

@qnighy
Last active June 2, 2022 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qnighy/b1292689914b0029de2754b3d90d45fd to your computer and use it in GitHub Desktop.
Save qnighy/b1292689914b0029de2754b3d90d45fd to your computer and use it in GitHub Desktop.

parse.y

字句解析状態

基本の字句解析状態はlex_state_bits, lex_state_eにある。

  • EXPR_BEG
    • 式の開始位置
  • EXPR_END
    • リテラル・識別子の終了位置
  • EXPR_ENDARG
  • EXPR_ENDFN
  • EXPR_ARG
  • EXPR_CMDARG
  • EXPR_MID
  • EXPR_FNAME
  • EXPR_DOT
  • EXPR_CLASS
  • EXPR_LABEL
  • EXPR_LABELED
  • EXPR_FITEM

これらとは別に p->ctxt.in_kwarg などの補助状態がある

lexer実装の直前にも補助関数がある

  • EXPR_VALUE
  • EXPR_BEG_ANY ... EXPR_BEG または EXPR_MID または EXPR_CLASS
  • EXPR_ARG_ANY ... EXPR_ARG または EXPR_CMDARG
  • EXPR_END_ANY ... EXPR_END または EXPR_ENDARG または EXPR_ENDFN
  • EXPR_NONE ... いずれでもない
  • IS_ARG ... EXPR_ARG_ANYと同じ
  • IS_END ... EXPR_END_ANYと同じ
  • IS_BEG ... 以下のいずれかを満たすことを判定
    • EXPR_BEG_ANY
    • EXPR_ARG かつ EXPR_LABELED
  • IS_SPCARG ... IS_ARGに加えて、以下の条件を追加で満たすことを判定
    • 直前に空白がある
    • かつ、直後が空白ではない
  • IS_LABEL_POSSIBLE
  • IS_LABEL_SUFFIX
  • IS_AFTER_OPERATOR

改行

改行文字は以下のように処理される

  • EXPR_BEG, EXPR_CLASS, EXPR_FNAME, EXPR_DOT のいずれかが成立、かつEXPR_LABELEDではない場合
    • 改行を読み飛ばす。
  • EXPR_ARGかつEXPR_LABELEDの場合
    • in_kwargであれば、改行トークン '\n' を出力する。
    • それ以外の場合は改行を読み飛ばす。
  • それ以外の場合、次の行の空白を除いた最初の文字を調べる。
    • 次の行が # で始まっているなら、改行を読み飛ばす。
    • 次の行が &. で始まっているなら、改行を読み飛ばす。
    • 次の行が . で始まっているが .. で始まっていないなら、改行を読み飛ばす。
    • 上のいずれにも該当しなければ、改行トークン '\n' を出力する。
# +の後の改行は無視される (EXPR_BEGのため)
x +
  y

# xの後の改行は有効
x
  + y
# xとyの間には2つの改行があるが、最初の1つだけが有効 (2つ目はEXPR_BEGのため無視される)
x

y
# メソッドチェーンは後続できる
x
  .y

# safe navigationによるメソッドチェーンも後続できる
x
  &.y

# 以下はメソッドチェーンではないため後続できない (2つの式に分割される)
x
  ..y
# 以下も同様
x
  ...y
# メソッドチェーンの間に空行ははさめない
x

  .y # error
  
# しかし、空行ではなくコメントになっていれば有効
x
#
  .y # ok

行コメント # に改行は含まない。行コメントが改行文字に後続されている場合、改行文字は有効。

# xと+yに分かれる
x #foo
+ y

記号

IS_BEG それ以外
* tSTAR '*'
** tDSTAR tPOW
& tAMPER '&'
+ tUPLUS '+'
.. tBDOT2 tDOT2
... tBDOT3 tDOT3
:: tCOLON3 tCOLON2
/ tREGEXP_BEG '/'
( tLPAREN '('
[ tLBRACK '['

ただしIS_SPCARGの場合など細かい条件がある

キーワード

defs/keywordsに一覧がある (これはビルドの途中で lex.c として生成される)。いくつかのキーワードは状態によって異なるトークンになる

  • break
  • else
  • nil
  • ensure
  • end
  • then
  • not
  • false
  • self
  • elsif
  • rescue
    • keyword_rescue ... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合
    • modifier_rescue ... それ以外
  • true
  • `until
    • keyword_until ... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合
    • modifier_until ... それ以外
  • unless
    • keyword_unless ... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合
    • modifier_unless ... それ以外
  • return
  • def
  • and
  • do
  • yield
  • for
  • undef
  • or
  • in
  • when
  • retry
  • if
    • keyword_if ... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合
    • modifier_if
  • case
  • redo
  • next
  • super
  • module
  • begin
  • __LINE__
  • __FILE__
  • __ENCODING__
  • END
  • alias
  • BEGIN
  • defined
  • class
  • while
    • keyword_while ... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合
    • modifier_while ... それ以外

非終端記号

  • program
    • パーサーエントリポイント
    • lexer stateの設定など必要な処理をしている
  • top_compstmt / top_stmts / top_stmt
    • 大文字のBEGINブロック (BEGIN { ... }) を含む全ての文、ただし:
      • top_compstmt ... 0個以上の文 + 末尾セミコロン
      • top_stmts ... 0個以上の文
      • top_stmt ... 1個の文
  • begin_block
    • 大文字のBEGINブロック (BEGIN { ... })
  • bodystmt
    • do-end系ブロックの中身
    • compstmt に加えて、 else 節, rescue 節, ensure 節を書ける
  • compstmt / stmts / stmt
    • 大文字のBEGINブロック (BEGIN { ... }) を除く文、ただし:
      • compstmt ... 0個以上の文 + 末尾セミコロン
      • stmts ... 0個以上の文
      • stmt ... 1個の文
  • stmt_or_begin
    • stmt のエラー処理用
  • command_asgn
    • 代入以下の優先度の文 (ただし多重代入は除く)
  • command_rhs
  • expr
    • 狭義の式 (代入系の処理を含まない)
  • def_name
    • def で定義されるメソッドに使える識別子 (=, [], []=, ?, ! などのsuffixを含む)
  • defn_head
    • def の引数より前 (def + 識別子)
  • defs_head
    • 特異 def の引数より前 (def + 式 + . + 識別子)
  • expr_value
    • expr の亜種。never型の式 (return 式など) が来たらエラーとする
  • expr_value_do
  • command_call
    • メソッド呼び出し以下の式
  • block_command
    • ブロックつきメソッド呼び出しを接頭辞に含むメソッド呼び出し式
  • cmd_brace_block
    • 波括弧型の引数つきブロック ({ |x| x + 1 })
  • fcall
  • command
    • メソッド呼び出しやそれに類する式
  • mlhs
    • 多重代入左辺 (x, y)
  • mlhs_inner
    • 1つ以上の丸括弧で覆われた多重代入左辺 ((x, y), z(x, y))
    • この中では括弧がdestructorとして振る舞う
  • mlhs_basic
    • 単純丸括弧以外の多重代入左辺
  • mlhs_item
  • mlhs_head
  • mlhs_post
  • mlhs_node
  • lhs
  • cname
    • クラス・モジュールの宣言名 (class / module 直後の識別子)
    • tCONSTANT と同等だが、 tIDENTIFIER へのエラーフォールバックが定義されている
  • cpath
    • クラス・モジュールの宣言パス (class / module 直後には :: を含む宣言名が書ける)
  • fname
  • fitem
  • undef_list
  • op
  • reswords
  • arg
    • 式のうち引数位置に書けるもの (and, or, not, =>, in などを含まない)
  • relop
  • rel_expr
    • 式 (arg) のうち連鎖比較演算 (a < b < c など) を切り出したもの
    • 警告用に存在している
  • lex_ctxt
  • arg_value
    • arg の亜種。never型の式 (return 式など) が来たらエラーとする
  • aref_args
    • 配列リテラルの中身
  • arg_rhs
    • arg の亜種。代入の右辺には rescue が書けるようになっている
  • paren_args
    • 括弧つきの関数呼び出し (f(...)) の括弧とその中身
  • opt_paren_args
  • opt_call_args
  • call_args
  • command_args
  • block_arg
    • ブロック引数 (f(..., &block))
  • opt_block_arg
  • args
    • 位置引数
  • mrhs_arg
  • mrhs
  • primary
    • 式のうち左右にデリミタを持つもの
  • primary_value
    • primary_value の亜種。never型の式 (return 式など) が来たらエラーとする
  • k_begin
  • k_if
  • k_unless
  • k_while
  • k_until
  • k_case
  • k_for
  • k_class
  • k_module
  • k_def
  • k_do
  • k_do_block
  • k_rescue
  • k_ensure
  • k_when
  • k_else
  • k_elsif
  • k_end
  • k_return
  • then
    • then またはその代替として使える以下のいずれか: ; / then / ;then
  • do
    • do またはその代替として使える以下のいずれか: ; / do
  • if_tail
    • if-elseチェインの elsif ~ elsif ~ elsif ~ else ~ まで (最後の end は含まない)
  • opt_else
    • else 節 (最後の end は含まない) または無
  • for_var
    • for の左辺
  • f_marg
  • f_marg_list
  • f_margs
  • f_rest_marg
  • f_any_kwrest
  • f_eq
  • block_args_tail
  • opt_block_args_tail
  • excessed_comma
  • block_param
  • opt_block_param
  • block_param_def
  • opt_bv_decl
  • bv_decls
  • bvar
  • lambda
  • f_larglist
  • lambda_body
  • do_block
  • block_call
  • method_call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment