From: Michael D. Lowis Date: Fri, 31 Jan 2020 03:20:40 +0000 (-0500) Subject: added declaration parsing and scaffolding for array X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=c305ebd33e6d15c34af4a394ff65d7fcaefaf7c8;p=proto%2Fsclpl-rb.git added declaration parsing and scaffolding for array --- diff --git a/compile.rb b/compile.rb index dc048bb..1dec61f 100755 --- a/compile.rb +++ b/compile.rb @@ -75,9 +75,13 @@ class Lexer "else" => :else, } + attr_accessor :file + attr_accessor :data + def initialize(path) @file = path - @data = StringScanner.new(File.read(path)) + @text = File.read(path) + @data = StringScanner.new(@text) end def get_id_type(str) @@ -105,6 +109,10 @@ class Lexer Tok.new("EOF", @file, @data.pos, :eof) end end + + def linenum(tok = nil) + @text[0..(tok.pos || @data.pos)].count("\n") + 1 + end end class Parser @@ -127,6 +135,7 @@ class Parser RULES = { "." => { prefix: nil, infix: :access, level: :call }, + "[" => { prefix: nil, infix: :subscript, level: :call }, "(" => { prefix: :grouping, infix: :func_call, level: :call }, "+" => { prefix: :unary, infix: :binary, level: :term }, "-" => { prefix: :unary, infix: :binary, level: :term }, @@ -303,13 +312,8 @@ 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) + decl_or_expr() else expression() end @@ -345,6 +349,15 @@ class Parser var end + def decl_or_expr() + ident = Ast::Ident.new(expect(:ident).text) + if matches(":") + declaration(@prev) + else + parseNextLevel(ident, :none) + end + end + ####################################### # Expression Parsing ####################################### @@ -365,7 +378,11 @@ class Parser consume() prefixRule = getRule(@prev)[:prefix] error("error parsing expression") if not prefixRule - ast = send(prefixRule) + parseNextLevel(send(prefixRule), level) + end + + def parseNextLevel(left, level) + ast = left while keepGoing(level) consume() infixRule = getRule(@prev)[:infix] @@ -384,6 +401,18 @@ class Parser end end + def subscript(left) + right = expression() +# p right + ast = Ast::Apply.new(nil, "[", [left, right]) +# p ast + expect("]") + p peek() + ast = parseNextLevel(ast, :call) +# p ast + ast + end + def variable() Ast::Ident.new(@prev.text) end @@ -449,7 +478,7 @@ class Parser # Parsing Primitives ####################################### def error(str) - puts str + puts "#{@lex.file}:#{@lex.linenum(@next || @prev)}: #{str}" exit 1 end diff --git a/example.src b/example.src index f8a72d1..9aa2bd4 100644 --- a/example.src +++ b/example.src @@ -6,21 +6,21 @@ cmd : ?[String] = true fetchsel(sel : String) { # foo : String = 123 -# 1 + 1 -# return 0 # if 1 { return 5 } else {} # if 1 {} else if 1 {} -# 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) + cmd[1] = sel +# 1 + 1 +# Posix.exec(cmd) # return 0 } +#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 +#} +