start conditionals

This commit is contained in:
Torsten Ruger
2015-09-14 16:47:22 +03:00
parent 11a218449d
commit acf4046225
11 changed files with 225 additions and 119 deletions

View File

@ -59,9 +59,62 @@ module Ast
end
end
class TypedName < NameExpression
attr_reader :type
def initialize type , name
super(name)
@type = type.to_sym
end
def attributes
[:type, :name]
end
def inspect
"#{self.class.name}.new(#{type.inspect},#{name.inspect})"
end
def to_s
inspect
end
end
class VariableDefinition < TypedName
attr_reader :right
def initialize type , name , right
super(type , name)
@right = right
end
def attributes
super + [:right]
end
def inspect
self.class.name + ".new(" + type.inspect + "," + name.inspect + "," + right.inspect + ")"
end
def to_s
inspect
end
end
class VariableExpression < NameExpression
end
class AssignmentExpression < NameExpression
attr_reader :right
def initialize name, right
super(name)
@right = right
end
def attributes
super + [:right]
end
def inspect
self.class.name + ".new(" + name.inspect + "," + right.inspect + ")"
end
def to_s
"#{left} = #{right}"
end
end
class ModuleName < NameExpression
end

View File

@ -1,5 +1,5 @@
module Ast
class OperatorExpression < Expression
attr_reader :operator, :left, :right
@ -10,28 +10,11 @@ module Ast
[:operator, :left, :right]
end
def inspect
self.class.name + ".new(" + operator.inspect + ", " + left.inspect + "," + right.inspect + ")"
self.class.name + ".new(" + operator.inspect + ", " + left.inspect + "," + right.inspect + ")"
end
def to_s
"#{left} #{operator} #{right}"
end
end
class AssignmentExpression < Expression
attr_reader :left, :right
def initialize left, right
@left, @right = left, right
end
def attributes
[:left, :right]
end
def inspect
self.class.name + ".new(" + left.inspect + "," + right.inspect + ")"
end
def to_s
"#{left} = #{right}"
end
end
end

View File

@ -13,11 +13,6 @@ grammar BasicTypes
rule print /[[:print:]]/ end # Like [:graph:], but includes the space character
rule xdigit /[[:xdigit:]]/ end # Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)
# ruby is newline sensitive, so there is more whitespace footwork
# rule of thumb is that anything eats space behind it, but only blank, no newlines
# comments are also deliminatord, but also don't include the newline
rule deliminator blank* comment? end
rule linebreak (!blank space) end #define in regex terms for utf
rule comment #don't include the newline (which ends the comment)
@ -25,11 +20,11 @@ grammar BasicTypes
end
rule name_expression
(name:([a-z_] [a-zA-Z0-9_]*) deliminator) { Ast::NameExpression.new(capture(:name).to_str)}
(name:([a-z_] [a-zA-Z0-9_]*) space*) { Ast::NameExpression.new(capture(:name).to_str)}
end
rule module_name_expression
(name:([A-Z] [a-zA-Z0-9_]*) deliminator) { Ast::ModuleName.new(capture(:name).to_str)}
(name:([A-Z] [a-zA-Z0-9_]*) space*) { Ast::ModuleName.new(capture(:name).to_str)}
end
rule digits
@ -37,7 +32,7 @@ grammar BasicTypes
end
rule integer_expression
(digits deliminator) { Ast::IntegerExpression.new(to_str.to_i) }
(digits space*) { Ast::IntegerExpression.new(to_str.to_i) }
end
rule string_expression
@ -56,51 +51,51 @@ grammar BasicTypes
# operator symbols are separate in Opreators
rule left_parenthesis
'(' space?
'(' space*
end
rule right_parenthesis
')' space?
')' space*
end
rule left_brace
'{' space?
'{' space*
end
rule right_brace
'}' space?
'}' space*
end
rule left_bracket
'[' space?
'[' space*
end
rule right_bracket
']' space?
']' space*
end
rule association
"=>" space?
"=>" space*
end
rule comma
',' space?
',' space*
end
rule colon
':' space?
':' space*
end
rule semicolon
';' space?
';' space*
end
rule question_mark
'?' space?
'?' space*
end
rule excamation_mark
'!' space?
'!' space*
end
end

View File

@ -28,11 +28,6 @@ grammar Expression
call_site | basic_expression
end
rule expression
# (simple_return | while_do | conditional | operator_expression | call_site ) >> newline
(call_site ) newline
end
rule function_definition
keyword_def name:function_name parameter_list newline expressions_end newline
end

View File

@ -0,0 +1,37 @@
grammar Function
include Statement
rule more_typed_args
(comma typed_arg )* {
captures(:typed_arg).collect{|u| u.value }
}
end
rule typed_argument_list
(left_parenthesis typed_arg? more_typed_args right_parenthesis){
args = [ ]
args << capture(:typed_arg).value if capture(:typed_arg)
args += capture(:more_typed_args).value if capture(:more_typed_args)
args
}
end
rule call_site
(basic_expression "." name_expression argument_list space?) {
Ast::CallSiteExpression.new(capture(:name_expression).to_str ,
capture(:argument_list).value ,
capture(:basic_expression).value )
}
end
rule function_definition
keyword_def name:function_name parameter_list newline expressions_end newline
end
rule parameter_list
left_parenthesis parameter_list:( name:parameter? (comma name:parameter)* ) right_parenthesis
end
root call_site
end

View File

@ -1,37 +1,37 @@
grammar Keywords
include BasicTypes
rule keyword_begin 'begin' deliminator end
rule keyword_class 'class' deliminator end
rule keyword_def 'def' deliminator end
rule keyword_do 'do' deliminator end
rule keyword_else 'else' deliminator end
rule keyword_end 'end' deliminator end
rule keyword_if 'if' deliminator end
rule keyword_rescue 'rescue' deliminator end
rule keyword_return 'return' deliminator end
rule keyword_module 'module' deliminator end
rule keyword_unless 'unless' deliminator end
rule keyword_until 'until' deliminator end
rule keyword_while 'while' deliminator end
rule keyword_begin 'begin' space* end
rule keyword_class 'class' space* end
rule keyword_def 'def' space* end
rule keyword_do 'do' space* end
rule keyword_else 'else' space* end
rule keyword_end 'end' space* end
rule keyword_if 'if' end
rule keyword_rescue 'rescue' space* end
rule keyword_return 'return' space* end
rule keyword_module 'module' space* end
rule keyword_unless 'unless' space* end
rule keyword_until 'until' space* end
rule keyword_while 'while' space* end
rule keyword_nil
('nil' deliminator ){ Ast::NilExpression.new }
('nil' space* ){ Ast::NilExpression.new }
end
rule keyword_false
('false' deliminator) { Ast::FalseExpression.new }
('false' space*) { Ast::FalseExpression.new }
end
rule keyword_true
('true' deliminator) { Ast::TrueExpression.new }
('true' space*) { Ast::TrueExpression.new }
end
# this rule is just to make sure identifiers can't be keywords. Kind of duplication here, but we need the
# space in above rules, so just make sure to add any here too.
rule keyword ('begin' | 'def' | 'do' | 'else' | 'end' |
'false' | 'if' | 'rescue' | 'true' | 'nil' |
'unless' | 'until' | 'while') deliminator
'unless' | 'until' | 'while') space*
end
rule keyword_expression

View File

@ -1,39 +1,13 @@
#require_relative "basic_types"
#require_relative "compound_types"
#require_relative "tokens"
#require_relative "keywords"
#require_relative "control"
#require_relative "expression"
#require_relative "call_site"
#require_relative "function_definition"
#require_relative "module_definition"
#require_relative "operators"
require 'ast/expression'
module Parser
# obviously a work in progress !!
# We "compose" the parser from bits, divide and hopefully conquer
Citrus.require "parser/basic"
Citrus.require "parser/keywords"
Citrus.require "parser/expression"
Citrus.require "parser/statement"
# class Salama < output::Parser
# include BasicTypes
# include CompoundTypes
# include Tokens
# include Keywords
# include Control
# include Expression
# include CallSite
# include FunctionDefinition
# include Operators
# include ModuleDef
# rule(:root_body) {(module_definition | class_definition | function_definition | expression |
# operator_expression | call_site | basic_type | hash_constant | array_constant )}
# rule(:root) { root_body.repeat.as(:expression_list) }
# end
end

View File

@ -0,0 +1,58 @@
grammar Statement
include Expression
rule type
(typ:("int" | "ref") space*) { capture(:typ).to_s }
end
rule typed_arg
(type name_expression) {
Ast::TypedName.new(capture(:type).value , capture(:name_expression).value.name)
}
end
rule variable_definition
(typed_arg ("=" space* value_expression)?) {
type = capture(:typed_arg).value
value = capture(:value_expression) ? capture(:value_expression).value : nil
var = Ast::VariableDefinition.new(type.type , type.name , value)
}
end
rule assignment
(name_expression "=" space* value_expression){
Ast::AssignmentExpression.new( capture(:name_expression).value.name , capture(:value_expression).value)
}
end
rule conditional
(keyword_if left_parenthesis value_expression right_parenthesis
body
keyword_end) {
Ast::IfExpression.new( capture(:value_expression).value , capture(:body).value , nil)
}
end
rule while
keyword_while left_parenthesis value_expression right_parenthesis keyword_do
body
keyword_end
end
rule return
keyword_return value_expression newline
end
rule body
(statement+){
captures(:statement).collect{|u| u.value }
}
end
rule statement
conditional | while | return | variable_definition | assignment
end
root statement
end