
LL(1) parser
Odaym
1 Likes0 Commentsruby#LL(1) parser as a solution for exercise 4.9 in "Compiler Construction: Principles and Practice" #String given is (a,(b,(2)),(c))$ #deduce the grammar ;) class Parser def initialize() @parsing_stack = [] @parsing_stack.push('$') @parsing_stack.push('lexp-seq') end def launch! introduction result = nil until result == :done print "> " user_response = gets.chomp result = parse(user_response) end @parsing_stack.inspect conclusion end def parse (input) output = "" counter = 0 puts "This is how your stack looks like: \n#{@parsing_stack.inspect}" input.each_char do |single_char| case single_char when '(' while @parsing_stack[-1] != single_char if @parsing_stack[-1] == 'lexp-seq' @parsing_stack.pop @parsing_stack.push('lexp-seq1','lexp') puts @parsing_stack.inspect elsif @parsing_stack[-1] == 'lexp' @parsing_stack.pop @parsing_stack.push('list') puts @parsing_stack.inspect elsif @parsing_stack[-1] == 'list' @parsing_stack.pop @parsing_stack.push(')','lexp-seq','(') puts @parsing_stack.inspect end end if @parsing_stack[-1] == single_char @parsing_stack.pop puts @parsing_stack.inspect output += single_char counter += 1 puts "read #{counter} characters so far" end when 'a','b','c' while @parsing_stack[-1] != 'identifier' if @parsing_stack[-1] == 'atom' @parsing_stack.pop @parsing_stack.push('identifier') puts @parsing_stack.inspect elsif @parsing_stack[-1] == 'lexp' @parsing_stack.pop @parsing_stack.push('atom') puts @parsing_stack.inspect elsif @parsing_stack[-1] == 'lexp-seq' @parsing_stack.pop @parsing_stack.push('lexp-seq1', 'lexp') puts @parsing_stack.inspect end end if @parsing_stack[-1] == 'identifier' @parsing_stack.pop puts @parsing_stack.inspect output += single_char counter += 1 puts "read #{counter} characters so far" end when '0'..'9' while @parsing_stack[-1] != 'number' if @parsing_stack[-1] == 'lexp' @parsing_stack.pop @parsing_stack.push('atom') puts @parsing_stack.inspect elsif @parsing_stack[-1] == 'atom' @parsing_stack.pop @parsing_stack.push('number') puts @parsing_stack.inspect elsif @parsing_stack[-1] == 'lexp-seq' @parsing_stack.pop @parsing_stack.push('lexp-seq1', 'lexp') puts @parsing_stack.inspect end end if @parsing_stack[-1] == 'number' @parsing_stack.pop puts @parsing_stack.inspect output += single_char counter += 1 puts "read #{counter} characters so far" end when ')' while @parsing_stack[-1] != single_char if @parsing_stack[-1] == 'lexp-seq1' @parsing_stack.pop puts @parsing_stack.inspect end end if @parsing_stack[-1] == ')' @parsing_stack.pop puts @parsing_stack.inspect output += single_char counter += 1 puts "read #{counter} characters so far" end when ',' while @parsing_stack[-1] != single_char if @parsing_stack[-1] == 'lexp-seq1' @parsing_stack.pop @parsing_stack.push('lexp-seq') @parsing_stack.push(',') puts @parsing_stack.inspect end end if @parsing_stack[-1] == ',' @parsing_stack.pop puts @parsing_stack.inspect output += single_char counter += 1 puts "read #{counter} characters so far" end when '$' while @parsing_stack[-1] != single_char if @parsing_stack[-1] == 'lexp-seq1' @parsing_stack.pop puts @parsing_stack.inspect end end if @parsing_stack[-1] == '$' @parsing_stack.pop output += single_char counter += 1 puts "read #{counter} characters so far" puts "#{output}" return :done end when "\s" else puts "\nInput not recognized!" end end end def introduction puts "\n<<< Welcome to the LL(1) Parser >>>\n" puts "This is an interactive LL(1) Parser for you to play with.\n\n" end def conclusion puts "\n<<< Goodbye and happy parsing! >>>" end end parser = Parser.new() parser.launch!