module X12 grammar X12syntax # $Id: x12syntax.treetop 36 2008-11-13 18:36:36Z ikk $ # This is a syntax definition for the X12-syntax files. rule x12syntax (table / segment / composite / loop )+ { def get elements.inject({}){|s, i| if i.nonterminal? r = i.get s[r.class] ||= {} s[r.class][r.name]=r end s } end } end # LOOP rule loop space? 'loop' space loop_name space repeat space? '{' space? loop_components space? '}' space? { def get Loop.new(loop_name.text_value, loop_components.get, repeat.get) end } end rule loop_components loop_component+ { def get elements.map{|i| i.get} end } end rule loop_component loop_segment / loop end rule loop_segment space? 'segment' space identifier space repeat space? '{' space? fields space? '}' { def get Segment.new(identifier.text_value, fields.get, repeat.get) end } / space? 'segment' space identifier space repeat space? { def get Segment.new(identifier.text_value, [], repeat.get) end } end # COMPOSITE rule composite space? 'composite' space composite_name space? '{' space? fields space? '}' space? { def get Composite.new(composite_name.text_value, fields.get) end } end # SEGMENT rule segment space? 'segment' space identifier space? '{' space? fields space? '}' space? { def get Segment.new(identifier.text_value, fields.get) end } end rule fields field+ { def get elements.map{|i| i.get} end } end rule field space? field_name space field_type space field_required space field_min_length '-' field_max_length field_validation space? { def get #elements.each{|i| puts "*** [#{i.text_value}] #{i.inspect}"} Field.new(*[field_name.text_value, field_type.text_value, field_required.text_value, field_min_length.text_value, field_max_length.text_value, field_validation.get, ]) end } end rule field_name identifier end rule field_type 'I' / 'S' / composite_name / constant end rule composite_name 'C' numeric_char+ end rule field_required 'R' / 'O' end rule field_min_length numeric_char+ end rule field_max_length numeric_char+ end rule field_validation [ ]+ identifier { def get identifier.text_value end } / space { def get nil end } end # TABLE rule table space? 'table' space identifier space? '{' space? name_value_lines space? '}' space? { def get Table.new(identifier.text_value, name_value_lines.get) end } end rule name_value_lines name_value_line+ { def get elements.inject({}){|s, i| s[i.get_name] = i.get_value; s} end } end rule name_value_line space? name space value { def get_name name.text_value end def get_value value.text_value end } end rule name alphanumeric_char+ end rule value [^\r\n]+ end rule repeat min_required ':' max_allowed { def get Range.new(min_required.text_value.to_i, max_allowed.text_value.to_i) end } end rule min_required numeric_char+ end rule max_allowed numeric_char+ end rule loop_name alphanumeric_char+ end # UTILITY rule constant '"' [^"]* '"' end rule identifier alpha_char alphanumeric_char* end rule non_space_char !space . end rule alpha_char [A-Za-z_] end rule alphanumeric_char alpha_char / numeric_char end rule numeric_char [0-9] end rule space (white / comment_c_style / comment_to_eol)+ end rule comment_c_style '/*' (!'*/' . )* '*/' end rule comment_to_eol '#' (!"\n" .)+ end rule white [ \t\n\r] end rule eol "\n" / "\r" end end end