Basic CSS parser boilerplate.

This currently only parses single node tests (e.g. just "foo").
This commit is contained in:
Yorick Peterse 2014-10-02 23:31:58 +02:00
parent 4eea6d8359
commit b9a1f914bd
4 changed files with 91 additions and 1 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ lib/oga/xml/parser.rb
lib/oga/xpath/lexer.rb
lib/oga/xpath/parser.rb
lib/oga/css/lexer.rb
lib/oga/css/parser.rb
lib/liboga.*

View File

@ -49,3 +49,4 @@ require_relative 'oga/xpath/parser'
require_relative 'oga/xpath/evaluator'
require_relative 'oga/css/lexer'
require_relative 'oga/css/parser'

84
lib/oga/css/parser.y Normal file
View File

@ -0,0 +1,84 @@
##
# AST parser for CSS expressions.
#
class Oga::CSS::Parser
options no_result_var
rule
css
: selectors { val[0] }
| /* none */ { nil }
;
selectors
: selectors selector { val[0] << val[1] }
| selector { val[0] }
;
selector
: node_test
;
node_test
: node_name { s(:test, *val[0]) }
;
node_name
# foo
: T_IDENT { [nil, val[0]] }
# ns|foo
| T_IDENT T_PIPE T_IDENT { [val[0], val[2]] }
# |foo
| T_PIPE T_IDENT { [nil, val[1]] }
;
end
---- inner
##
# @param [String] data The input to parse.
#
def initialize(data)
@lexer = Lexer.new(data)
end
##
# @param [Symbol] type
# @param [Array] children
# @return [AST::Node]
#
def s(type, *children)
return AST::Node.new(type, children)
end
##
# Yields the next token from the lexer.
#
# @yieldparam [Array]
#
def yield_next_token
@lexer.advance do |*args|
yield args
end
yield [false, false]
end
##
# Parses the input and returns the corresponding AST.
#
# @example
# parser = Oga::CSS::Parser.new('foo.bar')
# ast = parser.parse
#
# @return [AST::Node]
#
def parse
ast = yyparse(self, :yield_next_token)
return ast
end
# vim: set ft=racc:

View File

@ -3,4 +3,8 @@ rule '.rb' => '.y' do |task|
end
desc 'Generates the parser'
task :parser => ['lib/oga/xml/parser.rb', 'lib/oga/xpath/parser.rb']
task :parser => [
'lib/oga/xml/parser.rb',
'lib/oga/xpath/parser.rb',
'lib/oga/css/parser.rb'
]