diff --git a/lib/oga/xpath/lexer.rl b/lib/oga/xpath/lexer.rl index c2e7064..998febf 100644 --- a/lib/oga/xpath/lexer.rl +++ b/lib/oga/xpath/lexer.rl @@ -316,6 +316,19 @@ module Oga emit(:T_TYPE_TEST, ts, te - 2) } + # Variables + # + # XPath 1.0 allows the use of variables in expressions. Oddly enough you + # can not assign variables in an expression, you can only refer to them. + # This means that libraries themselves have to expose an interface for + # setting variables. + # + var = '$' identifier; + + action emit_variable { + emit(:T_VAR, ts + 1, te) + } + main := |* operator; whitespace | slash | lparen | rparen | comma | colon; @@ -325,6 +338,7 @@ module Oga '[' => { add_token(:T_LBRACK) }; ']' => { add_token(:T_RBRACK) }; + var => emit_variable; string => emit_string; integer => emit_integer; float => emit_float; diff --git a/lib/oga/xpath/parser.y b/lib/oga/xpath/parser.y index 4d0c417..4c68743 100644 --- a/lib/oga/xpath/parser.y +++ b/lib/oga/xpath/parser.y @@ -6,7 +6,7 @@ class Oga::XPath::Parser token T_AXIS T_COLON T_COMMA T_FLOAT T_INT T_IDENT T_TYPE_TEST token T_LBRACK T_RBRACK T_LPAREN T_RPAREN T_SLASH T_STRING token T_PIPE T_AND T_OR T_ADD T_DIV T_MOD T_EQ T_NEQ T_LT T_GT T_LTE T_GTE -token T_SUB T_MUL +token T_SUB T_MUL T_VAR options no_result_var @@ -42,6 +42,7 @@ rule | call | path | absolute_path + | variable ; path_member @@ -139,6 +140,10 @@ rule number : T_INT { s(:int, val[0]) } | T_FLOAT { s(:float, val[0]) } + + variable + : T_VAR { s(:var, val[0]) } + ; end ---- inner diff --git a/spec/oga/xpath/lexer/variable_spec.rb b/spec/oga/xpath/lexer/variable_spec.rb new file mode 100644 index 0000000..5f23860 --- /dev/null +++ b/spec/oga/xpath/lexer/variable_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe Oga::XPath::Lexer do + context 'variables' do + example 'lex a variable reference' do + lex_xpath('$foo').should == [[:T_VAR, 'foo']] + end + end +end diff --git a/spec/oga/xpath/parser/variable_spec.rb b/spec/oga/xpath/parser/variable_spec.rb new file mode 100644 index 0000000..6935d35 --- /dev/null +++ b/spec/oga/xpath/parser/variable_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Oga::XPath::Parser do + context 'variables' do + example 'parse a variable reference' do + parse_xpath('$foo').should == s(:var, 'foo') + end + + example 'parse a variable reference in a predicate' do + parse_xpath('foo[$bar]').should == s( + :axis, + 'child', + s(:test, nil, 'foo', s(:var, 'bar')) + ) + end + end +end