def self.parse(parser, scope)
if tok = parser.skipspaces and tok.type == :string and (tok.raw == 'volatile' or tok.raw == '__volatile__')
volatile = true
tok = parser.skipspaces
end
if not tok or tok.type != :punct or tok.raw != '('
ftok = tok
body = ''
if tok.type == :punct and tok.raw == '{'
loop do
raise ftok, 'unterminated asm block' if not tok = parser.lexer.readtok
break if tok.type == :punct and tok.raw == '}'
case tok.type
when :space; body << ' '
when :eol; body << "\n"
when :punct; body << tok.raw
when :quoted; body << CExpression.string_inspect(tok.value)
when :string
body << case tok.raw
when 'asm', '__asm', '__asm__'; "\n"
when '_emit'; 'db'
else tok.raw
end
end
end
elsif tok.type == :punct and tok.raw == '<'
raise ftok, 'bad asm heredoc' if not tok = parser.lexer.readtok or tok.type != :punct or tok.raw != '<'
delimiter = parser.lexer.readtok
if delimiter.type == :punct and delimiter.raw == '-'
skipspc = true
delimiter = parser.lexer.readtok
end
raise ftok, 'bad asm heredoc delim' if delimiter.type != :string or not tok = parser.lexer.readtok or tok.type != :eol
nl = true
loop do
raise ftok, 'unterminated heredoc' if not tok = parser.lexer.readtok
break if nl and tok.raw == delimiter.raw
raw = tok.raw
raw = "\n" if skipspc and tok.type == :eol
body << raw
nl = (tok.type == :eol and (raw[-1] == \n or raw[-1] == \r))
end
else
parser.lexer.unreadtok tok
loop do
break if not tok = parser.lexer.readtok or tok.type == :eol
case tok.type
when :space; body << ' '
when :punct
case tok.raw
when '}'
parser.lexer.unreadtok tok
break
else body << tok.raw
end
when :quoted; body << (body.empty? ? tok.value : CExpression.string_inspect(tok.value))
when :string
body << case tok.raw
when 'asm', '__asm', '__asm__'; "\n"
when '_emit'; 'db'
else tok.raw
end
end
end
end
return new(body, ftok, nil, nil, nil, volatile)
end
raise tok || parser, '"(" expected' if not tok or tok.type != :punct or tok.raw != '('
raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
body = tok
ret = new body.value, body
tok = parser.skipspaces
raise tok || parser, '":" or ")" expected' if not tok or tok.type != :punct or (tok.raw != ':' and tok.raw != ')')
if tok.raw == ':'
ret.output = []
raise parser if not tok = parser.skipspaces
while tok.type == :quoted
type = tok.value
raise tok, 'expr expected' if not var = CExpression.parse_value(parser, scope)
ret.output << [type, var]
raise tok || parser, '":" or "," or ")" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ',' and tok.raw != ')' and tok.raw != ':')
break if tok.raw == ':' or tok.raw == ')'
raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
end
end
if tok.raw == ':'
ret.input = []
raise parser if not tok = parser.skipspaces
while tok.type == :quoted
type = tok.value
raise tok, 'expr expected' if not var = CExpression.parse_value(parser, scope)
ret.input << [type, var]
raise tok || parser, '":" or "," or ")" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ',' and tok.raw != ')' and tok.raw != ':')
break if tok.raw == ':' or tok.raw == ')'
raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
end
end
if tok.raw == ':'
ret.clobber = []
raise parser if not tok = parser.skipspaces
while tok.type == :quoted
ret.clobber << tok.value
raise tok || parser, '"," or ")" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ',' and tok.raw != ')')
break if tok.raw == ')'
raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
end
end
raise tok || parser, '")" expected' if not tok or tok.type != :punct or tok.raw != ')'
ret.parse_attributes(parser)
parser.checkstatementend(tok)
ret
end