Guest User

Untitled

a guest
Jun 16th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rails 7.78 KB | None | 0 0
  1. require './parser.rb'
  2. require './lexer.rb'
  3. require './token.rb'
  4. require './ast.rb'
  5.  
  6. TokenType.new :LPAREN, /^[(]/m
  7. TokenType.new :RPAREN, /^[)]/m
  8. TokenType.new :SEPARATOR, /^[,;]/m
  9. TokenType.new(:FLOAT, /^[0-9]+\.[0-9]*(e[\+\-]?[0-9]+)?/m) {|value| value.to_f}
  10. TokenType.new(:INTEGER, /^[1-9][0-9]*/m) {|value| value.to_i}
  11. TokenType.new(:STRING, /^'(?:[^'\\]|\\.)*'/m) {|value| value[1, -1]}
  12. TokenType.new :OPERATOR, /^(\=\=|\!\=|and|not|or|[\+\-\/\*\^\<\>\=])/m
  13. TokenType.new :KEYWORD, /^(if|then|else|end|do|while|def|as|return|break|continue)/m
  14. TokenType.new :IDENT, /^[a-zA-Z_][a-zA-Z0-9_]*/m
  15.  
  16.  
  17. class OrangeParser < Parser
  18.  
  19.  def program
  20.    main = ProgramNode.new
  21.    while not peek_type == :EOF
  22.      if optional :KEYWORD, 'def'
  23.        main.functions << function_definition
  24.        next
  25.      else
  26.        main.statements << statement
  27.      end
  28.    end
  29.    main
  30.  end
  31.  
  32.  def function_definition
  33.    print 'enter function_definition ', @token, @stack,  "\n"
  34.    defn = definition
  35.    arguments = definition_list
  36.    function_block = statement_block 'end'
  37.    expect :KEYWORD, 'end'
  38.    return FunctionDefinitionNode.new defn, arguments, function_block
  39.    print 'exit function_definition ', @token, @stack,  "\n"
  40.  end
  41.  
  42.  def definition_list
  43.    expect_type :LPAREN
  44.    if optional_type :RPAREN
  45.      return []
  46.    end
  47.    definitions = [definition]
  48.    while optional_type :SEPARATOR
  49.      definitions << definition
  50.    end
  51.    expect_type :RPAREN
  52.    return definitions
  53.  end
  54.  
  55.  def definition
  56.    ident = expect_type :IDENT
  57.    expect :KEYWORD, 'as'
  58.    type = expect_type :IDENT
  59.    DefinitionNode.new ident.value, type.value
  60.  end
  61.  
  62.  def statement_block *end_token
  63.    if end_token.length == 0
  64.      end_token = ['end']
  65.    end
  66.    block = StatementBlockNode.new
  67.    while not end_token.include? @token.value
  68.      block << statement
  69.    end
  70.    block
  71.  end
  72.  
  73.  def statement
  74.    print 'enter statement ', @token, @stack,  "\n"
  75.    if optional :KEYWORD, 'if'
  76.      return if_statement
  77.  
  78.    elsif optional :KEYWORD, 'while'
  79.      return while_statement
  80.  
  81.    elsif optional :KEYWORD, 'return'
  82.      return ReturnStatementNode.new expression
  83.  
  84.    elsif optional :KEYWORD, 'contine'
  85.      return ContinueStatementNode.new
  86.  
  87.    elsif optional :KEYWORD, 'break'
  88.      return BreakStatementNode.new
  89.  
  90.    # because Orange has an ambiguous grammar, we need to use lookaheads here to determine
  91.    # whether we want to use the definition production or go on and parse as an expression
  92.  
  93.    elsif peek_type == :IDENT and lookahead(0).value == 'as'
  94.      return definition
  95.  
  96.    else
  97.      return expression
  98.  
  99.    end
  100.  
  101.  end
  102.  
  103.  def if_statement
  104.    print 'enter if_statement ', @token, @stack,  "\n"
  105.    condition = expression
  106.    expect :KEYWORD, 'then'
  107.    true_block = statement_block 'end', 'else'
  108.    if optional :KEYWORD, 'else'
  109.      false_block = statement_block
  110.    else
  111.      false_block = nil
  112.    end
  113.    expect :KEYWORD, 'end'
  114.    print 'exit if_statement ', @token, @stack,  "\n"
  115.    IfStatementNode.new condition, true_block, false_block
  116.  end
  117.  
  118.  def while_statement
  119.    print 'enter while_statement ', @token, @stack,  "\n"
  120.    condition = expression
  121.    expect :KEYWORD, 'do'
  122.    loop_block = statement_block 'end'
  123.    expect :KEYWORD, 'end'
  124.    print 'exit while_statement ', @token, @stack,  "\n"
  125.    WhileStatementNode.new condition, loop_block
  126.  end
  127.  
  128.  
  129.  def expression
  130.    # expression := logicand ('=' logicand)*
  131.    print 'enter expression ', @token, @stack,  "\n"
  132.    logicand
  133.    while optional :OPERATOR, '='
  134.      logicand
  135.      other = @stack.pop
  136.      @stack << AssignmentOpNode.new(@stack.pop, other)
  137.    end
  138.    print 'exit expression ', @token, @stack, "\n"
  139.    stack.pop
  140.  end
  141.  
  142.  def logicand
  143.    # logicand := comparand (('and'|'or') comparand)*
  144.    print 'enter logicand ', @token, @stack, "\n"
  145.    comparand
  146.    while operator = value_in('and', 'or')
  147.      comparand
  148.      other = @stack.pop
  149.      @stack << (operator == 'and' ? AndOpNode.new(@stack.pop, other) : OrOpNode.new(@stack.pop, other))
  150.    end
  151.    print 'exit logicand ', @token, @stack, "\n"
  152.  end
  153.  
  154.  def comparand
  155.    # comparand := summand (('<'| '>' | '==' | '!=') summand)*
  156.    print 'enter comparand ', @token, @stack, "\n"
  157.    summand
  158.    while operator = value_in('<', '>', '==', '!=')
  159.      summand
  160.      other = @stack.pop
  161.      case operator
  162.        when '<'
  163.          @stack << LessThanOpNode.new(@stack.pop, other)
  164.        when '>'
  165.          @stack << GreaterThanOpNode.new(@stack.pop, other)
  166.        when '=='
  167.          @stack << EqualToOpNode.new(@stack.pop, other)
  168.        when '!='
  169.          @stack << NotEqualToOpNode.new(@stack.pop, other)
  170.      end
  171.  
  172.    end
  173.    print 'exit comparand ', @token, @stack, "\n"
  174.  end
  175.  
  176.  def summand
  177.    print 'enter summand ', @token, @stack, "\n"
  178.    # summand := factor ('+'|'-' factor)*
  179.    term
  180.    while operator = value_in('+', '-')
  181.      term
  182.      other = @stack.pop
  183.      @stack << (operator == '+' ? AddOpNode.new(@stack.pop, other) : SubOpNode.new(@stack.pop, other))
  184.    end
  185.    print 'exit summand ', @token, @stack, "\n"
  186.  end
  187.  
  188.  def term
  189.    # term := exponent ('*'|'/' exponent)*
  190.    print 'enter term ', @token, @stack, "\n"
  191.    factor
  192.    while operator = value_in('*', '/')
  193.      factor
  194.      other = @stack.pop
  195.      @stack << (operator == '*' ? MulOpNode.new(@stack.pop, other) : DivOpNode.new(@stack.pop, other))
  196.    end
  197.    print 'exit term ', @token, @stack, "\n"
  198.  end
  199.  
  200.  def factor
  201.    # factor := prefix_operator ('^' prefix_operator)*
  202.    print 'enter factor ', @token, @stack, "\n"
  203.    exponent
  204.    while optional :OPERATOR, '^'
  205.      exponent
  206.      other = @stack.pop
  207.      @stack << ExpOpNode.new(@stack.pop, other)
  208.    end
  209.    print 'exit factor ', @token, @stack, "\n"
  210.  end
  211.  
  212.  def exponent
  213.    print 'enter exponent ', @token, @stack, "\n"
  214.    # exponent := ('-'|'not')? atom
  215.    if optional(:OPERATOR, '-')
  216.      atom
  217.      @stack << NegativeOpNode.new(@stack.pop)
  218.  
  219.    elsif optional(:OPERATOR, 'not')
  220.      atom
  221.      @stack << NotOpNode.new(@stack.pop)
  222.  
  223.    else
  224.      atom
  225.  
  226.    end
  227.    print 'exit exponent ', @token, @stack, "\n"
  228.  
  229.  end
  230.  
  231.  def atom
  232.    print 'enter atom ', @token, @stack, "\n"
  233.    # atom := integer | float | string | ident ('(' parameter_list ')')? | '(' expression ')'
  234.    if value = optional_type(:INTEGER)
  235.      @stack << IntegerNode.new(value)
  236.  
  237.    elsif value = optional_type(:FLOAT)
  238.      @stack << FloatNode.new(value)
  239.  
  240.    elsif value = optional_type(:STRING)
  241.      @stack << StringNode.new(value)
  242.  
  243.    elsif value = optional_type(:IDENT)
  244.      @stack << IdentNode.new(value)
  245.      if optional_type :LPAREN
  246.        function_call
  247.      end
  248.  
  249.    elsif optional_type(:LPAREN)
  250.      expression
  251.      expect :RPAREN, ')'
  252.  
  253.    elsif @token.value == ')'
  254.      return
  255.  
  256.    else
  257.      raise "Expected INTEGER, FLOAT, STRING or LPAREN, got #{@token}"
  258.  
  259.    end
  260.    print 'exit atom ', @token, @stack, "\n"
  261.  end
  262.  
  263.  def function_call
  264.    print 'enter function_call ', @token, @stack, "\n"
  265.    ident = @stack.pop
  266.    arguments = parameter_list
  267.    @stack << FunctionCallNode.new(ident, arguments)
  268.    print 'exit function_call ', @token, @stack, "\n"
  269.  end
  270.  
  271.  def parameter_list
  272.    if optional :RPAREN, ')'
  273.      return []
  274.    end
  275.    arguments = [expression]
  276.    while optional_type :SEPARATOR
  277.      arguments << expression
  278.    end
  279.    expect_type :RPAREN
  280.    arguments
  281.  end
  282.  
  283. end
  284.  
  285. #puts lexer.tokens, "\n"
  286.  
  287. code = %Q{
  288.  def fib as int(n as int)
  289.    if n < 2 then
  290.      return 1
  291.    else
  292.      return fib(n - 1) + fib(n - 2)
  293.    end
  294.  end
  295. }
  296.  
  297. puts code
  298.  
  299. lexer = LexicalAnalyser.new code
  300. puts lexer.tokenise
  301.  
  302.  
  303.  
  304. #parser = OrangeParser.new code
  305. #puts parser.program
Add Comment
Please, Sign In to add comment