From: Michael D. Lowis Date: Wed, 29 Jan 2020 04:06:16 +0000 (-0500) Subject: added member access and function calls X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=af913f05c15dbcf8ae2e424b4fc32440a2dc9fc0;p=proto%2Fsclpl-rb.git added member access and function calls --- diff --git a/compile.rb b/compile.rb index 9f3fdba..2cbbd44 100755 --- a/compile.rb +++ b/compile.rb @@ -20,6 +20,7 @@ module Ast Return = Struct.new(:type, :val) Var = Struct.new(:name, :type, :value) IfStmt = Struct.new(:cond, :br1, :br2) + Ident = Struct.new(:name) end BuiltinSyms = { @@ -57,7 +58,7 @@ class Lexer Tok = Struct.new(:text, :file, :pos, :type) SPACE = /([ \t\v\n\r]+|#.*\n)/ IDENT = /[_a-zA-Z][_a-zA-Z0-9]*/ - BRACES = /[\(\)\[\]\{\}]/ + BRACES = /[\(\)\[\]\{\}\.]/ OPERATORS = /[*\/=+-:\$]/ INTEGER = /[0-9]+/ STRING = /"(\\"|[^"])*"/ @@ -124,11 +125,13 @@ class Parser LVLNAMES = LEVELS.keys RULES = { + "." => { prefix: nil, infix: :access, level: :call }, "(" => { prefix: :grouping, infix: :func_call, level: :call }, "+" => { prefix: :unary, infix: :binary, level: :term }, "-" => { prefix: :unary, infix: :binary, level: :term }, "*" => { prefix: nil, infix: :binary, level: :factor }, "/" => { prefix: nil, infix: :binary, level: :factor }, + :ident => { prefix: :variable, infix: nil, level: :none }, :nil => { prefix: :constant, infix: nil, level: :none }, :bool => { prefix: :constant, infix: nil, level: :none }, :int => { prefix: :constant, infix: nil, level: :none }, @@ -292,13 +295,13 @@ class Parser return_statement() elsif matches(:if) if_statement() - elsif matches(:ident) - ident = expect(:ident) - if matches(":") - declaration(ident) - else - binary(ident) - end +# elsif matches(:ident) +# ident = expect(:ident) +# if matches(":") +# declaration(ident) +# else +# binary(ident) +# end else expression() end @@ -363,13 +366,27 @@ class Parser ast end + def access(left) + right = Ast::Ident.new(expect(:ident).text) + access = Ast::Apply.new(nil, ".", [left, right]) + if accept("(") + func_call(access) + else + access + end + end + + def variable() + Ast::Ident.new(@prev.text) + end + def constant() if (@prev.type == :int || @prev.type == :byte) val = @prev.text.to_i if @prev.type == :byte error("invalid byte value") if (val < 0 || val > 255) end - Ast::Val.new(Type::Int, ) + Ast::Val.new(Type::Int, nil) elsif (@prev.type == :string) Ast::Val.new("String", @prev.text) elsif (@prev.type == :nil) @@ -392,8 +409,13 @@ class Parser end def func_call(ast) + call = Ast::Apply.new(nil, ast, []) + while !matches(")") + call[:args] << expression() + expect(",") if !matches(")") + end expect(")") - Ast::Apply.new(nil, ast, []) + call end def unary() @@ -404,6 +426,7 @@ class Parser def nextLevel(tok) level = getRule(@prev)[:level] index = LVLNAMES.find_index(level) + error("unknown operator type '#{tok}'") if not index LVLNAMES[index + 1] end diff --git a/example.src b/example.src index bed21b6..a0024b4 100644 --- a/example.src +++ b/example.src @@ -1,28 +1,26 @@ module Main imports (X11, XSel, Posix) -cmd : [String] = true - -#[ "fetch", nil, nil ] +#cmd : [String] = true fetchsel(sel : String) { - foo : String = 123 - 1 + 1 - return 0 - if 1 { return 5 } else {} - if 1 {} else if 1 {} +# foo : String = 123 +# 1 + 1 +# return 0 +# if 1 { return 5 } else {} +# if 1 {} else if 1 {} +# cmd[1] = sel; + Posix.exec(cmd) +} -## cmd[1] = sel; -## Posix.exec(cmd) +main(args : [String]) : Int +{ +# x : X11.Config = 0 +# X11.init(x) +# X11.mkwin(x, 1, 1, X11.PropertyChangeMask) +# XSel.init(x) +# X11.loop(x, nil) +# return 0 } -# -#$main(args : array of String) : Int -#{ -## x : X11.Config = {} -## X11.init(&x) -## X11.mkwin(&x, 1, 1, X11.PropertyChangeMask) -## XSel.init(&x) -## X11.loop(&x, nil) -#} -# +