net/http の deflate 対応パッチをもらった。 おおむねそのまま使えそうなので、 近いうちに修正を加えて 1.9 に取り込む予定。
(15:45)
レポートを書いてたはずなのにいつのまにか Racc をいじっている不思議。 今日は Parsec ちっくに many とか option を使えるようにしてみた。
どことなく C 風の文法 (アクションはまだ適当)
grammar = Racc::Grammar.define { g = self precedence_table { higher right '[' right '*@', '&@', :CAST right '+@', '-@', '!' left '*', '/' left '+', '-' left ">>", "<<" left '&' left '|' left "==", "!=", '>', '>=', '<', '<=' left "&&" left "||" lower } g.program = many(:decl) g.decl = seq(:defvar) {|field| declare field }\ | seq(:defun) {|func| declare func }\ | seq(:defstruct) {|struct| define_type struct }\ | seq(:defunion) {|union| define_type union } g.defvar = seq(:storage, :type, :IDENT, option(:initval), ';') { |storage, type, name, val, _| Field.new(storage, type, name, val) } g.initval = seq('=', :expr) {|_, expr| expr } g.defun = seq( :storage, :type, :IDENT, '(', :params, ')', '{', :scope, '}') { |storage, type, name, _, params, _, _, body, _| Function.new(storage, type, name, params, body) } g.params = separated_by(',', :slot) g.defstruct = seq(:STRUCT, :IDENT, '{', many(:memb), '}', ';') { |_, tag, _, membs, _, _| StructType.new(tag, membs) } g.defunion = seq(:UNION, :IDENT, '{', many(:memb), '}', ';') { |_, tag, _, membs, _, _| UnionType.new(tag, membs) } g.memb = seq(:slot, ';') {|slot, _| slot } g.struct_decl = seq(:STRUCT, :IDENT, ';') {|_, tag, _| StructType.new(tag, nil) } g.union_decl = seq(:UNION, :IDENT, ';') {|_, tag, _| UnionType.new(tag, nil) } g.scope = seq(_ { push_scope }, many(:vardecl), :stmts) {|_, decls, stmts| pop_scope ScopeNode.new(decls, stmts) } g.storage = null() | seq(:STATIC) | seq(:EXTERN) g.slot = seq(:type, :IDENT) {|type, name| Slot.new(type, new) } g.type = seq(:VOID) {|_| @types.void }\ | seq(:CHAR) {|_| @types.char }\ | seq(:SHORT) {|_| @types.short }\ | seq(:INT) {|_| @types.int }\ | seq(:LONG) {|_| @types.long }\ | seq(:LONG, :LONG) {|_,_| @types.longlong }\ | seq(:type, '[',']') {|t,_,_| @types.array_of(t) }\ | seq(:type, '*') {|t,_,_| @types.pointer_to(t) }\ | seq(:STRUCT, :IDENT) {|_, tag| @types.struct(tag) }\ | seq(:UNION, :IDENT) {|_, tag| @types.union(tag) } g.stmts = many(:stmt) {|stmts| stmts.compact } g.stmt = seq(';') { nil }\ | seq(:expr, ';') {|node, _| node }\ | seq(:IF, '(', :expr, ')', '{', :scope, '}', option(:else)){ |_, _, cond, _, _, then_body, _, else_node| n = IfNode.new(cond, then_body, else_node) n.location = cond.location n }\ | seq(:WHILE, '(', :expr, ')', '{', :scope, '}') { |_, _, cond, _, _, body, _| n = WhileNode.new(cond, body) n.location = cond.location n }\ | seq(:BREAK, ';') {|*| BreakNode.new(nil) }\ | seq(:CONTINUE, ';') {|*| ContinueNode.new(nil) }\ | seq(:RETURN, ';') {|*| ReturnNode.new(nil) }\ | seq(:RETURN, :expr, ';') {|_, expr, _| ReturnNode.new(expr) } g.else = seq(:ELSE, '{', :stmts, '}') {|_, _, body, _| body } g.expr = seq(:primary)\ | seq(:expr, '+', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '-', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '*', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '/', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '&', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '|', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '>>', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '<<', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '>', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '>=', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '<', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '<=', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '==', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '!=', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '&&', :expr) {|*a| newnode(BinaryOpNode, *a) }\ | seq(:expr, '||', :expr) {|*a| newnode(BinaryOpNode, *a) } g.primary = seq(:DIGIT) {|num| newnode(LiteralNode, @types.int, num) }\ | seq(:CHARACTER) {|ch| newnode(LiteralNode, @types.char, ch) }\ | seq(:STRING) {|str| newnode(LiteralNode, @target.types(@types.char), string_constant(str)) }\ | seq(:IDENT) {|sym| newnode(VarrefNode, @namespace, sym) }\ | seq('+', :primary).prec('+@') {|op, expr| newnode(UnaryOpNode, op, expr) }\ | seq('-', :primary).prec('-@') {|op, expr| newnode(UnaryOpNode, op, expr) }\ | seq('!', :primary) {|op, expr| newnode(UnaryOpNode, op, expr) }\ | seq('*', :primary).prec('*@') {|op, expr| newnode(UnaryOpNode, op, expr) }\ | seq('&', :primary).prec('&@') {|op, expr| newnode(UnaryOpNode, op, expr) }\ | seq(:primary, '[', :expr, ']') {|expr, _, idx, _| newnode(BinaryOpNode, '[]', expr, idx) }\ | seq(:IDENT, '(', separated_by(',', :expr), ')') { |name, _, args, _| newnode(FuncallNode, name, args) }\ | seq(:cast, :primary).prec(:CAST) {|type, node| CastNode.new(type, node) }\ | seq('(', :expr, ')') {|_, node, _| node } }
生成される文法
rule 1 program: rule 2 program: program decl rule 3 decl: defvar rule 4 decl: defun rule 5 decl: defstruct rule 6 decl: defunion rule 7 decl: struct_decl rule 8 decl: union_decl rule 9 defvar: storage type IDENT option@initval ";" rule 10 option@initval: rule 11 option@initval: initval rule 12 initval: "=" expr rule 13 defun: storage type IDENT "(" params ")" "{" scope "}" rule 14 separated_by1@slot: slot rule 15 separated_by1@slot: separated_by1@slot "," slot rule 16 params: rule 17 params: separated_by1@slot rule 18 defstruct: STRUCT IDENT "{" many@memb "}" ";" rule 19 many@memb: rule 20 many@memb: many@memb memb rule 21 defunion: UNION IDENT "{" many@memb "}" ";" rule 22 memb: slot ";" rule 23 struct_decl: STRUCT IDENT ";" rule 24 union_decl: UNION IDENT ";" rule 25 scope: @1 many@vardecl stmts rule 26 @1: rule 27 many@vardecl: rule 28 many@vardecl: many@vardecl vardecl rule 29 storage: rule 30 storage: STATIC rule 31 storage: EXTERN rule 32 slot: type IDENT rule 33 type: VOID rule 34 type: CHAR rule 35 type: SHORT rule 36 type: INT rule 37 type: LONG rule 38 type: LONG LONG rule 39 type: type "[" "]" rule 40 type: type "*" rule 41 type: STRUCT IDENT rule 42 type: UNION IDENT rule 43 stmts: many@stmt-1-base rule 44 many@stmt-1-base: rule 45 many@stmt-1-base: many@stmt-1-base stmt rule 46 stmt: ";" rule 47 stmt: expr ";" rule 48 stmt: IF "(" expr ")" "{" scope "}" option@else rule 49 stmt: WHILE "(" expr ")" "{" scope "}" rule 50 stmt: BREAK ";" rule 51 stmt: CONTINUE ";" rule 52 stmt: RETURN ";" rule 53 stmt: RETURN expr ";" rule 54 option@else: rule 55 option@else: else rule 56 else: ELSE "{" stmts "}" rule 57 expr: primary rule 58 expr: expr "+" expr rule 59 expr: expr "-" expr rule 60 expr: expr "*" expr rule 61 expr: expr "/" expr rule 62 expr: expr "&" expr rule 63 expr: expr "|" expr rule 64 expr: expr ">>" expr rule 65 expr: expr "<<" expr rule 66 expr: expr ">" expr rule 67 expr: expr ">=" expr rule 68 expr: expr "<" expr rule 69 expr: expr "<=" expr rule 70 expr: expr "==" expr rule 71 expr: expr "!=" expr rule 72 expr: expr "&&" expr rule 73 expr: expr "||" expr rule 74 primary: DIGIT rule 75 primary: CHARACTER rule 76 primary: STRING rule 77 primary: IDENT rule 78 primary: "+" primary rule 79 primary: "-" primary rule 80 primary: "!" primary rule 81 primary: "*" primary rule 82 primary: "&" primary rule 83 primary: primary "[" expr "]" rule 84 primary: IDENT "(" option@separated_by1@expr ")" rule 85 primary: cast primary rule 86 primary: "(" expr ")" rule 87 separated_by1@expr: expr rule 88 separated_by1@expr: separated_by1@expr "," expr rule 89 option@separated_by1@expr: rule 90 option@separated_by1@expr: separated_by1@expr
(03:10)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.