Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: txus/lambra
base: b29ceb49f5
...
head fork: txus/lambra
compare: 6e76bddd08
Checking mergeability… Don't worry, you can still create the pull request.
  • 4 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
View
21 lib/lambra/parser/lambra.kpeg
@@ -8,9 +8,12 @@
%% false_value = ast False(line, column)
%% nil_value = ast Nil(line, column)
%% symbol = ast Symbol(line, column, name)
+%% keyword = ast Keyword(line, column, name)
%% seq = ast Sequence(line, column, elements)
-%% form = ast Form(line, column, elements)
+%% list = ast List(line, column, elements)
%% vector = ast Vector(line, column, elements)
+%% set = ast Set(line, column, elements)
+%% map = ast Map(line, column, elements)
eof = !.
@@ -37,6 +40,7 @@ nil = "nil" ~nil_value(current_line, current_column)
word = < /[a-zA-Z_\*][a-zA-Z0-9_\-\*]*/ > { text }
symbol = word:w ~symbol(current_line, current_column, w.to_sym)
+keyword = ":" word:w ~keyword(current_line, current_column, w.to_sym)
string = '"' < /[^\\"]*/ > '"' ~string_value(current_line, current_column, text)
@@ -48,15 +52,24 @@ literal = float
| nil
| string
| vector
+ | set
+ | map
| symbol
+ | keyword
-form = "(" expr_list:e ")" ~form(current_line, current_column, e)
- | "(" ")" ~form(current_line, current_column, [])
+list = "(" expr_list:e ")" ~list(current_line, current_column, e)
+ | "(" ")" ~list(current_line, current_column, [])
vector = "[" expr_list:e "]" ~vector(current_line, current_column, e)
| "[" "]" ~vector(current_line, current_column, [])
-expr = form
+set = "#{" expr_list:e "}" ~set(current_line, current_column, e)
+ | "#{" "}" ~set(current_line, current_column, [])
+
+map = "{" expr_list:e "}" ~map(current_line, current_column, Hash[*e])
+ | "{" "}" ~map(current_line, current_column, {})
+
+expr = list
| literal
many_expr = comment:e many_expr:m { [e] + m }
View
235 lib/lambra/parser/parser.rb
@@ -366,7 +366,27 @@ def initialize(line, column)
attr_reader :line
attr_reader :column
end
- class Form < Node
+ class Keyword < Node
+ def initialize(line, column, name)
+ @line = line
+ @column = column
+ @name = name
+ end
+ attr_reader :line
+ attr_reader :column
+ attr_reader :name
+ end
+ class List < Node
+ def initialize(line, column, elements)
+ @line = line
+ @column = column
+ @elements = elements
+ end
+ attr_reader :line
+ attr_reader :column
+ attr_reader :elements
+ end
+ class Map < Node
def initialize(line, column, elements)
@line = line
@column = column
@@ -404,6 +424,16 @@ def initialize(line, column, elements)
attr_reader :column
attr_reader :elements
end
+ class Set < Node
+ def initialize(line, column, elements)
+ @line = line
+ @column = column
+ @elements = elements
+ end
+ attr_reader :line
+ attr_reader :column
+ attr_reader :elements
+ end
class String < Node
def initialize(line, column, value)
@line = line
@@ -446,8 +476,14 @@ def initialize(line, column, elements)
def false_value(line, column)
::Lambra::AST::False.new(line, column)
end
- def form(line, column, elements)
- ::Lambra::AST::Form.new(line, column, elements)
+ def keyword(line, column, name)
+ ::Lambra::AST::Keyword.new(line, column, name)
+ end
+ def list(line, column, elements)
+ ::Lambra::AST::List.new(line, column, elements)
+ end
+ def map(line, column, elements)
+ ::Lambra::AST::Map.new(line, column, elements)
end
def nil_value(line, column)
::Lambra::AST::Nil.new(line, column)
@@ -458,6 +494,9 @@ def number(line, column, value)
def seq(line, column, elements)
::Lambra::AST::Sequence.new(line, column, elements)
end
+ def set(line, column, elements)
+ ::Lambra::AST::Set.new(line, column, elements)
+ end
def string_value(line, column, value)
::Lambra::AST::String.new(line, column, value)
end
@@ -853,6 +892,34 @@ def _symbol
return _tmp
end
+ # keyword = ":" word:w {keyword(current_line, current_column, w.to_sym)}
+ def _keyword
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string(":")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_word)
+ w = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; keyword(current_line, current_column, w.to_sym); end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_keyword unless _tmp
+ return _tmp
+ end
+
# string = "\"" < /[^\\"]*/ > "\"" {string_value(current_line, current_column, text)}
def _string
@@ -889,7 +956,7 @@ def _string
return _tmp
end
- # literal = (float | integer | hex | true | false | nil | string | vector | symbol)
+ # literal = (float | integer | hex | true | false | nil | string | vector | set | map | symbol | keyword)
def _literal
_save = self.pos
@@ -918,9 +985,18 @@ def _literal
_tmp = apply(:_vector)
break if _tmp
self.pos = _save
+ _tmp = apply(:_set)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_map)
+ break if _tmp
+ self.pos = _save
_tmp = apply(:_symbol)
break if _tmp
self.pos = _save
+ _tmp = apply(:_keyword)
+ break if _tmp
+ self.pos = _save
break
end # end choice
@@ -928,8 +1004,8 @@ def _literal
return _tmp
end
- # form = ("(" expr_list:e ")" {form(current_line, current_column, e)} | "(" ")" {form(current_line, current_column, [])})
- def _form
+ # list = ("(" expr_list:e ")" {list(current_line, current_column, e)} | "(" ")" {list(current_line, current_column, [])})
+ def _list
_save = self.pos
while true # choice
@@ -952,7 +1028,7 @@ def _form
self.pos = _save1
break
end
- @result = begin; form(current_line, current_column, e); end
+ @result = begin; list(current_line, current_column, e); end
_tmp = true
unless _tmp
self.pos = _save1
@@ -975,7 +1051,7 @@ def _form
self.pos = _save2
break
end
- @result = begin; form(current_line, current_column, []); end
+ @result = begin; list(current_line, current_column, []); end
_tmp = true
unless _tmp
self.pos = _save2
@@ -988,7 +1064,7 @@ def _form
break
end # end choice
- set_failed_rule :_form unless _tmp
+ set_failed_rule :_list unless _tmp
return _tmp
end
@@ -1056,12 +1132,140 @@ def _vector
return _tmp
end
- # expr = (form | literal)
+ # set = ("#{" expr_list:e "}" {set(current_line, current_column, e)} | "#{" "}" {set(current_line, current_column, [])})
+ def _set
+
+ _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; set(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; set(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 :_set unless _tmp
+ return _tmp
+ end
+
+ # map = ("{" expr_list:e "}" {map(current_line, current_column, Hash[*e])} | "{" "}" {map(current_line, current_column, {})})
+ def _map
+
+ _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; map(current_line, current_column, Hash[*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; map(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 :_map unless _tmp
+ return _tmp
+ end
+
+ # expr = (list | literal)
def _expr
_save = self.pos
while true # choice
- _tmp = apply(:_form)
+ _tmp = apply(:_list)
break if _tmp
self.pos = _save
_tmp = apply(:_literal)
@@ -1318,11 +1522,14 @@ def _root
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[:_symbol] = rule_info("symbol", "word:w {symbol(current_line, current_column, w.to_sym)}")
+ Rules[:_keyword] = rule_info("keyword", "\":\" word:w {keyword(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 | vector | symbol)")
- Rules[:_form] = rule_info("form", "(\"(\" expr_list:e \")\" {form(current_line, current_column, e)} | \"(\" \")\" {form(current_line, current_column, [])})")
+ Rules[:_literal] = rule_info("literal", "(float | integer | hex | true | false | nil | string | vector | set | map | symbol | keyword)")
+ Rules[:_list] = rule_info("list", "(\"(\" expr_list:e \")\" {list(current_line, current_column, e)} | \"(\" \")\" {list(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[:_set] = rule_info("set", "(\"\#{\" expr_list:e \"}\" {set(current_line, current_column, e)} | \"\#{\" \"}\" {set(current_line, current_column, [])})")
+ Rules[:_map] = rule_info("map", "(\"{\" expr_list:e \"}\" {map(current_line, current_column, Hash[*e])} | \"{\" \"}\" {map(current_line, current_column, {})})")
+ Rules[:_expr] = rule_info("expr", "(list | 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 }")
Rules[:_expr_list_b] = rule_info("expr_list_b", "(expr:e br-sp expr_list_b:l { [e] + l } | expr:e { [e] })")
View
28 lib/lambra/syntax/ast.rb
@@ -30,7 +30,33 @@ def to_sexp
end
end
- class Form < Node
+ class Keyword < Node
+ def to_sexp
+ [sexp_name, @name]
+ end
+ end
+
+ class List < Node
+ def to_sexp
+ [sexp_name,
+ *@elements.map(&:to_sexp)]
+ end
+ end
+
+ class Map < Node
+ def to_sexp
+ return super if @elements.empty?
+
+ keys = @elements.keys.map(&:to_sexp)
+ values = @elements.values.map(&:to_sexp)
+
+ elements = Hash[keys.zip(values)]
+
+ [sexp_name, elements]
+ end
+ end
+
+ class Set < Node
def to_sexp
[sexp_name,
*@elements.map(&:to_sexp)]
View
46 spec/syntax/ast_spec.rb
@@ -6,6 +6,18 @@
end
end
+describe "The Symbol node" do
+ relates "hello-world" do
+ parse { [:symbol, :"hello-world"] }
+ end
+end
+
+describe "The Keyword node" do
+ relates ":hello-world" do
+ parse { [:keyword, :"hello-world"] }
+ end
+end
+
describe "The Number node" do
relates "42" do
parse { [:number, 42] }
@@ -44,18 +56,18 @@
end
end
-describe "The Form node" do
+describe "The List node" do
relates '()' do
- parse { [:form] }
+ parse { [:list] }
end
relates '(1 , 2 3)' do
- parse { [:form, [:number, 1], [:number, 2], [:number, 3]] }
+ parse { [:list, [:number, 1], [:number, 2], [:number, 3]] }
end
relates '(hello world 43 "hey")' do
parse {
- [:form,
+ [:list,
[:symbol, :hello],
[:symbol, :world],
[:number, 43.0],
@@ -65,9 +77,9 @@
relates "(hello \n\t (world 43) \"hey\")" do
parse {
- [:form,
+ [:list,
[:symbol, :hello],
- [:form,
+ [:list,
[:symbol, :world],
[:number, 43.0]],
[:string, "hey"]]
@@ -98,10 +110,30 @@
parse {
[:vector,
[:symbol, :hello],
- [:form,
+ [:list,
[:symbol, :world],
[:number, 43.0]],
[:string, "hey"]]
}
end
end
+
+describe "The Map node" do
+ relates '{}' do
+ parse { [:map] }
+ end
+
+ relates '{:a 1 :b 2}' do
+ parse { [:map, {[:keyword, :a] => [:number, 1], [:keyword, :b] => [:number, 2]}] }
+ end
+end
+
+describe "The Set node" do
+ relates '#{}' do
+ parse { [:set] }
+ end
+
+ relates '#{:a :b :c}' do
+ parse { [:set, [:keyword, :a], [:keyword, :b], [:keyword, :c]] }
+ end
+end

No commit comments for this range

Something went wrong with that request. Please try again.