unify grammar file

This commit is contained in:
Torsten Ruger 2015-09-14 17:15:14 +03:00
parent 114817602e
commit d0980265fd
9 changed files with 127 additions and 216 deletions

View File

@ -1,5 +1,5 @@
grammar BasicTypes grammar Bosl
# unicode generalized categories , according to regex ruby page # unicode generalized categories , according to regex ruby page
rule lower /[[:lower:]]/ end # Lowercase alphabetical character rule lower /[[:lower:]]/ end # Lowercase alphabetical character
@ -135,4 +135,107 @@ grammar BasicTypes
'!' space* '!' space*
end end
rule more_args
(comma basic_expression )* {
captures(:basic_expression).collect{|u| u.value }
}
end
rule argument_list
(left_parenthesis basic_expression? more_args right_parenthesis){
args = [ ]
args << capture(:basic_expression).value if capture(:basic_expression)
args += capture(:more_args).value if capture(:more_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 value_expression
call_site | basic_expression
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
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 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
end end

View File

@ -1,40 +0,0 @@
grammar Expression
include BasicTypes
rule more_args
(comma basic_expression )* {
captures(:basic_expression).collect{|u| u.value }
}
end
rule argument_list
(left_parenthesis basic_expression? more_args right_parenthesis){
args = [ ]
args << capture(:basic_expression).value if capture(:basic_expression)
args += capture(:more_args).value if capture(:more_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 value_expression
call_site | basic_expression
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 +0,0 @@
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

@ -5,8 +5,6 @@ module Parser
# obviously a work in progress !! # obviously a work in progress !!
Citrus.require "parser/basic" Citrus.require "parser/bosl"
Citrus.require "parser/expression"
Citrus.require "parser/statement"
end end

View File

@ -1,58 +0,0 @@
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

View File

@ -4,46 +4,16 @@ require_relative "setup"
module ParserHelper module ParserHelper
def self.included(base) def self.included(base)
base.send :include, InstanceMethods #provides helpers and setup # base.send :include, InstanceMethods #provides helpers and setup
base.send :extend, ClassMethods #gets the method creation going
end end
module InstanceMethods def setup
def setup @parser = Bosl
@parser = Keywords
end
# check that @input parses correctly to @input
def check_parse
is = @parser.parse(@input , :root => @root)
assert_equal @input , is
end
# check that @input parses and transforms to @output
def check_ast
syntax = @parser.parse(@input , :root => @root)
#puts is.inspect
assert_equal @output , syntax.value
end
end end
module ClassMethods def check rule = :root
# this creates test methods dynamically. For each test_* method we create parse = @parser.parse(@input , :root => rule)
# three test_*[ast/parse/transf] methods that in turn check the three phases. assert_equal @input , parse
# runnable_methods is called by minitest to determine which tests to run assert_equal @output , parse.value
def runnable_methods end
tests = []
public_instance_methods(true).grep(/^test_/).map(&:to_s).each do |test|
["ast" , "parse"].each do |what|
name = "#{test}_#{what}"
tests << name
self.send(:define_method, name ) do
send(test)
send("check_#{what}")
end
end
end
tests
end
end
end end

View File

@ -1,16 +1,8 @@
require_relative "../setup" require_relative "../parser_helper"
class TestBasic < MiniTest::Test class TestBasic < MiniTest::Test
#test basics and keyword expressions. Keywords includes BasicTypes #test basics and keyword expressions. Keywords includes BasicTypes
def setup include ParserHelper
@parser = BasicTypes
end
def check rule = :root
parse = @parser.parse(@input , :root => rule)
assert_equal @input , parse
assert_equal @output , parse.value
end
def test_true def test_true
@input = 'true ' @input = 'true '

View File

@ -1,39 +1,31 @@
require_relative "../parser_helper" require_relative "../parser_helper"
class TestCallSite < MiniTest::Test class TestCallSite < MiniTest::Test
include ParserHelper
def setup
@parser = Expression
end
def check
parse = @parser.parse(@input)
assert_equal @input , parse
assert_equal @output , parse.value
end
def test_single_self def test_single_self
@input = 'self.foo(42)' @input = 'self.foo(42)'
@output = Ast::CallSiteExpression.new :foo, [Ast::IntegerExpression.new(42)] @output = Ast::CallSiteExpression.new :foo, [Ast::IntegerExpression.new(42)]
check check :call_site
end end
def test_single_name def test_single_name
@input = 'my_my.foo(42)' @input = 'my_my.foo(42)'
@parse_output = {:receiver=>{:name=>"my_my"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]} @parse_output = {:receiver=>{:name=>"my_my"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::NameExpression.new("my_my")) @output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::NameExpression.new("my_my"))
check check :call_site
end end
def test_int_receiver def test_int_receiver
@input = '42.put()' @input = '42.put()'
@output = Ast::CallSiteExpression.new(:put, [] ,Ast::IntegerExpression.new(42)) @output = Ast::CallSiteExpression.new(:put, [] ,Ast::IntegerExpression.new(42))
check check :call_site
end end
def test_string_receiver def test_string_receiver
@input = '"hello".puts()' @input = '"hello".puts()'
@output = Ast::CallSiteExpression.new(:puts, [] ,Ast::StringExpression.new("hello")) @output = Ast::CallSiteExpression.new(:puts, [] ,Ast::StringExpression.new("hello"))
check check :call_site
end end
def test_call_site_2 def test_call_site_2
@ -41,7 +33,7 @@ class TestCallSite < MiniTest::Test
@output = Ast::CallSiteExpression.new :baz, @output = Ast::CallSiteExpression.new :baz,
[Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo") ] , [Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo") ] ,
Ast::NameExpression.new(:self) Ast::NameExpression.new(:self)
check check :call_site
end end
def test_call_site_3 def test_call_site_3
@ -51,7 +43,7 @@ class TestCallSite < MiniTest::Test
Ast::NameExpression.new("foo") , Ast::NameExpression.new("foo") ,
Ast::NameExpression.new("bar")] , Ast::NameExpression.new("bar")] ,
Ast::NameExpression.new(:self) Ast::NameExpression.new(:self)
check check :call_site
end end
end end

View File

@ -1,33 +1,24 @@
require_relative "../parser_helper" require_relative "../parser_helper"
class TestConditional < MiniTest::Test class TestConditional < MiniTest::Test
include ParserHelper
def setup
@parser = Statement
end
def check
parse = @parser.parse(@input)
assert_equal @input , parse
assert_equal @output , parse.value
end
def test_assignment def test_assignment
@input = "myvar = 42" @input = "myvar = 42"
@output = Ast::AssignmentExpression.new(:myvar,Ast::IntegerExpression.new(42)) @output = Ast::AssignmentExpression.new(:myvar,Ast::IntegerExpression.new(42))
check check :assignment
end end
def test_variable_declaration def test_variable_declaration
@input = "int myvar" @input = "int myvar"
@output = Ast::VariableDefinition.new(:int,:myvar,nil) @output = Ast::VariableDefinition.new(:int,:myvar,nil)
check check :variable_definition
end end
def test_variable_declaration_value def test_variable_declaration_value
@input = "int myvar = 42" @input = "int myvar = 42"
@output = Ast::VariableDefinition.new(:int,:myvar,Ast::IntegerExpression.new(42)) @output = Ast::VariableDefinition.new(:int,:myvar,Ast::IntegerExpression.new(42))
check check :variable_definition
end end
def test_if def test_if
@ -37,7 +28,7 @@ if( 1 )
end end
HERE HERE
@output = Ast::IfExpression.new(Ast::IntegerExpression.new(1), [Ast::VariableDefinition.new(:int,:num,Ast::IntegerExpression.new(42))],nil ) @output = Ast::IfExpression.new(Ast::IntegerExpression.new(1), [Ast::VariableDefinition.new(:int,:num,Ast::IntegerExpression.new(42))],nil )
check check :conditional
end end
def ttest_conditional_with_calls def ttest_conditional_with_calls