Class: Gemite::Parser

Inherits:
Object
  • Object
show all
Includes:
AST
Defined in:
lib/gemite/parser.rb

Overview

の中身や、式の断片(補間・@ifの条件式など)をASTへ変換する。

再帰下降パーサー。

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tokens) ⇒ Parser

Returns a new instance of Parser.



40
41
42
43
# File 'lib/gemite/parser.rb', line 40

def initialize(tokens)
  @tokens = tokens
  @pos = 0
end

Class Method Details

.parse_expression_from_source(source, line: 1) ⇒ Object

ソース文字列を単一の式としてパースする(expr補間や@if条件式用)



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/gemite/parser.rb', line 21

def self.parse_expression_from_source(source, line: 1)
  tokens = Lexer.new(source, line: line).tokenize
  parser = new(tokens)
  parser.send(:skip_newlines)
  expr = parser.send(:parse_expression)
  parser.send(:skip_newlines)
  unless parser.send(:check, :EOF)
    tok = parser.send(:current)
    raise Gemite::SyntaxError.new("式の後に余分なトークンがあります (#{tok.type})", line: tok.line)
  end
  expr
end

.parse_for_clause_from_source(source, line: 1) ⇒ Object

"var in iterable" 形式(@forの節)をパースする



35
36
37
38
# File 'lib/gemite/parser.rb', line 35

def self.parse_for_clause_from_source(source, line: 1)
  tokens = Lexer.new(source, line: line).tokenize
  new(tokens).parse_for_clause
end

.parse_statements_from_source(source, line: 1) ⇒ Object

ソース文字列全体を「文の並び」としてパースする(ブロックの中身用)



15
16
17
18
# File 'lib/gemite/parser.rb', line 15

def self.parse_statements_from_source(source, line: 1)
  tokens = Lexer.new(source, line: line).tokenize
  new(tokens).parse_statements_until(nil)
end

Instance Method Details

#parse_for_clauseObject



45
46
47
48
49
50
# File 'lib/gemite/parser.rb', line 45

def parse_for_clause
  name_tok = expect(:IDENT)
  expect(:IN)
  iterable = parse_expression
  [name_tok.value, iterable]
end

#parse_statements_until(stop_types) ⇒ Object

stop_types: nilならEOFまで。配列ならそのトークン型に出会うまで(消費はしない)。



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/gemite/parser.rb', line 53

def parse_statements_until(stop_types)
  stmts = []
  skip_newlines
  loop do
    break if check(:EOF)
    break if stop_types && stop_types.include?(current.type)

    stmts << parse_statement
    skip_newlines
  end
  stmts
end