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.



120
121
122
123
124
# File 'lib/termular/parser.rb', line 120

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

Class Method Details

.parse!(src) ⇒ Object



116
117
118
# File 'lib/termular/parser.rb', line 116

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

Instance Method Details

#additive_expressionObject



185
186
187
188
189
190
191
192
193
194
# File 'lib/termular/parser.rb', line 185

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



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

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

#call_expressionObject



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/termular/parser.rb', line 216

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



154
155
156
157
158
159
160
161
162
163
164
# File 'lib/termular/parser.rb', line 154

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

#expressionObject



181
182
183
# File 'lib/termular/parser.rb', line 181

def expression
  additive_expression
end

#multiplicative_expressionObject



196
197
198
199
200
201
202
203
204
205
# File 'lib/termular/parser.rb', line 196

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



134
135
136
# File 'lib/termular/parser.rb', line 134

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

#option_commandObject



175
176
177
178
179
# File 'lib/termular/parser.rb', line 175

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

#parseObject



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

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



130
131
132
# File 'lib/termular/parser.rb', line 130

def peek_token
  @tokens[@i + 1]
end

#power_expressionObject



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

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

#relationObject



166
167
168
169
170
171
172
173
# File 'lib/termular/parser.rb', line 166

def relation
  left = expression
  assert_type next_token, :LT, :LTE, :GT, :GTE
  op = token[0]
  right = expression
  { LT: AST::LessThan, LTE: AST::LessThanEqual, GT: AST::GreaterThan,
    GTE: AST::GreaterThanEqual }[op].new left: left, right: right
end

#tokenObject



126
127
128
# File 'lib/termular/parser.rb', line 126

def token
  @tokens[@i]
end

#unary_expressionObject



232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/termular/parser.rb', line 232

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