Permalink
Browse files

Add more advanced parsing stuff, including some code I'm not sure we …

…need.
  • Loading branch information...
1 parent 0274d76 commit a1c81255e7a0cd5f940dffe0781e39d2d50fdca2 @nex3 committed Jul 7, 2008
Showing with 107 additions and 18 deletions.
  1. +10 −3 grammar.rb
  2. +31 −15 jabl.rb
  3. +32 −0 parse_node.rb
  4. +34 −0 scanner.rb
View
@@ -3,11 +3,18 @@
class Jabl
class NestGrammar < Dhaka::Grammar
for_symbol Dhaka::START_SYMBOL_NAME do
- fun_statement ['fun_statement']
+ fun_statement %w[fun identifier arglist]
end
- for_symbol 'fun_statement' do
- argless %w[fun identifier]
+ for_symbol 'arglist' do
+ empty_args []
+ no_args %w[ ( ) ]
+ args %w[ ( args ) ]
+ end
+
+ for_symbol 'args' do
+ single_arg %w[ identifier ]
+ multiple_args %w[ identifier , arglist_list ]
end
end
NestParser = Dhaka::Parser.new(NestGrammar)
View
46 jabl.rb
@@ -1,11 +1,13 @@
require 'rubygems'
require 'enumerator'
-require 'lexer'
-require 'grammar'
+require 'scanner'
+#require 'lexer'
+#require 'grammar'
+#require 'parse_node'
class Jabl
Line = Struct.new(:text, :tabs, :index)
- Node = Struct.new(:text, :index, :children, :parsed)
+ Node = Struct.new(:text, :index, :children, :scanner)
def initialize(string)
@tree, _ = tree(tabulate(string))
@@ -28,14 +30,17 @@ def inspect(nodes = @tree, tabs = 0)
end.join(',')
end
+ def parse_tree
+ @tree
+ end
+
private
def compile(node, tabs)
- return tabs(tabs) + node.text + ";\n" if node.parsed.nil?
+ return tabs(tabs) + node.text + ";\n" if node.children.empty?
- case node.parsed.first
- when "fun_statement"; compile_fun node, tabs
- else; raise "Invalid parse node: #{node.parsed.inspect}"
+ if node.scanner.keyword :fun; compile_fun node, tabs
+ else; raise "Invalid parse node: #{node.inspect}"
end
end
@@ -44,8 +49,24 @@ def compile_nodes(nodes, tabs)
end
def compile_fun(node, tabs)
+ node.scanner.whitespace!
+ name = node.scanner.identifier!
+
+ args = []
+ if node.scanner.scan(/\(/)
+ loop do
+ node.scanner.whitespace?
+ args << node.scanner.identifier!
+ node.scanner.whitespace?
+ unless node.scanner.scan(/,/)
+ node.scanner.scan!(/\)/)
+ break
+ end
+ end
+ end
+
<<END
-#{tabs(tabs)}function #{node.parsed[1][2][1]}() {
+#{tabs(tabs)}function #{name}(#{args.join(', ')}) {
#{compile_nodes(node.children, tabs + 1)}#{tabs(tabs)}}
END
end
@@ -82,17 +103,12 @@ def tree(arr, i = 0)
def parse_nodes(nodes)
nodes.each do |n|
- next if n.children.empty?
n.children = parse_nodes(n.children)
- n.parsed = simplify_parse(NestParser.parse(NestLexer.lex(n.text)))
+ n.scanner = Scanner.new(n.text)
+ #_, n.parsed = ParseNode.from_node(NestParser.parse(NestLexer.lex(n.text)))
end
end
- def simplify_parse(node)
- return [node.token.symbol_name, node.token.value] if node.is_a? Dhaka::ParseTreeLeafNode
- [node.production.name] + node.child_nodes.map(&method(:simplify_parse))
- end
-
def tabs(tabs)
' ' * tabs
end
View
@@ -0,0 +1,32 @@
+class Jabl
+ class ParseNode
+ attr :name
+ attr :children
+
+ def self.from_node(node)
+ return [node.token.symbol_name, node.token.value] if node.is_a? Dhaka::ParseTreeLeafNode
+ return node.production.name, new(node)
+ end
+
+ def initialize(node)
+ @name = node.production.name
+ @children = node.child_nodes.inject({}) do |h, n|
+ name, node = ParseNode.from_node n
+ h[name] = node
+ h
+ end
+ end
+
+ def inspect
+ "#<#{name} #{children.inspect}>"
+ end
+
+ def method_missing(name, *args, &block)
+ return super(name, *args, &block) unless args.empty? && block.nil?
+ sname = name.to_s
+ return children[sname[0...-1]] if sname[-1] == ??
+ return children[sname] if children[sname]
+ super(name)
+ end
+ end
+end
View
@@ -0,0 +1,34 @@
+require 'strscan'
+
+class Jabl
+ class Scanner < StringScanner
+ def keyword(str)
+ scan(/\b#{Regexp.escape(str.to_s)}\b/)
+ end
+
+ def whitespace
+ scan(/\s+/)
+ end
+
+ def whitespace?
+ scan(/\s*/)
+ end
+
+ def identifier
+ scan(/\w+/)
+ end
+
+ def assert_empty!
+ return if eos?
+ raise "Expected end of line, got #{rest.inspect}"
+ end
+
+ def method_missing(name, *args, &block)
+ super(name, *args, &block) unless name.to_s[-1] == ?!
+ name = name.to_s
+ res = send(name[0...-1], *args, &block)
+ return res if res
+ raise "Expected #{name[0...-1]}(#{args.inspect[1...-1]})"
+ end
+ end
+end

0 comments on commit a1c8125

Please sign in to comment.