# File lib/crokus/parser.rb, line 1058 def primary case showNext.kind when :ident return Ident.new(acceptIt) when :integer_lit return IntLit.new(acceptIt) when :float_lit return FloatLit.new(acceptIt) when :string_lit return StrLit.new(acceptIt) when :char_lit return CharLit.new(acceptIt) when :lparen acceptIt e=expression expect :rparen return Parenth.new(e) when :lbrace return array_or_struct_init() end end
class Crokus::Parser
Constants
- ASSIGN_OP
- STARTERS_ABSTRACT_DECLARATOR
abstract_declarator
: pointer | direct_abstract_declarator | pointer direct_abstract_declarator ;
- STARTERS_ARRAY_OR_STRUCT_INIT
- STARTERS_PRIMARY
- STARTERS_TYPE_QUALIFIER
pointer
: '*' | '*' type_qualifier_list | '*' pointer | '*' type_qualifier_list pointer ;
- STARTERS_TYPE_SPECIFIER
- STARTERS_UNARY
- UNARY_OP
Attributes
str[RW]
tokens[RW]
Public Class Methods
new()
click to toggle source
# File lib/crokus/parser.rb, line 15 def initialize @ppr=PrettyPrinter.new @verbose=false #@verbose=true end
Public Instance Methods
abstract_decl()
click to toggle source
# File lib/crokus/parser.rb, line 931 def abstract_decl indent "abstract_decl" if showNext.is? STARTERS_ABSTRACT_DECLARATOR case showNext.kind when :mul pointer else direct_abstract_declarator end else raise "ERROR : in abstract_declarator. Expecting one of #{STARTERS_ABSTRACT_DECLARATOR}" end dedent end
acceptIt()
click to toggle source
# File lib/crokus/parser.rb, line 21 def acceptIt say showNext.kind.to_s+" "+showNext.val tokens.shift end
additive()
click to toggle source
# File lib/crokus/parser.rb, line 790 def additive indent "addititve : #{showNext}" e1=multitive while showNext.is? [:add,:sub] op=acceptIt e2=multitive e1=Binary.new(e1,op,e2) end dedent e1 end
andexp()
click to toggle source
# File lib/crokus/parser.rb, line 742 def andexp indent "andexp : #{showNext}" e1=eqexp while showNext.is? :and op=acceptIt e2=eqexp e1=Binary.new(e1,op,e2) end dedent e1 end
argument_expr_list()
click to toggle source
# File lib/crokus/parser.rb, line 1080 def argument_expr_list list=[] list << expression while showNext.is? :comma acceptIt list << expression end list end
array_or_struct_init()
click to toggle source
# File lib/crokus/parser.rb, line 1090 def array_or_struct_init indent "array_or_struct_init" expect :lbrace elements=[] while !showNext.is? :rbrace elements << (e=expression) if showNext.is? :comma acceptIt end end expect :rbrace dedent return ArrayOrStructInit.new(elements) end
arrayed?(type)
click to toggle source
# File lib/crokus/parser.rb, line 436 def arrayed?(type) return if tokens.empty? while showNext.is? :lbrack acceptIt if showNext.is? :rbrack acceptIt type=ArrayOf.new(type,IntLit.new(ZERO)) else e=expression type=ArrayOf.new(type,e) expect :rbrack end end return type end
assign()
click to toggle source
# File lib/crokus/parser.rb, line 668 def assign indent "assign : #{showNext}" e1=cond_expr while showNext.is? ASSIGN_OP op=acceptIt e2=assign e1=Assign.new(e1,op,e2) end dedent return e1 end
castexp()
click to toggle source
# File lib/crokus/parser.rb, line 814 def castexp indent "castexpr : #{showNext}" case showNext.kind when :lparen # parenth expr OR casting ! res=is_casting? if res e=casting else e=parenthesized end else e=unary end dedent return e end
casting()
click to toggle source
def is_casting?
i=0 tok=DUMMY while tok.kind!=:rparen tok=@tokens[i] i+=1 end pp tok=@tokens[i] return false if tok.is? [:mul,:add,:sub] pp cond=STARTERS_UNARY-STARTERS_ARRAY_OR_STRUCT_INIT return true if tok.is? cond return false
end
# File lib/crokus/parser.rb, line 870 def casting puts "casting : #{showNext}" if $options[:verbose] expect :lparen t=parse_type expect :rparen u=unary CastedExpr.new(t,u) end
cond_expr()
click to toggle source
# File lib/crokus/parser.rb, line 680 def cond_expr indent "cond_expr : #{showNext}" e1=logor while showNext.is? :qmark acceptIt e2=expression expect :colon e3=cond_expr e1=CondExpr.new(e1,e2,e3) end dedent return e1 end
dbg_print(node)
click to toggle source
# File lib/crokus/parser.rb, line 61 def dbg_print node puts "debug ast node".center(60,'-') puts node.accept(@ppr) puts "-"*60 end
dbg_print_next(n)
click to toggle source
# File lib/crokus/parser.rb, line 57 def dbg_print_next n pp tokens[0..n-1].collect{|tok| tok.inspect} end
debug()
click to toggle source
declaration()
click to toggle source
int a int * a int a=1,b=2; int a[] int* f() struct name *ptr; paire_t paire = {1,2}; int a,b,*c
# File lib/crokus/parser.rb, line 389 def declaration ret=[] @current_type=type=parse_type() d=declarator() a=arrayed?(type) if a type=a end func=parenthesized? if func func.type=type ret << func #func return ret end init=initialization? ret << Decl.new(type,d,init) while tokens.any? and showNext.is?(:comma) acceptIt ptr=pointed? if ptr type2=PointerTo.new(type) end d2=declarator a2=arrayed?(type) i2=initialization? ret << Decl.new(type2||type,d2) end if tokens.any? maybe :semicolon end return ret end
declarator()
click to toggle source
# File lib/crokus/parser.rb, line 422 def declarator if showNext.is? :ident ret=@current_ident=Ident.new(acceptIt) end return ret end
define()
click to toggle source
# File lib/crokus/parser.rb, line 152 def define indent "define" expect :sharp expect :ident #define name=expect :ident args=[] if showNext.is? :lparen acceptIt while !showNext.is?(:rparen) args << acceptIt if showNext.is?(:comma) acceptIt end end expect :rparen end e=expression() dedent return Define.new(name,args,e) end
design_unit()
click to toggle source
# File lib/crokus/parser.rb, line 109 def design_unit indent "designUnit" du=DesignUnit.new while tokens.any? case showNext.kind when :sharp case showNext(2).val when "include" du << include() when "define" du << define() end else du << declaration maybe :semicolon if tokens.any? end end dedent du.list.flatten! return du end
direct_abstract_declarator()
click to toggle source
# File lib/crokus/parser.rb, line 967 def direct_abstract_declarator raise end
do_while()
click to toggle source
# File lib/crokus/parser.rb, line 325 def do_while indent "do_while" expect :do body=statement() expect :while e=expression dedent DoWhile.new(e,body) end
eqexp()
click to toggle source
# File lib/crokus/parser.rb, line 754 def eqexp indent "eqexp : #{showNext}" e1=relexp while showNext.is? [:eq,:neq] op=acceptIt e2=relexp e1=Binary.new(e1,op,e2) end dedent e1 end
exclor()
click to toggle source
# File lib/crokus/parser.rb, line 730 def exclor indent "exclor : #{showNext}" e1=andexp while showNext.is? :xor op=acceptIt e2=andexp e1=Binary.new(e1,op,e2) end dedent e1 end
expect(kind)
click to toggle source
# File lib/crokus/parser.rb, line 30 def expect kind if ((actual=tokens.shift).kind)!=kind puts "ERROR :" show_line(actual.pos) raise "expecting '#{kind}'. Received '#{actual.val}' around #{actual.pos}" end say actual.kind.to_s+" "+actual.val return actual end
expression()
click to toggle source
expression_statement()
click to toggle source
# File lib/crokus/parser.rb, line 636 def expression_statement if showNext.is? :semicolon acceptIt else e=expression expect :semicolon return e end end
func_formal_arg()
click to toggle source
# File lib/crokus/parser.rb, line 232 def func_formal_arg @current_type=type=parse_type() d=declarator a=arrayed?(type) if a type=a end return FormalArg.new(type,d) end
function_body()
click to toggle source
# File lib/crokus/parser.rb, line 242 def function_body indent "function_body" body=Body.new expect :lbrace while showNext.kind!=:rbrace s=statement() body << s if s end expect :rbrace dedent return body end
function_decl(name,type_)
click to toggle source
# File lib/crokus/parser.rb, line 202 def function_decl name,type_ indent "function" args=function_formal_args() case showNext.kind when :semicolon acceptIt ret =FunctionProto.new(name,type_,args) else body=function_body() ret= Function.new(name,type_,args,body) end dedent return ret end
function_formal_args()
click to toggle source
# File lib/crokus/parser.rb, line 217 def function_formal_args indent "function_formal_args" args=[] expect :lparen while !showNext.is? :rparen args << func_formal_arg() if !showNext.is? :rparen expect :comma end end expect :rparen dedent return args end
inclor()
click to toggle source
# File lib/crokus/parser.rb, line 718 def inclor indent "inclor : #{showNext}" e1=exclor while showNext.is? :or op=acceptIt e2=exclor e1=Binary.new(e1,op,e2) end dedent e1 end
include()
click to toggle source
# File lib/crokus/parser.rb, line 131 def include indent "include" expect :sharp expect :ident #include case showNext.kind when :lt acceptIt id1=expect :ident expect :dot id2=expect :ident expect :gt name=Token.new [:ident,id1.val+"."+id2.val,id1.pos] env=:env when :string_lit name=acceptIt env=:local end dedent return Include.new(name,env) end
initialization?()
click to toggle source
# File lib/crokus/parser.rb, line 452 def initialization? return if tokens.empty? if showNext.is? :assign expect :assign e=expression return e end end
is_casting?()
click to toggle source
# File lib/crokus/parser.rb, line 849 def is_casting? #puts "is_casting? : #{pp @tokens[0..1]}" cond1= @tokens[0].is?(:lparen) cond2= @tokens[1].is?([:int,:uint,:short,:byte,:float,:long,:double]) cond1 and cond2 end
linearize_comma_stmt(ary)
click to toggle source
# File lib/crokus/parser.rb, line 1047 def linearize_comma_stmt ary ary.collect do |stmt| case stmt when CommaStmt stmt.to_list else stmt end end.flatten end
logand()
click to toggle source
# File lib/crokus/parser.rb, line 706 def logand indent "logand : #{showNext}" e1=inclor while showNext.is? :andand op=acceptIt e2=inclor e1=Binary.new(e1,op,e2) end dedent e1 end
logor()
click to toggle source
# File lib/crokus/parser.rb, line 694 def logor indent "logor : #{showNext}" e1=logand while showNext.is? :oror op=acceptIt e2=logand e1=Binary.new(e1,op,e2) end dedent return e1 end
lookahead(n=2)
click to toggle source
# File lib/crokus/parser.rb, line 44 def lookahead(n=2) tokens[n] if tokens.any? end
maybe(kind)
click to toggle source
# File lib/crokus/parser.rb, line 26 def maybe kind return acceptIt if showNext.is? kind end
multitive()
click to toggle source
# File lib/crokus/parser.rb, line 802 def multitive indent "multitive : #{showNext}" e1=castexp while showNext.is? [:mul,:div,:mod] op=acceptIt e2=castexp e1=Binary.new(e1,op,e2) end dedent e1 end
parenthesized()
click to toggle source
# File lib/crokus/parser.rb, line 879 def parenthesized indent "parenthesized : #{showNext}" expect :lparen e=expression expect :rparen dedent return Parenth.new(e) end
parenthesized?()
click to toggle source
# File lib/crokus/parser.rb, line 461 def parenthesized? return if tokens.empty? if showNext.is? :lparen f=function_decl(@current_ident,@current_type) return f end end
parse(str)
click to toggle source
.….….… parsing methods .….……
# File lib/crokus/parser.rb, line 67 def parse str begin @str=str @tokens=Lexer.new.tokenize(str) #pp @tokens @tokens=@tokens.reject{|tok| tok==[nil,nil,nil]} @tokens=remove_comments() warnings=@tokens.select{|tok| tok.is? :lexer_warning} show_lexer_warnings(warnings) @tokens=@tokens.select{|tok| !tok.is? [:newline]} ast=design_unit() rescue Exception => e puts "PARSING ERROR : #{e}" puts "in C source at line/col #{showNext.pos}" puts e.backtrace abort end end
parseLoopCond()
click to toggle source
# File lib/crokus/parser.rb, line 612 def parseLoopCond indent "parseLoopCond" e=expression() dedent return e end
parseLoopEnd()
click to toggle source
# File lib/crokus/parser.rb, line 619 def parseLoopEnd indent "parseLoopEnd" s=statement() dedent return s end
parseLoopInit()
click to toggle source
# File lib/crokus/parser.rb, line 604 def parseLoopInit indent "parseLoopInit" ret=statement() dedent return [ret] # because for (int a,b=0;i<10;i++) is also possible. # then parser returns an array of Decl end
parse_body()
click to toggle source
# File lib/crokus/parser.rb, line 626 def parse_body body=Body.new expect :lbrace while !showNext.is? :rbrace body << statement() end expect :rbrace return body end
parse_else()
click to toggle source
# File lib/crokus/parser.rb, line 553 def parse_else indent "parse else" expect :else ret=Else.new stmt=statement() case stmt when Body ret.body=stmt else ret.body=Body.new([stmt]) end dedent return ret end
parse_for()
click to toggle source
# File lib/crokus/parser.rb, line 583 def parse_for indent "parse_for" forloop=For.new expect :for expect :lparen forloop.init << expression_statement forloop.cond = expression() expect :semicolon forloop.increment=expression() expect :rparen stmt=statement() case stmt when Body forloop.body=stmt else forloop.body=Body.new([stmt]) end dedent forloop end
parse_goto()
click to toggle source
# File lib/crokus/parser.rb, line 317 def parse_goto indent "goto" expect :goto #label id=expect(:ident) dedent Goto.new(id) end
parse_if()
click to toggle source
# File lib/crokus/parser.rb, line 526 def parse_if indent "parse_if" expect :if if showNext.is? :lparen # helps wrt casting. acceptIt lparen=true end cond=expression() expect :rparen if lparen body=Body.new if showNext.is? :lbrace lbrace=acceptIt end body << statement() if lbrace until showNext.is? :rbrace body << statement end expect :rbrace end if showNext.is? :else else_=parse_else() end dedent return If.new(cond,body,else_) end
parse_label()
click to toggle source
# File lib/crokus/parser.rb, line 311 def parse_label id=expect(:ident) expect(:colon) Ident.new(id) end
parse_return()
click to toggle source
# File lib/crokus/parser.rb, line 367 def parse_return indent "parse_return" expect :return unless showNext.is? :semicolon e=expression end dedent Return.new(e) end
parse_struct()
click to toggle source
# File lib/crokus/parser.rb, line 173 def parse_struct indent "struct" expect :struct name=nil if showNext.is? :ident name=acceptIt end ret=Struct.new(name) if showNext.is? :lbrace acceptIt while !showNext.is? :rbrace ret.decls << declaration() end ret.decls.flatten! expect :rbrace end dedent return ret end
parse_type()
click to toggle source
# File lib/crokus/parser.rb, line 469 def parse_type indent "parse_type" ret=Type.new(nil) ret.precisions << spec_qualifier?() # const, volatile if showNext.is? [:signed,:unsigned] ret.precisions << acceptIt end case showNext.kind when :ident,:char,:int,:short,:long,:float,:double,:void ret.name=acceptIt while showNext.is? [:char,:int,:short,:long,:float,:double,:void] ret.precisions << ret.name ret.name=acceptIt end ret.precisions.flatten! when :struct ret=parse_struct() when :typedef ret=typedef() else raise "Parsing ERROR in type declaration: '#{showNext}' #{showNext.pos}" end while showNext.is? [:mul,:lparen] case showNext.kind when :mul acceptIt ret=PointerTo.new(ret) when :lparen acceptIt if showNext.is? :rparen acceptIt else expression expect :rparen end end end dedent return ret end
parse_while()
click to toggle source
# File lib/crokus/parser.rb, line 568 def parse_while indent "parse_while" expect :while cond=expression() stmt=statement() case stmt when Body body=stmt else body=Body.new([stmt]) end dedent return While.new(cond,body) end
pointed?()
click to toggle source
# File lib/crokus/parser.rb, line 429 def pointed? return if tokens.empty? while showNext.is? :mul acceptIt end end
pointer()
click to toggle source
# File lib/crokus/parser.rb, line 953 def pointer expect :mul while showNext.is? STARTERS_TYPE_QUALIFIER+[:mul] case showNext.kind when :volatile acceptIt when :const acceptIt when :mult acceptIt end end end
postfix()
click to toggle source
# File lib/crokus/parser.rb, line 1012 def postfix indent "postfix : #{showNext}" e1=primary while showNext.is? [:lbrack,:lparen,:dot,:inc_op,:dec_op,:ptr_op] case showNext.kind when :lbrack acceptIt e2=expression expect :rbrack e1=Indexed.new(e1,e2) when :lparen acceptIt args=[] if !showNext.is? :rparen args=argument_expr_list end expect :rparen args=linearize_comma_stmt(args) e1=FunCall.new(e1,args) when :dot acceptIt e2=Ident.new(expect :ident) e1=Dotted.new(e1,e2) when :ptr_op op=acceptIt expect :ident when :inc_op,:dec_op op=acceptIt e1=PostFixAccu.new(e1,op) end end dedent e1 end
primary()
click to toggle source
relexp()
click to toggle source
# File lib/crokus/parser.rb, line 766 def relexp indent "relexp : #{showNext}" e1=shiftexp while showNext.is? [:lte,:lt,:gte,:gt ] op=acceptIt e2=shiftexp e1=Binary.new(e1,op,e2) end dedent e1 end
remove_comments()
click to toggle source
# File lib/crokus/parser.rb, line 92 def remove_comments ret=[] in_comment=false tokens.each do |tok| case tok.kind when :comment when :lcomment in_comment=true when :rcomment in_comment=false else ret << tok unless in_comment end end ret end
shiftexp()
click to toggle source
# File lib/crokus/parser.rb, line 778 def shiftexp indent "shiftexp : #{showNext}" e1=additive while showNext.is? [:shift_l,:shift_r] op=acceptIt e2=additive e1=Binary.new(e1,op,e2) end dedent e1 end
showNext(n=1)
click to toggle source
# File lib/crokus/parser.rb, line 40 def showNext(n=1) tokens[n-1] if tokens.any? end
show_lexer_warnings(warnings)
click to toggle source
# File lib/crokus/parser.rb, line 86 def show_lexer_warnings warnings warnings.each do |warn| puts "lexer warning : #{warn.val} at #{warn.pos}" end end
show_line(pos)
click to toggle source
# File lib/crokus/parser.rb, line 48 def show_line pos l,c=*pos show_lines(str,l-2) line=str.split(/\n/)[l-1] pointer="-"*(5+c)+ "^" puts "#{l.to_s.ljust(5)}|#{line}" puts pointer end
sizeof()
click to toggle source
# File lib/crokus/parser.rb, line 997 def sizeof expect :sizeof case showNext.kind when :lparen acceptIt #e=typename e=parse_type expect :rparen else #e=unary e=expression end Sizeof.new(e) end
spec_qualifier?()
click to toggle source
# File lib/crokus/parser.rb, line 513 def spec_qualifier? list=[] while showNext.is? STARTERS_TYPE_QUALIFIER case showNext.kind when :volatile list << acceptIt when :const list << acceptIt end end list end
spec_qualifier_list()
click to toggle source
# File lib/crokus/parser.rb, line 898 def spec_qualifier_list indent "spec_qualifier_list #{showNext.inspect}" while showNext.is? STARTERS_TYPE_SPECIFIER+STARTERS_TYPE_QUALIFIER if showNext.is? STARTERS_TYPE_SPECIFIER list << type_specifier else list << type_qualifier end end dedent list end
statement(arg=nil)
click to toggle source
# File lib/crokus/parser.rb, line 255 def statement(arg=nil) indent "statement ...#{showNext.kind} #{showNext.pos.first}" case showNext.kind when :lbrace ret=parse_body() when :unsigned,:signed,:int,:short,:float,:double,:long,:char,:void ret=declaration() when :struct ret=declaration() when :if ret=parse_if() when :while ret=parse_while() when :for ret=parse_for() when :switch ret=switch() when :return ret=parse_return when :break acceptIt ret=Break.new when :continue acceptIt ret=Continue.new when :do ret=do_while() when :goto ret=parse_goto() when :ident case showNext(2).kind when :ident ret=declaration when :colon l=parse_label s=statement ret=LabeledStmt.new(l,s) else ret=expression_statement end when :const,:volatile ret=declaration() when :semicolon acceptIt #ret=expression_statement when :inc_op,:dec_op,:mul ret=expression_statement else show_line(showNext.pos) raise "unknown statement start at #{showNext.pos} .Got #{showNext.kind} #{showNext.val}" end maybe :semicolon dedent return ret end
switch()
click to toggle source
# File lib/crokus/parser.rb, line 335 def switch indent "switch" expect :switch expect :lparen e=expression ret=Switch.new(e,cases=[],default=nil) expect :rparen expect :lbrace while showNext.is? :case expect :case case_e=expression case_body=Body.new expect :colon while showNext.kind!=:rbrace and showNext.kind!=:case and showNext.kind!=:default case_body << statement() end cases << Case.new(case_e,case_body) end if showNext.is? :default acceptIt expect :colon default_body=Body.new while showNext.kind!=:rbrace default_body << statement() end ret.default=default_body end expect :rbrace dedent return ret end
type_specifier()
click to toggle source
# File lib/crokus/parser.rb, line 912 def type_specifier type=Type.new(nil,[]) indent "type_specifier #{showNext}" if showNext.is? STARTERS_TYPE_SPECIFIER ret=acceptIt type.name=ret else raise "ERROR : type_specifier. Expecting one of '#{STARTERS_TYPE_SPECIFIER}' at #{showNext.pos}" end dedent type end
typedef()
click to toggle source
# File lib/crokus/parser.rb, line 193 def typedef indent "typedef" expect :typedef type=parse_type() id=expect(:ident) dedent return Typedef.new(type,id) end
typename()
click to toggle source
# File lib/crokus/parser.rb, line 888 def typename indent "typename" type=specifier_qualifier while showNext.is? STARTERS_ABSTRACT_DECLARATOR list << abstract_decl end dedent list end
unary()
click to toggle source
# File lib/crokus/parser.rb, line 971 def unary if STARTERS_PRIMARY.include? showNext.kind u=postfix elsif showNext.is? [:and,:mul,:add,:sub,:tilde,:not] op=acceptIt e=castexp u=Unary.new(op,e) else case showNext.kind when :inc_op op=acceptIt u=unary u=PreFixAccu.new(op,u) when :dec_op op=acceptIt u=unary u=PreFixAccu.new(op,u) when :sizeof u=sizeof() else raise "not an unary. showNext : #{showNext}" end end return u end