mirror of
https://github.com/samsonjs/csc360-a1-shell.git
synced 2026-03-25 08:45:52 +00:00
76 lines
1.8 KiB
Ruby
76 lines
1.8 KiB
Ruby
require "shell/quote_cursor"
|
|
|
|
module Shell
|
|
class StringParser
|
|
class << self
|
|
def split_commands(line)
|
|
commands = []
|
|
command = +""
|
|
cursor = QuoteCursor.new
|
|
next_op = :always
|
|
i = 0
|
|
|
|
while i < line.length
|
|
c = line[i]
|
|
if cursor.unquoted?
|
|
case c
|
|
when ";"
|
|
commands << {command: command, op: next_op}
|
|
command = +""
|
|
next_op = :always
|
|
i += 1
|
|
next
|
|
when "&"
|
|
if line[i + 1] == "&"
|
|
if command.strip.empty?
|
|
raise ArgumentError, "syntax error near unexpected token `&&`"
|
|
end
|
|
commands << {command: command, op: next_op}
|
|
command = +""
|
|
next_op = :and
|
|
i += 2
|
|
next
|
|
end
|
|
end
|
|
end
|
|
|
|
segment, i = cursor.consume(line, i)
|
|
command << segment
|
|
end
|
|
|
|
if next_op == :and && command.strip.empty?
|
|
raise ArgumentError, "syntax error: expected command after `&&`"
|
|
end
|
|
|
|
commands << {command: command, op: next_op}
|
|
commands
|
|
end
|
|
|
|
def read_dollar_paren(line, start_index)
|
|
output = +""
|
|
i = start_index
|
|
depth = 1
|
|
cursor = QuoteCursor.new
|
|
|
|
while i < line.length
|
|
c = line[i]
|
|
|
|
if cursor.unquoted?
|
|
case c
|
|
when "("
|
|
depth += 1
|
|
when ")"
|
|
depth -= 1
|
|
return [output, i + 1] if depth.zero?
|
|
end
|
|
end
|
|
|
|
segment, i = cursor.consume(line, i)
|
|
output << segment
|
|
end
|
|
|
|
raise ArgumentError, "Unmatched $(...)"
|
|
end
|
|
end
|
|
end
|
|
end
|