基本の字句解析状態はlex_state_bits, lex_state_eにある。
EXPR_BEG- 式の開始位置
EXPR_END- リテラル・識別子の終了位置
EXPR_ENDARGEXPR_ENDFNEXPR_ARGEXPR_CMDARGEXPR_MIDEXPR_FNAMEEXPR_DOTEXPR_CLASSEXPR_LABELEXPR_LABELEDEXPR_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'を出力する。 - それ以外の場合は改行を読み飛ばす。
- in_kwargであれば、改行トークン
- それ以外の場合、次の行の空白を除いた最初の文字を調べる。
- 次の行が
#で始まっているなら、改行を読み飛ばす。 - 次の行が
&.で始まっているなら、改行を読み飛ばす。 - 次の行が
.で始まっているが..で始まっていないなら、改行を読み飛ばす。 - 上のいずれにも該当しなければ、改行トークン
'\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 として生成される)。いくつかのキーワードは状態によって異なるトークンになる。
breakelsenilensureendthennotfalseselfelsifrescuekeyword_rescue... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合modifier_rescue... それ以外
true- `until
keyword_until... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合modifier_until... それ以外
unlesskeyword_unless... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合modifier_unless... それ以外
returndefanddoyieldforundeforinwhenretryifkeyword_if... EXPR_FNAME, EXPR_BEG, または EXPR_LABELED の場合modifier_if
caseredonextsupermodulebegin__LINE____FILE____ENCODING__ENDaliasBEGINdefinedclasswhilekeyword_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ブロック (
begin_block- 大文字のBEGINブロック (
BEGIN { ... })
- 大文字のBEGINブロック (
bodystmt- do-end系ブロックの中身
compstmtに加えて、else節,rescue節,ensure節を書ける
compstmt/stmts/stmt- 大文字のBEGINブロック (
BEGIN { ... }) を除く文、ただし:compstmt... 0個以上の文 + 末尾セミコロンstmts... 0個以上の文stmt... 1個の文
- 大文字のBEGINブロック (
stmt_or_beginstmtのエラー処理用
command_asgn- 代入以下の優先度の文 (ただし多重代入は除く)
command_rhsexpr- 狭義の式 (代入系の処理を含まない)
def_namedefで定義されるメソッドに使える識別子 (=,[],[]=,?,!などのsuffixを含む)
defn_headdefの引数より前 (def+ 識別子)
defs_head- 特異
defの引数より前 (def+ 式 +.+ 識別子)
- 特異
expr_valueexprの亜種。never型の式 (return式など) が来たらエラーとする
expr_value_docommand_call- メソッド呼び出し以下の式
block_command- ブロックつきメソッド呼び出しを接頭辞に含むメソッド呼び出し式
cmd_brace_block- 波括弧型の引数つきブロック (
{ |x| x + 1 })
- 波括弧型の引数つきブロック (
fcallcommand- メソッド呼び出しやそれに類する式
mlhs- 多重代入左辺 (
x, y)
- 多重代入左辺 (
mlhs_inner- 1つ以上の丸括弧で覆われた多重代入左辺 (
(x, y), zの(x, y)) - この中では括弧がdestructorとして振る舞う
- 1つ以上の丸括弧で覆われた多重代入左辺 (
mlhs_basic- 単純丸括弧以外の多重代入左辺
mlhs_itemmlhs_headmlhs_postmlhs_nodelhscname- クラス・モジュールの宣言名 (
class/module直後の識別子) tCONSTANTと同等だが、tIDENTIFIERへのエラーフォールバックが定義されている
- クラス・モジュールの宣言名 (
cpath- クラス・モジュールの宣言パス (
class/module直後には::を含む宣言名が書ける)
- クラス・モジュールの宣言パス (
fnamefitemundef_listopreswordsarg- 式のうち引数位置に書けるもの (
and,or,not,=>,inなどを含まない)
- 式のうち引数位置に書けるもの (
reloprel_expr- 式 (
arg) のうち連鎖比較演算 (a < b < cなど) を切り出したもの - 警告用に存在している
- 式 (
lex_ctxtarg_valueargの亜種。never型の式 (return式など) が来たらエラーとする
aref_args- 配列リテラルの中身
arg_rhsargの亜種。代入の右辺にはrescueが書けるようになっている
paren_args- 括弧つきの関数呼び出し (
f(...)) の括弧とその中身
- 括弧つきの関数呼び出し (
opt_paren_argsopt_call_argscall_argscommand_argsblock_arg- ブロック引数 (
f(..., &block))
- ブロック引数 (
opt_block_argargs- 位置引数
mrhs_argmrhsprimary- 式のうち左右にデリミタを持つもの
primary_valueprimary_valueの亜種。never型の式 (return式など) が来たらエラーとする
k_begink_ifk_unlessk_whilek_untilk_casek_fork_classk_modulek_defk_dok_do_blockk_rescuek_ensurek_whenk_elsek_elsifk_endk_returnthenthenまたはその代替として使える以下のいずれか:;/then/;then
dodoまたはその代替として使える以下のいずれか:;/do
if_tail- if-elseチェインの
elsif ~ elsif ~ elsif ~ else ~まで (最後のendは含まない)
- if-elseチェインの
opt_elseelse節 (最後のendは含まない) または無
for_varforの左辺
f_margf_marg_listf_margsf_rest_margf_any_kwrestf_eqblock_args_tailopt_block_args_tailexcessed_commablock_paramopt_block_paramblock_param_defopt_bv_declbv_declsbvarlambdaf_larglistlambda_bodydo_blockblock_callmethod_call