Skip to content
This repository has been archived by the owner on Dec 24, 2023. It is now read-only.

Commit

Permalink
Fixed 'call'
Browse files Browse the repository at this point in the history
- Fixed 'call' expressions (ex. "print(hello)")
- Tried to fix the empty lines
- Fixed closures
  • Loading branch information
deathbeam committed Apr 23, 2016
1 parent 2d9379f commit 11cd69e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 73 deletions.
9 changes: 7 additions & 2 deletions examples/test.spoon
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#!/usr/bin/env spoon

function a(b = 7, c = "aaa")
if a < 0
return c
call = ->
print "Closure!"

if b < 0
call()
else
print "Fail"

function a(b = 7, c = "aaa")
if a < 0
Expand Down
130 changes: 67 additions & 63 deletions lib/spoon/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ def initialize
}

# Matches word
rule(:word) {
rule(:name) {
skip_key >>
match['a-zA-Z\-'].repeat(1).as(:word)
(match['a-zA-Z'] >> match['a-zA-Z\-'].repeat).as(:name)
}

# Matches strings
Expand Down Expand Up @@ -71,6 +71,13 @@ def initialize
).as(:number)
}

# Matches everything that starts with '#' until end of line
# example: # abc
rule(:comment) {
str("#") >>
stop
}

# Matches literals (strings, numbers)
rule(:literal) {
number |
Expand All @@ -82,8 +89,9 @@ def initialize
condition |
closure |
chain |
call |
ret |
word |
name |
literal
}

Expand All @@ -92,25 +100,12 @@ def initialize
function
}

# Matches everything that starts with '#' until end of line
# example: # abc
rule(:comment) {
str("#") >>
stop
}

# Matches expression or indented block and skips end of line at end
rule(:body) {
block |
expression
}

# Matches chain value
rule(:chain_value) {
call |
word
}

# Matches chain of expressions
# example: abc(a).def(b).efg
rule(:chain) {
Expand All @@ -123,12 +118,20 @@ def initialize
).as(:chain)
}

# Matches chain value
rule(:chain_value) {
call |
name
}

# Matches function call
# example: a(b, c, d, e, f)
rule(:call) {
word >>
space.maybe >>
parens(expression_list.as(:arguments))
(
name >>
space.maybe >>
parens(expression_list.as(:arguments))
).as(:call)
}

# Matches return statement
Expand All @@ -142,7 +145,7 @@ def initialize
# Matches indented block and consumes newlines at start and in between
# but not at end
rule(:block) {
newline >>
skipline.maybe >>
indent >>
(
expression >>
Expand All @@ -152,7 +155,17 @@ def initialize
).repeat
).maybe.as(:block) >>
dedent >>
endofline.maybe
skipline.maybe
}

# Matches function parameter
# example a = 1
rule(:parameter) {
name >>
(
trim(str("=")) >>
expression.as(:value)
).maybe
}

# Matches comma delimited function parameters
Expand All @@ -164,14 +177,17 @@ def initialize
).repeat
}

# Matches function parameter
# example a = 1
rule(:parameter) {
word.as(:name) >>
# Matches expression
rule(:expression) {
(
trim(str("=")) >>
expression.as(:value)
).maybe
statement |
(
value.as(:left) >>
trim(operator) >>
value.as(:right)
) |
value
) >> skipline.maybe
}

# Matches comma delimited expressions
Expand All @@ -184,28 +200,6 @@ def initialize
).repeat
}

# Matches operator
rule(:operator) {
(
str("<=") |
str(">=") |
str("!=") |
str("==") |
str("+=") |
str("-=") |
str("*=") |
str("/=") |
str("%=") |
str("and=") |
str("or=") |
key("or") |
key("and") |
key("is") |
key("isnt") |
match['\+\-\*\/%\^><\|&=']
).as(:op)
}

# Matches closure
# example: (a) -> b
rule(:closure) {
Expand All @@ -216,25 +210,13 @@ def initialize
).as(:closure)
}

# Matches expression
rule(:expression) {
(
statement |
(
value.as(:left) >>
trim(operator) >>
value.as(:right)
) | value
) >> endofline.maybe
}

# Matches function definition
# example: def (a) b
rule(:function) {
(
key("function") >>
space.maybe >>
word.as(:name) >>
name >>
space.maybe >>
function_body
).as(:function)
Expand Down Expand Up @@ -266,5 +248,27 @@ def initialize
).maybe
).as(:condition)
}

# Matches operator
rule(:operator) {
(
str("<=") |
str(">=") |
str("!=") |
str("==") |
str("+=") |
str("-=") |
str("*=") |
str("/=") |
str("%=") |
str("and=") |
str("or=") |
key("or") |
key("and") |
key("is") |
key("isnt") |
match['\+\-\*\/%\^><\|&=']
).as(:op)
}
end
end
13 changes: 5 additions & 8 deletions lib/spoon/util/parser_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,22 @@ def key(value)
def trim(value) whitespace.maybe >> value >> whitespace.maybe end

# Matches value in parens or not in parens
def parens(value) (str("(") >> whitespace.maybe >> value >> whitespace.maybe >> str(")")) | value end
def parens(value) (str("(") >> whitespace.maybe >> value.maybe >> whitespace.maybe >> str(")")) | value end

# Matches single or multiple end of lines
rule(:newline) { match["\n\r"].repeat(1) }
rule(:newline) { match["\n\r"] }

# Matches single or multiple spaces, tabs and comments
rule(:space) { (match("\s") | comment).repeat(1) }
rule(:space) { (comment | match("\s")).repeat(1) }

# Matches all whitespace (tab, end of line, space, comments)
rule(:whitespace) { (match["\s\n\r"] | comment).repeat(1) }
rule(:whitespace) { (comment | match["\s\n\r"]).repeat(1) }

# Matches everything until end of line
rule(:stop) { match["^\n"].repeat }

# Matches empty line
rule(:emptyline) { (match["\n\r"] >> match("\s").repeat >> match["\n\r"]) | match["\n\r"] }

# Matches space to end of line
rule(:endofline) { space.maybe >> emptyline.repeat(1) }
rule(:skipline) { (space.maybe >> newline).repeat(1) }

# Dummy comment rule, override in implementation
rule(:comment) { never_match }
Expand Down

0 comments on commit 11cd69e

Please sign in to comment.