Ruby 无意中找了 ruby 语法的伪 BNF 范式,发出来给大家参考一下。

rasefon · 2013年08月29日 · 最后由 luikore 回复于 2013年08月29日 · 3614 次阅读

Pseudo BNF Syntax of Ruby

Here is the syntax of Ruby in pseudo BNF. For more detail, see parse.y in Ruby distribution.

PROGRAM : COMPSTMT

COMPSTMT : STMT (TERM EXPR)* [TERM]

STMT : CALL do [|' [BLOCK_VAR]|'] COMPSTMT end | undef FNAME | alias FNAME FNAME | STMT if EXPR | STMT while EXPR | STMT unless EXPR | STMT until EXPR | BEGIN'{' COMPSTMT }' |END' {' COMPSTMT}' | LHS =' COMMAND [do [|' [BLOCK_VAR] `|'] COMPSTMT end] | EXPR

EXPR : MLHS =' MRHS | return CALL_ARGS | yield CALL_ARGS | EXPR and EXPR | EXPR or EXPR | not EXPR | COMMAND |!' COMMAND | ARG

CALL : FUNCTION | COMMAND

COMMAND : OPERATION CALL_ARGS | PRIMARY .' OPERATION CALL_ARGS | PRIMARY::' OPERATION CALL_ARGS | super CALL_ARGS

FUNCTION : OPERATION [(' [CALL_ARGS])'] | PRIMARY .' OPERATION(' [CALL_ARGS] )' | PRIMARY::' OPERATION (' [CALL_ARGS])' | PRIMARY .' OPERATION | PRIMARY::' OPERATION | super (' [CALL_ARGS])' | super

ARG : LHS =' ARG | LHS OP_ASGN ARG | ARG..' ARG | ARG ...' ARG | ARG+' ARG | ARG -' ARG | ARG' ARG | ARG /' ARG | ARG%' ARG | ARG `*' ARG | +' ARG |-' ARG | ARG |' ARG | ARG^' ARG | ARG &' ARG | ARG<=>' ARG | ARG >' ARG | ARG>=' ARG | ARG <' ARG | ARG<=' ARG | ARG ==' ARG | ARG===' ARG | ARG !=' ARG | ARG=~' ARG | ARG !~' ARG |!' ARG | ~' ARG | ARG<<' ARG | ARG >>' ARG | ARG&&' ARG | ARG `||' ARG | defined? ARG | PRIMARY

PRIMARY : (' COMPSTMT)' | LITERAL | VARIABLE | PRIMARY ::' IDENTIFIER |::' IDENTIFIER | PRIMARY [' [ARGS]]' | [' [ARGS [,']] ]' |{' [(ARGS|ASSOCS) [,']]}' | return [(' [CALL_ARGS])'] | yield [(' [CALL_ARGS])'] | defined? (' ARG)' | FUNCTION | FUNCTION {' [|' [BLOCK_VAR] |'] COMPSTMT}' | if EXPR THEN COMPSTMT (elsif EXPR THEN COMPSTMT)* [else COMPSTMT] end | unless EXPR THEN COMPSTMT [else COMPSTMT] end | while EXPR DO COMPSTMT end | until EXPR DO COMPSTMT end | case COMPSTMT (when WHEN_ARGS THEN COMPSTMT)+ [else COMPSTMT] end | for BLOCK_VAR in EXPR DO COMPSTMT end | begin COMPSTMT [rescue [ARGS] DO COMPSTMT]+ [else COMPSTMT] [ensure COMPSTMT] end | class IDENTIFIER [<' IDENTIFIER] COMPSTMT end | module IDENTIFIER COMPSTMT end | def FNAME ARGDECL COMPSTMT end | def SINGLETON (.'|`::') FNAME ARGDECL COMPSTMT end

WHEN_ARGS : ARGS [,'' ARG] | `' ARG

THEN : TERM | then | TERM then

DO : TERM | do | TERM do

BLOCK_VAR : LHS | MLHS

MLHS : MLHS_ITEM ,' [MLHS_ITEM (,' MLHS_ITEM)] [`' [LHS]] | `*' LHS

MLHS_ITEM : LHS | '(' MLHS ')'

LHS : VARIABLE | PRIMARY [' [ARGS]]' | PRIMARY `.' IDENTIFIER

MRHS : ARGS [,'' ARG] | `' ARG

CALL_ARGS : ARGS | ARGS [,' ASSOCS] [,' *' ARG] [,' &' ARG] | ASSOCS [,' *' ARG] [,' &' ARG] |*' ARG [,'&' ARG] | `&' ARG | COMMAND

ARGS : ARG (`,' ARG)*

ARGDECL : (' ARGLIST)' | ARGLIST TERM

ARGLIST : IDENTIFIER(,'IDENTIFIER)*[,'*'[IDENTIFIER]][,'&'IDENTIFIER] |*'IDENTIFIER[,'&'IDENTIFIER] | [`&'IDENTIFIER]

SINGLETON : VARIABLE | (' EXPR)'

ASSOCS : ASSOC (`,' ASSOC)*

ASSOC : ARG `=>' ARG

VARIABLE : VARNAME | nil | self

LITERAL : numeric | SYMBOL | STRING | STRING2 | HERE_DOC | REGEXP

TERM : ;' |\n'

The followings are recognized by lexical analizer.

OP_ASGN : +=' |-=' | *=' |/=' | %=' |**=' | &=' ||=' | ^=' |<<=' | >>=' |&&=' | `||='

SYMBOL : :'FNAME |:'VARNAME

FNAME : IDENTIFIER | ..' ||' | ^' |&' | <=>' |==' | ===' |=~' | >' |>=' | <' |<=' | +' |-' | *' |/' | %' |**' | <<' |>>' | ~' |+@' | -@' |[]' | `[]='

OPERATION : IDENTIFIER | IDENTIFIER'!' | IDENTIFIER'?'

VARNAME : GLOBAL | `@'IDENTIFIER | IDENTIFIER

GLOBAL : $'IDENTIFIER |$'any_char | `$''-'any_char

STRING : "' any_char*"' | '' any_char*'' | ' any_char*'

STRING2 : %'(Q'|q'|x')char any_char* char

HERE_DOC : `<<'(IDENTIFIER|STRING) any_char* IDENTIFIER

REGEXP : /' any_char*/'[i'|o'|p'] |%'`r' char any_char* char

IDENTIFIER is the sqeunce of characters in the pattern of /[a-zA-Z_][a-zA-Z0-9_]*/.

其实我一直想做一个 ruby 版的解析器生成器,这样以后用 ruby 做外部 dsl 就会很方便。不知道有没有现成的可以用?

#1 楼 @rasefon ruby 自带 rex 和 racc, 还有 treetop, parslet 等

其实我一直想做一个 ruby 版的解析器生成器,这样以后用 ruby 做外部 dsl 就会很方便。不知道有没有现成的可以用? #2 楼 @luikore Thx! 刚粗略看了下,最像 lex/yacc 是 rex/racc. 另外这些 gems 有没有扫描时构建 AST 的功能?

#3 楼 @rasefon treetop 有,racc 应该也可以

需要 登录 后方可回复, 如果你还没有账号请 注册新账号