Permalink
Browse files

Using cannonical conformance tests now

  • Loading branch information...
fd committed May 29, 2011
1 parent 0eef7ef commit 6f057502257acaee21f485b682ca3e200dc2bcec
Showing with 346 additions and 569 deletions.
  1. +3 −0 .gitmodules
  2. +179 −44 lib/json_select/selector_parser.rb
  3. +9 −2 lib/json_select/selector_parser.tt
  4. +93 −44 spec/conformance_spec.rb
  5. +0 −14 spec/fixtures/README.md
  6. +0 −31 spec/fixtures/alltests.txt
  7. +0 −31 spec/fixtures/basic.json
  8. +0 −31 spec/fixtures/basic.xml
  9. +0 −14 spec/fixtures/basic_children.ast
  10. +0 −1 spec/fixtures/basic_children.output
  11. +0 −13 spec/fixtures/basic_combination.ast
  12. +0 −1 spec/fixtures/basic_combination.output
  13. +0 −11 spec/fixtures/basic_first-child.ast
  14. +0 −2 spec/fixtures/basic_first-child.output
  15. +0 −22 spec/fixtures/basic_grouping.ast
  16. +0 −4 spec/fixtures/basic_grouping.output
  17. +0 −7 spec/fixtures/basic_id.ast
  18. +0 −1 spec/fixtures/basic_id.output
  19. +0 −7 spec/fixtures/basic_id_multiple.ast
  20. +0 −3 spec/fixtures/basic_id_multiple.output
  21. +0 −7 spec/fixtures/basic_id_quotes.ast
  22. +0 −2 spec/fixtures/basic_id_quotes.output
  23. +0 −10 spec/fixtures/basic_id_with_type.ast
  24. +0 −1 spec/fixtures/basic_id_with_type.output
  25. +0 −11 spec/fixtures/basic_last-child.ast
  26. +0 −2 spec/fixtures/basic_last-child.output
  27. +0 −11 spec/fixtures/basic_nth-child-2.ast
  28. +0 −4 spec/fixtures/basic_nth-child-2.output
  29. +0 −11 spec/fixtures/basic_nth-child.ast
  30. +0 −3 spec/fixtures/basic_nth-child.output
  31. +0 −11 spec/fixtures/basic_nth-last-child.ast
  32. +0 −2 spec/fixtures/basic_nth-last-child.output
  33. +0 −6 spec/fixtures/basic_root_pseudo.ast
  34. +0 −31 spec/fixtures/basic_root_pseudo.output
  35. +0 −7 spec/fixtures/basic_type.ast
  36. +0 −14 spec/fixtures/basic_type.output
  37. +0 −7 spec/fixtures/basic_type2.ast
  38. +0 −1 spec/fixtures/basic_type2.output
  39. +0 −7 spec/fixtures/basic_type3.ast
  40. +0 −47 spec/fixtures/basic_type3.output
  41. +0 −5 spec/fixtures/basic_universal.ast
  42. +0 −86 spec/fixtures/basic_universal.output
  43. +1 −0 spec/fixtures/conformance
  44. 0 spec/fixtures/{basic_children.selector → parser/level_1/basic_children.output}
  45. 0 spec/fixtures/{basic_children.selector.out → parser/level_1/basic_children.selector}
  46. 0 spec/fixtures/{basic_combination.selector → parser/level_1/basic_combination.output}
  47. 0 spec/fixtures/{basic_combination.selector.out → parser/level_1/basic_combination.selector}
  48. 0 spec/fixtures/{basic_first-child.selector.out → parser/level_1/basic_first-child.output}
  49. 0 spec/fixtures/{ → parser/level_1}/basic_first-child.selector
  50. 0 spec/fixtures/{basic_grouping.selector.out → parser/level_1/basic_grouping.output}
  51. 0 spec/fixtures/{ → parser/level_1}/basic_grouping.selector
  52. 0 spec/fixtures/{basic_id.selector.out → parser/level_1/basic_id.output}
  53. 0 spec/fixtures/{ → parser/level_1}/basic_id.selector
  54. 0 spec/fixtures/{basic_id_multiple.selector.out → parser/level_1/basic_id_multiple.output}
  55. 0 spec/fixtures/{ → parser/level_1}/basic_id_multiple.selector
  56. 0 spec/fixtures/{basic_id_quotes.selector.out → parser/level_1/basic_id_quotes.output}
  57. 0 spec/fixtures/{ → parser/level_1}/basic_id_quotes.selector
  58. 0 spec/fixtures/{basic_id_with_type.selector.out → parser/level_1/basic_id_with_type.output}
  59. 0 spec/fixtures/{ → parser/level_1}/basic_id_with_type.selector
  60. 0 spec/fixtures/{basic_last-child.selector.out → parser/level_1/basic_last-child.output}
  61. 0 spec/fixtures/{ → parser/level_1}/basic_last-child.selector
  62. 0 spec/fixtures/{basic_nth-child-2.selector.out → parser/level_1/basic_nth-child-2.output}
  63. 0 spec/fixtures/{ → parser/level_1}/basic_nth-child-2.selector
  64. 0 spec/fixtures/{basic_nth-child.selector.out → parser/level_1/basic_nth-child.output}
  65. 0 spec/fixtures/{ → parser/level_1}/basic_nth-child.selector
  66. 0 spec/fixtures/{basic_nth-last-child.selector.out → parser/level_1/basic_nth-last-child.output}
  67. 0 spec/fixtures/{ → parser/level_1}/basic_nth-last-child.selector
  68. 0 spec/fixtures/{basic_root_pseudo.selector.out → parser/level_1/basic_root_pseudo.output}
  69. 0 spec/fixtures/{ → parser/level_1}/basic_root_pseudo.selector
  70. 0 spec/fixtures/{basic_type.selector → parser/level_1/basic_type.output}
  71. 0 spec/fixtures/{basic_type.selector.out → parser/level_1/basic_type.selector}
  72. 0 spec/fixtures/{basic_type2.selector → parser/level_1/basic_type2.output}
  73. 0 spec/fixtures/{basic_type2.selector.out → parser/level_1/basic_type2.selector}
  74. 0 spec/fixtures/{basic_type3.selector.out → parser/level_1/basic_type3.output}
  75. 0 spec/fixtures/{ → parser/level_1}/basic_type3.selector
  76. 0 spec/fixtures/{basic_universal.selector.out → parser/level_1/basic_universal.output}
  77. 0 spec/fixtures/{ → parser/level_1}/basic_universal.selector
  78. +1 −0 spec/fixtures/parser/level_3/basic_has-sans-paren.output
  79. +2 −0 spec/fixtures/parser/level_3/basic_has-sans-paren.selector
  80. +1 −0 spec/fixtures/parser/level_3/basic_has-whitespace.output
  81. +3 −0 spec/fixtures/parser/level_3/basic_has-whitespace.selector
  82. +1 −0 spec/fixtures/parser/level_3/basic_has.output
  83. +1 −0 spec/fixtures/parser/level_3/basic_has.selector
  84. +52 −0 spec/parser_spec.rb
View
@@ -0,0 +1,3 @@
+[submodule "spec/fixtures/conformance"]
+ path = spec/fixtures/conformance
+ url = git://github.com/lloyd/JSONSelectTests.git
@@ -619,7 +619,18 @@ def a
end
def e
- elements[4]
+ elements[5]
+ end
+
+ end
+
+ module Pseudo2
+ def a
+ elements[1]
+ end
+
+ def s
+ elements[5]
end
end
@@ -669,53 +680,66 @@ def _nt_pseudo
end
s4 << r5
if r5
- r6 = _nt_pseudo_function_name
+ r6 = _nt_positional_pseudo_function_name
s4 << r6
if r6
- if has_terminal?('(', false, index)
- r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
- @index += 1
- else
- terminal_parse_failure('(')
- r7 = nil
+ s7, i7 = [], index
+ loop do
+ r8 = _nt_ws
+ if r8
+ s7 << r8
+ else
+ break
+ end
end
+ r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
s4 << r7
if r7
- s8, i8 = [], index
- loop do
- r9 = _nt_ws
- if r9
- s8 << r9
- else
- break
- end
+ if has_terminal?('(', false, index)
+ r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
+ @index += 1
+ else
+ terminal_parse_failure('(')
+ r9 = nil
end
- r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
- s4 << r8
- if r8
- r10 = _nt_expression
+ s4 << r9
+ if r9
+ s10, i10 = [], index
+ loop do
+ r11 = _nt_ws
+ if r11
+ s10 << r11
+ else
+ break
+ end
+ end
+ r10 = instantiate_node(SyntaxNode,input, i10...index, s10)
s4 << r10
if r10
- s11, i11 = [], index
- loop do
- r12 = _nt_ws
- if r12
- s11 << r12
- else
- break
- end
- end
- r11 = instantiate_node(SyntaxNode,input, i11...index, s11)
- s4 << r11
- if r11
- if has_terminal?(')', false, index)
- r13 = instantiate_node(SyntaxNode,input, index...(index + 1))
- @index += 1
- else
- terminal_parse_failure(')')
- r13 = nil
+ r12 = _nt_expression
+ s4 << r12
+ if r12
+ s13, i13 = [], index
+ loop do
+ r14 = _nt_ws
+ if r14
+ s13 << r14
+ else
+ break
+ end
end
+ r13 = instantiate_node(SyntaxNode,input, i13...index, s13)
s4 << r13
+ if r13
+ if has_terminal?(')', false, index)
+ r15 = instantiate_node(SyntaxNode,input, index...(index + 1))
+ @index += 1
+ else
+ terminal_parse_failure(')')
+ r15 = nil
+ end
+ s4 << r15
+ end
end
end
end
@@ -732,8 +756,95 @@ def _nt_pseudo
if r4
r0 = r4
else
- @index = i0
- r0 = nil
+ i16, s16 = index, []
+ if has_terminal?(':', false, index)
+ r17 = instantiate_node(SyntaxNode,input, index...(index + 1))
+ @index += 1
+ else
+ terminal_parse_failure(':')
+ r17 = nil
+ end
+ s16 << r17
+ if r17
+ r18 = _nt_subselector_pseudo_function_name
+ s16 << r18
+ if r18
+ s19, i19 = [], index
+ loop do
+ r20 = _nt_ws
+ if r20
+ s19 << r20
+ else
+ break
+ end
+ end
+ r19 = instantiate_node(SyntaxNode,input, i19...index, s19)
+ s16 << r19
+ if r19
+ if has_terminal?('(', false, index)
+ r21 = instantiate_node(SyntaxNode,input, index...(index + 1))
+ @index += 1
+ else
+ terminal_parse_failure('(')
+ r21 = nil
+ end
+ s16 << r21
+ if r21
+ s22, i22 = [], index
+ loop do
+ r23 = _nt_ws
+ if r23
+ s22 << r23
+ else
+ break
+ end
+ end
+ r22 = instantiate_node(SyntaxNode,input, i22...index, s22)
+ s16 << r22
+ if r22
+ r24 = _nt_selectors_group
+ s16 << r24
+ if r24
+ s25, i25 = [], index
+ loop do
+ r26 = _nt_ws
+ if r26
+ s25 << r26
+ else
+ break
+ end
+ end
+ r25 = instantiate_node(SyntaxNode,input, i25...index, s25)
+ s16 << r25
+ if r25
+ if has_terminal?(')', false, index)
+ r27 = instantiate_node(SyntaxNode,input, index...(index + 1))
+ @index += 1
+ else
+ terminal_parse_failure(')')
+ r27 = nil
+ end
+ s16 << r27
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if s16.last
+ r16 = instantiate_node(JSONSelect::Ast::PseudoSelector,input, i16...index, s16)
+ r16.extend(Pseudo2)
+ else
+ @index = i16
+ r16 = nil
+ end
+ if r16
+ r0 = r16
+ else
+ @index = i0
+ r0 = nil
+ end
end
end
@@ -817,10 +928,10 @@ def _nt_pseudo_class_name
r0
end
- def _nt_pseudo_function_name
+ def _nt_positional_pseudo_function_name
start_index = index
- if node_cache[:pseudo_function_name].has_key?(index)
- cached = node_cache[:pseudo_function_name][index]
+ if node_cache[:positional_pseudo_function_name].has_key?(index)
+ cached = node_cache[:positional_pseudo_function_name][index]
if cached
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
@index = cached.interval.end
@@ -854,7 +965,31 @@ def _nt_pseudo_function_name
end
end
- node_cache[:pseudo_function_name][start_index] = r0
+ node_cache[:positional_pseudo_function_name][start_index] = r0
+
+ r0
+ end
+
+ def _nt_subselector_pseudo_function_name
+ start_index = index
+ if node_cache[:subselector_pseudo_function_name].has_key?(index)
+ cached = node_cache[:subselector_pseudo_function_name][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ if has_terminal?('has', false, index)
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 3))
+ @index += 3
+ else
+ terminal_parse_failure('has')
+ r0 = nil
+ end
+
+ node_cache[:subselector_pseudo_function_name][start_index] = r0
r0
end
@@ -63,7 +63,8 @@ grammar JSONSelectSelector
# ;
rule pseudo
( ':' a:pseudo_class_name <JSONSelect::Ast::PseudoSelector> ) /
- ( ':' a:pseudo_function_name '(' ws* e:expression ws* ')' <JSONSelect::Ast::PseudoSelector> )
+ ( ':' a:positional_pseudo_function_name ws* '(' ws* e:expression ws* ')' <JSONSelect::Ast::PseudoSelector> ) /
+ ( ':' a:subselector_pseudo_function_name ws* '(' ws* s:selectors_group ws* ')' <JSONSelect::Ast::PseudoSelector> )
end
# pseudo_class_name
@@ -74,10 +75,16 @@ grammar JSONSelectSelector
# pseudo_function_name
# : `nth-child` | `nth-last-child`
- rule pseudo_function_name
+ rule positional_pseudo_function_name
'nth-child' / 'nth-last-child'
end
+ # pseudo_function_name
+ # : `nth-child` | `nth-last-child`
+ rule subselector_pseudo_function_name
+ 'has'
+ end
+
# expression
# /* expression is and of the form "an+b" */
# : TODO
Oops, something went wrong.

6 comments on commit 6f05750

@lloyd

This comment has been minimized.

Show comment Hide comment
@lloyd

lloyd May 29, 2011

How are you finding the broken out conformance tests? How do you feel about the negative tests, those where the .output file contains Error:. Is it useful that actual error messages emitted by the javascript implementation occur in test files, or annoying?

How are you finding the broken out conformance tests? How do you feel about the negative tests, those where the .output file contains Error:. Is it useful that actual error messages emitted by the javascript implementation occur in test files, or annoying?

@fd

This comment has been minimized.

Show comment Hide comment
@fd

fd May 29, 2011

Owner

I think they are great. The negative tests are less useful but it's easy enough to map the JS error messages to Ruby error messages. Maybe it's a good idea to define standardized error numbers. Like this the tests are not coupled to the JS implementation.

Owner

fd replied May 29, 2011

I think they are great. The negative tests are less useful but it's easy enough to map the JS error messages to Ruby error messages. Maybe it's a good idea to define standardized error numbers. Like this the tests are not coupled to the JS implementation.

@lloyd

This comment has been minimized.

Show comment Hide comment
@lloyd

lloyd May 30, 2011

I don't know if I care to regulate how errors are reported in other implementations... But you are the only other implementor at this point, so basically I'm all ears.

One thing I was thinking is to change the extension of negative tests to .error (from .output). This way crazy over zealous implementations could copy the ref impl's js errors verbatim, while others could just check for the existence of the error file to determine whether or not an error was expected.

I don't know if I care to regulate how errors are reported in other implementations... But you are the only other implementor at this point, so basically I'm all ears.

One thing I was thinking is to change the extension of negative tests to .error (from .output). This way crazy over zealous implementations could copy the ref impl's js errors verbatim, while others could just check for the existence of the error file to determine whether or not an error was expected.

@fd

This comment has been minimized.

Show comment Hide comment
@fd

fd May 30, 2011

Owner

I think changing the extension of the negative tests to .error is better as it makes the test type more explicit.

Also I think that negative tests like this one are not in the right place. I feel that the level_{1,2,3} groups should contain tests about the value-selecting logic not about the parser. A forth group of tests, the parser tests (or maybe level_0), might contain the tests for the parser details (like white space, precedence, parse errors, etc.).

Owner

fd replied May 30, 2011

I think changing the extension of the negative tests to .error is better as it makes the test type more explicit.

Also I think that negative tests like this one are not in the right place. I feel that the level_{1,2,3} groups should contain tests about the value-selecting logic not about the parser. A forth group of tests, the parser tests (or maybe level_0), might contain the tests for the parser details (like white space, precedence, parse errors, etc.).

@lloyd

This comment has been minimized.

Show comment Hide comment
@lloyd

lloyd May 30, 2011

ok, I'll make the change to .error: lloyd/JSONSelectTests#1

I understand the suggestion about level_0, but it would be confusing. level_{123} correspond to conformance levels. Syntax errors in level 3 language constructs have to reside somewhere that they can be filtered out by implementers building level 1 support.

One thing we could do is create subdirectories under the level_{123} directories... perhaps syntax and matching directories. But then that gets into a pretty complicated structure for a fairly simple collection of stuff. what do you think?

ok, I'll make the change to .error: lloyd/JSONSelectTests#1

I understand the suggestion about level_0, but it would be confusing. level_{123} correspond to conformance levels. Syntax errors in level 3 language constructs have to reside somewhere that they can be filtered out by implementers building level 1 support.

One thing we could do is create subdirectories under the level_{123} directories... perhaps syntax and matching directories. But then that gets into a pretty complicated structure for a fairly simple collection of stuff. what do you think?

@fd

This comment has been minimized.

Show comment Hide comment
@fd

fd May 30, 2011

Owner

You're right. Let's just keep the level_0 stuff as it is and when things grow out of controle (which would presumably be in the distant future) we can still add more structure.

Owner

fd replied May 30, 2011

You're right. Let's just keep the level_0 stuff as it is and when things grow out of controle (which would presumably be in the distant future) we can still add more structure.

Please sign in to comment.