Class: Termular::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/termular/parser.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(src) ⇒ Parser

Returns a new instance of Parser.



104
105
106
107
108
# File 'lib/termular/parser.rb', line 104

def initialize(src)
  @src = src
  @tokens = Lexer.lex! src
  @i = -1
end

Class Method Details

.parse!(src) ⇒ Object



100
101
102
# File 'lib/termular/parser.rb', line 100

def self.parse!(src)
  Parser.new(src).parse
end

Instance Method Details

#additive_expressionObject



158
159
160
161
162
163
164
165
166
167
# File 'lib/termular/parser.rb', line 158

def additive_expression
  expr = multiplicative_expression
  while [:PLUS, :MINUS].include? peek_token[0]
    case next_token[0]
    when :PLUS;   expr = AST::Add.new       left: expr, right: multiplicative_expression
    when :MINUS;  expr = AST::Subtract.new  left: expr, right: multiplicative_expression
    end
  end
  expr
end

#assert_type(token, *types) ⇒ Object



122
123
124
125
126
# File 'lib/termular/parser.rb', line 122

def assert_type(token, *types)
  unless types.include? token[0]
    raise SyntaxError, "Expected one of #{types.join ", "}, found #{token[0]}"
  end
end

#call_expressionObject



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/termular/parser.rb', line 189

def call_expression
  expr = unary_expression
  while peek_token[0] == :OPEN_BRACKET
    next_token
    args = []
    args << expression
    while peek_token[0] == :COMMA
      next_token
      args << expression
    end
    expr = AST::Call.new callee: expr, args: args
    assert_type next_token, :CLOSE_BRACKET
  end
  expr
end

#commandObject



138
139
140
141
142
143
144
145
146
# File 'lib/termular/parser.rb', line 138

def command
  assert_type next_token, :COMMAND
  case token[1]
  when "q";   AST::QuitCommand.new
  when "c";   AST::CartesianCommand.new expression: expression
  when "p";   AST::PolarCommand.new expression: expression
  when "opt"; option_command
  end
end

#expressionObject



154
155
156
# File 'lib/termular/parser.rb', line 154

def expression
  additive_expression
end

#multiplicative_expressionObject



169
170
171
172
173
174
175
176
177
178
# File 'lib/termular/parser.rb', line 169

def multiplicative_expression
  expr = power_expression
  while [:TIMES, :DIVIDE].include? peek_token[0]
    case next_token[0]
    when :TIMES;  expr = AST::Multiply.new  left: expr, right: power_expression
    when :DIVIDE; expr = AST::Divide.new    left: expr, right: power_expression
    end
  end
  expr
end

#next_tokenObject



118
119
120
# File 'lib/termular/parser.rb', line 118

def next_token
  @tokens[@i += 1]
end

#option_commandObject



148
149
150
151
152
# File 'lib/termular/parser.rb', line 148

def option_command
  assert_type next_token, :BAREWORD
  opt = token[1]
  AST::OptionCommand.new option: opt, expression: expression
end

#parseObject



128
129
130
131
132
133
134
135
136
# File 'lib/termular/parser.rb', line 128

def parse
  cmd = if peek_token[0] == :COMMAND
          command
        else
          AST::CartesianCommand.new expression: expression
        end
  assert_type next_token, :END
  cmd
end

#peek_tokenObject



114
115
116
# File 'lib/termular/parser.rb', line 114

def peek_token
  @tokens[@i + 1]
end

#power_expressionObject



180
181
182
183
184
185
186
187
# File 'lib/termular/parser.rb', line 180

def power_expression
  expr = call_expression
  if peek_token[0] == :POWER
    next_token
    expr = AST::Power.new left: expr, right: power_expression
  end
  expr
end

#tokenObject



110
111
112
# File 'lib/termular/parser.rb', line 110

def token
  @tokens[@i]
end

#unary_expressionObject



205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/termular/parser.rb', line 205

def unary_expression
  case next_token[0]
  when :MINUS;      AST::Negate.new expression: unary_expression
  when :BAREWORD;   AST::Variable.new name: token[1]
  when :NUMBER;     AST::Number.new number: token[1]
  when :OPEN_PAREN; expr = expression
                    assert_type next_token, :CLOSE_PAREN
                    expr
  else
    raise SyntaxError, "Unexpected #{token[0]}"
  end
end