Skip to content

Commit

Permalink
Showing 7 changed files with 154 additions and 145 deletions.
7 changes: 3 additions & 4 deletions lib/opal/compiler.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
require 'opal/lexer'
require 'opal/grammar'
require 'set'
require 'opal/parser'
require 'opal/target_scope'
require 'opal/version'
require 'opal/fragment'
require 'opal/nodes'
require 'set'

module Opal
class Compiler
@@ -71,7 +70,7 @@ def compile(source, options = {})
@source = source
@options.update options

@sexp = Grammar.new.parse(@source, self.file)
@sexp = Parser.new.parse(@source, self.file)

top_node = Nodes::TopNode.new(@sexp, :expr, self)
@fragments = top_node.compile_to_fragments.flatten
84 changes: 42 additions & 42 deletions lib/opal/grammar.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 41 additions & 41 deletions lib/opal/grammar.y
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Opal::Grammar
class Opal::Parser

token CLASS MODULE DEF UNDEF BEGIN RESCUE ENSURE END IF UNLESS
THEN ELSIF ELSE CASE WHEN WHILE UNTIL FOR BREAK NEXT
@@ -85,7 +85,7 @@ stmts:
stmt:
ALIAS fitem
{
@lex_state = :expr_fname
lexer.lex_state = :expr_fname
}
fitem
{
@@ -394,12 +394,12 @@ fname:
| FID
| op
{
@lex_state = :expr_end
lexer.lex_state = :expr_end
result = val[0]
}
| reswords
{
@lex_state = :expr_end
lexer.lex_state = :expr_end
result = val[0]
}

@@ -676,11 +676,11 @@ call_args2:

command_args:
{
cmdarg_push 1
lexer.cmdarg_push 1
}
open_args
{
cmdarg_pop
lexer.cmdarg_pop
result = val[1]
}

@@ -753,7 +753,7 @@ primary:
| FID
| BEGIN
{
result = @line
result = lexer.line
}
bodystmt END
{
@@ -842,12 +842,12 @@ primary:
}
| WHILE
{
cond_push 1
result = @line
lexer.cond_push 1
result = lexer.line
}
expr_value do
{
cond_pop
lexer.cond_pop
}
compstmt END
{
@@ -856,12 +856,12 @@ primary:
}
| UNTIL
{
cond_push 1
result = @line
lexer.cond_push 1
result = lexer.line
}
expr_value do
{
cond_pop
lexer.cond_pop
}
compstmt END
{
@@ -894,7 +894,7 @@ primary:
compstmt END
| CLASS
{
result = @line
result = lexer.line
}
cpath superclass
{
@@ -904,11 +904,11 @@ primary:
{
result = new_class val[2], val[3], val[5]
result.line = val[1]
result.end_line = @line
result.end_line = lexer.line
}
| CLASS '<<'
{
result = @line
result = lexer.line
}
expr term
{
@@ -921,7 +921,7 @@ primary:
}
| MODULE
{
result = @line
result = lexer.line
}
cpath
{
@@ -931,11 +931,11 @@ primary:
{
result = new_module val[2], val[4]
result.line = val[1]
result.end_line = @line
result.end_line = lexer.line
}
| DEF fname
{
result = @scope_line
result = lexer.scope_line
push_scope
}
f_arglist bodystmt END
@@ -949,7 +949,7 @@ primary:
}
fname
{
result = @scope_line
result = lexer.scope_line
push_scope
}
f_arglist bodystmt END
@@ -1021,7 +1021,7 @@ if_tail:
}
| ELSIF
{
result = @line
result = lexer.line
}
expr_value then compstmt if_tail
{
@@ -1126,7 +1126,7 @@ do_block:
DO_BLOCK
{
push_scope :block
result = @line
result = lexer.line
}
opt_block_var compstmt END
{
@@ -1178,7 +1178,7 @@ brace_block:
LCURLY
{
push_scope :block
result = @line
result = lexer.line
}
opt_block_var compstmt '}'
{
@@ -1189,7 +1189,7 @@ brace_block:
| DO
{
push_scope :block
result = @line
result = lexer.line
}
opt_block_var compstmt END
{
@@ -1201,7 +1201,7 @@ brace_block:
case_body:
WHEN
{
result = @line
result = lexer.line
}
args then compstmt cases
{
@@ -1372,27 +1372,27 @@ string_content:
}
| STRING_DVAR
{
result = @string_parse
@string_parse = nil
result = lexer.string_parse
lexer.string_parse = nil
}
string_dvar
{
@string_parse = val[1]
lexer.string_parse = val[1]
result = s(:evstr, val[2])
}
| STRING_DBEG
{
cond_push 0
cmdarg_push 0
result = @string_parse
@string_parse = nil
@lex_state = :expr_beg
lexer.cond_push 0
lexer.cmdarg_push 0
result = lexer.string_parse
lexer.string_parse = nil
lexer.lex_state = :expr_beg
}
compstmt '}'
{
@string_parse = val[1]
cond_lexpop
cmdarg_lexpop
lexer.string_parse = val[1]
lexer.cond_lexpop
lexer.cmdarg_lexpop
result = s(:evstr, val[2])
}

@@ -1416,7 +1416,7 @@ symbol:
SYMBOL_BEG sym
{
result = s(:sym, val[1].intern)
@lex_state = :expr_end
lexer.lex_state = :expr_end
}
| SYMBOL
{
@@ -1485,11 +1485,11 @@ variable:
}
| FILE
{
result = s(:str, @file)
result = s(:str, self.file)
}
| LINE
{
result = s(:int, @line)
result = s(:int, lexer.line)
}

var_ref:
@@ -1529,7 +1529,7 @@ f_arglist:
'(' f_args opt_nl ')'
{
result = val[1]
@lex_state = :expr_beg
lexer.lex_state = :expr_beg
}
| f_args term
{
@@ -1594,7 +1594,7 @@ f_norm_arg:
| IDENTIFIER
{
result = val[0].intern
@scope.add_local result
scope.add_local result
}

f_arg_item:
48 changes: 6 additions & 42 deletions lib/opal/lexer.rb
Original file line number Diff line number Diff line change
@@ -1,59 +1,23 @@
require 'opal/sexp'
require 'opal/grammar'
require 'opal/grammar_helpers'
require 'opal/lexer_scope'
require 'strscan'

module Opal
class Lexer

class Grammar < Racc::Parser
attr_reader :line, :scope_line, :scope

attr_reader :line
attr_accessor :lex_state, :string_parse

def initialize
def initialize(source, file)
@lex_state = :expr_beg
@cond = 0
@cmdarg = 0
@line = 1
@scopes = []
@file = file

@string_parse_stack = []
@scanner = StringScanner.new(source)
end

def s(*parts)
sexp = Sexp.new(parts)
sexp.line = @line
sexp
end

def parse(source, file = '(string)')
@file = file
@scanner = StringScanner.new source
push_scope
result = do_parse
pop_scope

result
end

def on_error(t, val, vstack)
raise "parse error on value #{val.inspect} (#{token_to_str(t) || '?'}) :#{@file}:#{@line}"
end

def push_scope(type = nil)
top = @scopes.last
scope = LexerScope.new type
scope.parent = top
@scopes << scope
@scope = scope
end

def pop_scope
@scopes.pop
@scope = @scopes.last
end


def cond_push(n)
@cond = (@cond << 1) | (n & 1)
end
69 changes: 59 additions & 10 deletions lib/opal/grammar_helpers.rb → lib/opal/parser.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,55 @@
require 'opal/sexp'
require 'opal/lexer'
require 'opal/grammar'
require 'opal/parser_scope'

module Opal
class Grammar < Racc::Parser
class Parser < Racc::Parser

attr_reader :lexer, :file, :scope

def parse(source, file = '(string)')
@lexer = Lexer.new(source, file)
@file = file
@scopes = []

self.parse_to_sexp
end

def parse_to_sexp
push_scope
result = self.do_parse
pop_scope

result
end

def next_token
@lexer.next_token
end

def s(*parts)
sexp = Sexp.new(parts)
sexp.line = @line
sexp
end

def push_scope(type = nil)
top = @scopes.last
scope = ParserScope.new type
scope.parent = top
@scopes << scope
@scope = scope
end

def pop_scope
@scopes.pop
@scope = @scopes.last
end

def on_error(t, val, vstack)
raise "parse error on value #{val.inspect} (#{token_to_str(t) || '?'}) :#{@file}:#{lexer.line}"
end

def new_block(stmt = nil)
s = s(:block)
@@ -86,7 +136,7 @@ def new_args(norm, opt, rest, block)

if norm
norm.each do |arg|
@scope.add_local arg
scope.add_local arg
res << arg
end
end
@@ -100,12 +150,12 @@ def new_args(norm, opt, rest, block)
if rest
res << rest
rest_str = rest.to_s[1..-1]
@scope.add_local rest_str.to_sym unless rest_str.empty?
scope.add_local rest_str.to_sym unless rest_str.empty?
end

if block
res << block
@scope.add_local block.to_s[1..-1].to_sym
scope.add_local block.to_s[1..-1].to_sym
end

res << opt if opt
@@ -119,7 +169,7 @@ def new_block_args(norm, opt, rest, block)
if norm
norm.each do |arg|
if arg.is_a? Symbol
@scope.add_local arg
scope.add_local arg
res << s(:lasgn, arg)
else
res << arg
@@ -136,13 +186,13 @@ def new_block_args(norm, opt, rest, block)
if rest
r = rest.to_s[1..-1].to_sym
res << s(:splat, s(:lasgn, r))
@scope.add_local r
scope.add_local r
end

if block
b = block.to_s[1..-1].to_sym
res << s(:block_pass, s(:lasgn, b))
@scope.add_local b
scope.add_local b
end

res << opt if opt
@@ -229,7 +279,7 @@ def new_assignable(ref)
when :const
ref.type = :cdecl
when :identifier
@scope.add_local ref[1] unless @scope.has_local? ref[1]
scope.add_local ref[1] unless scope.has_local? ref[1]
ref.type = :lasgn
when :gvar
ref.type = :gasgn
@@ -275,7 +325,7 @@ def new_var_ref(ref)
# returns for __FILE__ as it is converted into str
ref
when :identifier
if @scope.has_local? ref[1]
if scope.has_local? ref[1]
s(:lvar, ref[1])
else
s(:call, nil, ref[1], s(:arglist))
@@ -371,4 +421,3 @@ def str_append(str, str2)
end
end
end

7 changes: 2 additions & 5 deletions lib/opal/lexer_scope.rb → lib/opal/parser_scope.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
module Opal
# LexerScope is used during lexing to keep track of local variables
# ParserScope is used during lexing to keep track of local variables
# created inside a scope. A lexer scope can be asked if it has a local
# variable defined, and it can also check its parent scope if applicable.
#
# A LexerScope is created automatically as a new scope is entered during
# the lexing stage.
class LexerScope
class ParserScope
attr_reader :locals
attr_accessor :parent

2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@

module Kernel
def opal_parse(str, file='(string)')
Opal::Grammar.new.parse str, file
Opal::Parser.new.parse str, file
end

def eval_js(javascript)

0 comments on commit 689a501

Please sign in to comment.