Skip to content

Commit

Permalink
Add vectors and more flexible symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
Josep M. Bach committed May 11, 2012
1 parent c7c57dc commit b29ceb4
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 6 deletions.
7 changes: 6 additions & 1 deletion lib/lambra/parser/lambra.kpeg
Expand Up @@ -10,6 +10,7 @@
%% symbol = ast Symbol(line, column, name)
%% seq = ast Sequence(line, column, elements)
%% form = ast Form(line, column, elements)
%% vector = ast Vector(line, column, elements)

eof = !.

Expand All @@ -34,7 +35,7 @@ true = "true" ~true_value(current_line, current_column)
false = "false" ~false_value(current_line, current_column)
nil = "nil" ~nil_value(current_line, current_column)

word = < /[a-zA-Z_][a-zA-Z0-9_]*/ > { text }
word = < /[a-zA-Z_\*][a-zA-Z0-9_\-\*]*/ > { text }
symbol = word:w ~symbol(current_line, current_column, w.to_sym)

string = '"' < /[^\\"]*/ > '"' ~string_value(current_line, current_column, text)
Expand All @@ -46,11 +47,15 @@ literal = float
| false
| nil
| string
| vector
| symbol

form = "(" expr_list:e ")" ~form(current_line, current_column, e)
| "(" ")" ~form(current_line, current_column, [])

vector = "[" expr_list:e "]" ~vector(current_line, current_column, e)
| "[" "]" ~vector(current_line, current_column, [])

expr = form
| literal

Expand Down
91 changes: 86 additions & 5 deletions lib/lambra/parser/parser.rb
Expand Up @@ -432,6 +432,16 @@ def initialize(line, column)
attr_reader :line
attr_reader :column
end
class Vector < Node
def initialize(line, column, elements)
@line = line
@column = column
@elements = elements
end
attr_reader :line
attr_reader :column
attr_reader :elements
end
end
def false_value(line, column)
::Lambra::AST::False.new(line, column)
Expand All @@ -457,6 +467,9 @@ def symbol(line, column, name)
def true_value(line, column)
::Lambra::AST::True.new(line, column)
end
def vector(line, column, elements)
::Lambra::AST::Vector.new(line, column, elements)
end
def setup_foreign_grammar; end

# eof = !.
Expand Down Expand Up @@ -791,13 +804,13 @@ def _nil
return _tmp
end

# word = < /[a-zA-Z_][a-zA-Z0-9_]*/ > { text }
# word = < /[a-zA-Z_\*][a-zA-Z0-9_\-\*]*/ > { text }
def _word

_save = self.pos
while true # sequence
_text_start = self.pos
_tmp = scan(/\A(?-mix:[a-zA-Z_][a-zA-Z0-9_]*)/)
_tmp = scan(/\A(?-mix:[a-zA-Z_\*][a-zA-Z0-9_\-\*]*)/)
if _tmp
text = get_text(_text_start)
end
Expand Down Expand Up @@ -876,7 +889,7 @@ def _string
return _tmp
end

# literal = (float | integer | hex | true | false | nil | string | symbol)
# literal = (float | integer | hex | true | false | nil | string | vector | symbol)
def _literal

_save = self.pos
Expand All @@ -902,6 +915,9 @@ def _literal
_tmp = apply(:_string)
break if _tmp
self.pos = _save
_tmp = apply(:_vector)
break if _tmp
self.pos = _save
_tmp = apply(:_symbol)
break if _tmp
self.pos = _save
Expand Down Expand Up @@ -976,6 +992,70 @@ def _form
return _tmp
end

# vector = ("[" expr_list:e "]" {vector(current_line, current_column, e)} | "[" "]" {vector(current_line, current_column, [])})
def _vector

_save = self.pos
while true # choice

_save1 = self.pos
while true # sequence
_tmp = match_string("[")
unless _tmp
self.pos = _save1
break
end
_tmp = apply(:_expr_list)
e = @result
unless _tmp
self.pos = _save1
break
end
_tmp = match_string("]")
unless _tmp
self.pos = _save1
break
end
@result = begin; vector(current_line, current_column, e); end
_tmp = true
unless _tmp
self.pos = _save1
end
break
end # end sequence

break if _tmp
self.pos = _save

_save2 = self.pos
while true # sequence
_tmp = match_string("[")
unless _tmp
self.pos = _save2
break
end
_tmp = match_string("]")
unless _tmp
self.pos = _save2
break
end
@result = begin; vector(current_line, current_column, []); end
_tmp = true
unless _tmp
self.pos = _save2
end
break
end # end sequence

break if _tmp
self.pos = _save
break
end # end choice

set_failed_rule :_vector unless _tmp
return _tmp
end

# expr = (form | literal)
def _expr

Expand Down Expand Up @@ -1236,11 +1316,12 @@ def _root
Rules[:_true] = rule_info("true", "\"true\" {true_value(current_line, current_column)}")
Rules[:_false] = rule_info("false", "\"false\" {false_value(current_line, current_column)}")
Rules[:_nil] = rule_info("nil", "\"nil\" {nil_value(current_line, current_column)}")
Rules[:_word] = rule_info("word", "< /[a-zA-Z_][a-zA-Z0-9_]*/ > { text }")
Rules[:_word] = rule_info("word", "< /[a-zA-Z_\\*][a-zA-Z0-9_\\-\\*]*/ > { text }")
Rules[:_symbol] = rule_info("symbol", "word:w {symbol(current_line, current_column, w.to_sym)}")
Rules[:_string] = rule_info("string", "\"\\\"\" < /[^\\\\\"]*/ > \"\\\"\" {string_value(current_line, current_column, text)}")
Rules[:_literal] = rule_info("literal", "(float | integer | hex | true | false | nil | string | symbol)")
Rules[:_literal] = rule_info("literal", "(float | integer | hex | true | false | nil | string | vector | symbol)")
Rules[:_form] = rule_info("form", "(\"(\" expr_list:e \")\" {form(current_line, current_column, e)} | \"(\" \")\" {form(current_line, current_column, [])})")
Rules[:_vector] = rule_info("vector", "(\"[\" expr_list:e \"]\" {vector(current_line, current_column, e)} | \"[\" \"]\" {vector(current_line, current_column, [])})")
Rules[:_expr] = rule_info("expr", "(form | literal)")
Rules[:_many_expr] = rule_info("many_expr", "(comment:e many_expr:m { [e] + m } | expr:e many_expr:m { [e] + m } | expr:e { [e] })")
Rules[:_sequence] = rule_info("sequence", "many_expr:e { e.size > 1 ? seq(current_line, current_column, e) : e.first }")
Expand Down
7 changes: 7 additions & 0 deletions lib/lambra/syntax/ast.rb
Expand Up @@ -36,5 +36,12 @@ def to_sexp
*@elements.map(&:to_sexp)]
end
end

class Vector < Node
def to_sexp
[sexp_name,
*@elements.map(&:to_sexp)]
end
end
end
end
31 changes: 31 additions & 0 deletions spec/syntax/ast_spec.rb
Expand Up @@ -74,3 +74,34 @@
}
end
end

describe "The Vector node" do
relates '[]' do
parse { [:vector] }
end

relates '[1 , 2 3]' do
parse { [:vector, [:number, 1], [:number, 2], [:number, 3]] }
end

relates '[hello world 43 "hey"]' do
parse {
[:vector,
[:symbol, :hello],
[:symbol, :world],
[:number, 43.0],
[:string, "hey"]]
}
end

relates "[hello \n\t (world 43) \"hey\"]" do
parse {
[:vector,
[:symbol, :hello],
[:form,
[:symbol, :world],
[:number, 43.0]],
[:string, "hey"]]
}
end
end

0 comments on commit b29ceb4

Please sign in to comment.