%%machine lex; # % fix highlighting
# # === BEFORE YOU START === # # Read the Ruby Hacking Guide chapter 11, available in English at # whitequark.org/blog/2013/04/01/ruby-hacking-guide-ch-11-finite-state-lexer/ # # Remember two things about Ragel scanners: # # 1) Longest match wins. # # 2) If two matches have the same length, the first # in source code wins. # # General rules of making Ragel and Bison happy: # # * `p` (position) and `@te` contain the index of the character # they're pointing to (“current”), plus one. `@ts` contains the index # of the corresponding character. The code for extracting matched token is: # # @source_buffer.slice(@ts…@te) # # * If your input is `foooooooobar` and the rule is: # # 'f' 'o'+ # # the result will be: # # foooooooobar # ^ ts=0 ^ p=te=9 # # * A Ragel lexer action should not emit more than one token, unless # you know what you are doing. # # * All Ragel commands (fnext, fgoto, …) end with a semicolon. # # * If an action emits the token and transitions to another state, use # these Ragel commands: # # emit($whatever) # fnext $next_state; fbreak; # # If you perform `fgoto` in an action which does not emit a token nor # rewinds the stream pointer, the parser's side-effectful, # context-sensitive lookahead actions will break in a hard to detect # and debug way. # # * If an action does not emit a token: # # fgoto $next_state; # # * If an action features lookbehind, i.e. matches characters with the # intent of passing them to another action: # # p = @ts - 1 # fgoto $next_state; # # or, if the lookbehind consists of a single character: # # fhold; fgoto $next_state; # # * Ragel merges actions. So, if you have `e_lparen = '(' %act` and # `c_lparen = '('` and a lexer action `e_lparen | c_lparen`, the result # will invoke the action `act`. # # e_something stands for “something with *e*mbedded action”. # # * EOF is explicit and is matched by `c_eof`. If you want to introspect # the state of the lexer, add this rule to the state: # # c_eof => do_eof; # # * If you proceed past EOF, the lexer will complain: # # NoMethodError: undefined method `ord' for nil:NilClass #
class Parser::Lexer
%% write data nofinal; # % ESCAPES = { ?a.ord => "\a", ?b.ord => "\b", ?e.ord => "\e", ?f.ord => "\f", ?n.ord => "\n", ?r.ord => "\r", ?s.ord => "\s", ?t.ord => "\t", ?v.ord => "\v", ?\\.ord => "\\" }.freeze REGEXP_META_CHARACTERS = Regexp.union(*"\\$()*+.<>?[]^{|}".chars).freeze RBRACE_OR_RBRACK = %w"} ]".freeze attr_reader :source_buffer attr_accessor :diagnostics attr_accessor :static_env attr_accessor :force_utf32 attr_accessor :cond, :cmdarg, :in_kwarg attr_accessor :tokens, :comments def initialize(version) @version = version @static_env = nil @tokens = nil @comments = nil reset end def reset(reset_state=true) # Ragel state: if reset_state # Unit tests set state prior to resetting lexer. @cs = self.class.lex_en_line_begin @cond = StackState.new('cond') @cmdarg = StackState.new('cmdarg') @cond_stack = [] @cmdarg_stack = [] end @force_utf32 = false # Set to true by some tests @source_pts = nil # @source as a codepoint array @p = 0 # stream position (saved manually in #advance) @ts = nil # token start @te = nil # token end @act = 0 # next action @stack = [] # state stack @top = 0 # state stack top pointer # Lexer state: @token_queue = [] @literal_stack = [] @eq_begin_s = nil # location of last encountered =begin @sharp_s = nil # location of last encountered # @newline_s = nil # location of last encountered newline @num_base = nil # last numeric base @num_digits_s = nil # starting position of numeric digits @num_suffix_s = nil # starting position of numeric suffix @num_xfrm = nil # numeric suffix-induced transformation @escape_s = nil # starting position of current sequence @escape = nil # last escaped sequence, as string @herebody_s = nil # starting position of current heredoc line # Ruby 1.9 ->() lambdas emit a distinct token if do/{ is # encountered after a matching closing parenthesis. @paren_nest = 0 @lambda_stack = [] # After encountering the closing line of <<~SQUIGGLY_HEREDOC, # we store the indentation level and give it out to the parser # on request. It is not possible to infer indentation level just # from the AST because escape sequences such as `\ ` or `\t` are # expanded inside the lexer, but count as non-whitespace for # indentation purposes. @dedent_level = nil # If the lexer is in `command state' (aka expr_value) # at the entry to #advance, it will transition to expr_cmdarg # instead of expr_arg at certain points. @command_state = false # True at the end of "def foo a:" @in_kwarg = false end def source_buffer=(source_buffer) @source_buffer = source_buffer if @source_buffer source = @source_buffer.source if defined?(Encoding) && source.encoding == Encoding::UTF_8 @source_pts = source.unpack('U*') else @source_pts = source.unpack('C*') end if @source_pts[0] == 0xfeff # Skip byte order mark. @p = 1 end else @source_pts = nil end end def encoding @source_buffer.source.encoding end LEX_STATES = { :line_begin => lex_en_line_begin, :expr_dot => lex_en_expr_dot, :expr_fname => lex_en_expr_fname, :expr_value => lex_en_expr_value, :expr_beg => lex_en_expr_beg, :expr_mid => lex_en_expr_mid, :expr_arg => lex_en_expr_arg, :expr_cmdarg => lex_en_expr_cmdarg, :expr_end => lex_en_expr_end, :expr_endarg => lex_en_expr_endarg, :expr_endfn => lex_en_expr_endfn, :expr_labelarg => lex_en_expr_labelarg, :interp_string => lex_en_interp_string, :interp_words => lex_en_interp_words, :plain_string => lex_en_plain_string, :plain_words => lex_en_plain_string, } def state LEX_STATES.invert.fetch(@cs, @cs) end def state=(state) @cs = LEX_STATES.fetch(state) end def push_cmdarg @cmdarg_stack.push(@cmdarg) @cmdarg =<EMAIL_ADDRESS>end def pop_cmdarg @cmdarg = @cmdarg_stack.pop end def push_cond @cond_stack.push(@cond) @cond =<EMAIL_ADDRESS>end def pop_cond @cond = @cond_stack.pop end def dedent_level # We erase @dedent_level as a precaution to avoid accidentally # using a stale value. dedent_level, @dedent_level = @dedent_level, nil dedent_level end # Return next token: [type, value]. def advance if @token_queue.any? return @token_queue.shift end # Ugly, but dependent on Ragel output. Consider refactoring it somehow. klass = self.class _lex_trans_keys = klass.send :_lex_trans_keys _lex_key_spans = klass.send :_lex_key_spans _lex_index_offsets = klass.send :_lex_index_offsets _lex_indicies = klass.send :_lex_indicies _lex_trans_targs = klass.send :_lex_trans_targs _lex_trans_actions = klass.send :_lex_trans_actions _lex_to_state_actions = klass.send :_lex_to_state_actions _lex_from_state_actions = klass.send :_lex_from_state_actions _lex_eof_trans = klass.send :_lex_eof_trans pe = @source_pts.size + 2 p, eof = @p, pe @command_state = (@cs == klass.lex_en_expr_value || @cs == klass.lex_en_line_begin) %% write exec; # % @p = p if @token_queue.any? @token_queue.shift elsif @cs == klass.lex_error [ false, [ '$error'.freeze, range(p - 1, p) ] ] else eof = @source_pts.size [ false, [ '$eof'.freeze, range(eof, eof) ] ] end end protected def eof_codepoint?(point) [0x04, 0x1a, 0x00].include? point end def version?(*versions) versions.include?(@version) end def stack_pop @top -= 1 @stack[@top] end if defined?(Encoding) def encode_escape(ord<EMAIL_ADDRESS>end else def encode_escape(ord) ord.chr end end def tok(s = @ts, e = @te) @source_buffer.slice(s...e) end def range(s = @ts, e = @te) Parser::Source::Range.new(@source_buffer, s, e) end def emit(type, value = tok, s = @ts, e = @te) token = [ type, [ value, range(s, e) ] ] @token_queue.push(token) @tokens.push(token) if @tokens token end def emit_table(table, s = @ts, e = @te) value = tok(s, e) emit(table[value], value, s, e) end def emit_do(do_block=false) if @cond.active? emit(:kDO_COND, 'do'.freeze) elsif @cmdarg.active? || do_block emit(:kDO_BLOCK, 'do'.freeze) else emit(:kDO, 'do'.freeze) end end def arg_or_cmdarg if @command_state self.class.lex_en_expr_cmdarg else self.class.lex_en_expr_arg end end def emit_comment(s = @ts, e = @te) if @comments @comments.push(Parser::Source::Comment.new(range(s, e))) end if @tokens @tokens.push([ :tCOMMENT, [ tok(s, e), range(s, e) ] ]) end nil end def diagnostic(type, reason, arguments=nil, location=range, highlights=[]) @diagnostics.process( Parser::Diagnostic.new(type, reason, arguments, location, highlights)) end # # === LITERAL STACK === # def push_literal(*args) new_literal = Literal.new(self, *args) @literal_stack.push(new_literal) if new_literal.words? && new_literal.backslash_delimited? if new_literal.interpolate? self.class.lex_en_interp_backslash_delimited_words else self.class.lex_en_plain_backslash_delimited_words end elsif new_literal.words? && !new_literal.backslash_delimited? if new_literal.interpolate? self.class.lex_en_interp_words else self.class.lex_en_plain_words end elsif !new_literal.words? && new_literal.backslash_delimited? if new_literal.interpolate? self.class.lex_en_interp_backslash_delimited else self.class.lex_en_plain_backslash_delimited end else if new_literal.interpolate? self.class.lex_en_interp_string else self.class.lex_en_plain_string end end end def literal @literal_stack.last end def pop_literal old_literal = @literal_stack.pop @dedent_level = old_literal.dedent_level if old_literal.type == :tREGEXP_BEG # Fetch modifiers. self.class.lex_en_regexp_modifiers else self.class.lex_en_expr_end end end # Mapping of strings to parser tokens. PUNCTUATION = { '=' => :tEQL, '&' => :tAMPER2, '|' => :tPIPE, '!' => :tBANG, '^' => :tCARET, '+' => :tPLUS, '-' => :tMINUS, '*' => :tSTAR2, '/' => :tDIVIDE, '%' => :tPERCENT, '~' => :tTILDE, ',' => :tCOMMA, ';' => :tSEMI, '.' => :tDOT, '..' => :tDOT2, '...' => :tDOT3, '[' => :tLBRACK2, ']' => :tRBRACK, '(' => :tLPAREN2, ')' => :tRPAREN, '?' => :tEH, ':' => :tCOLON, '&&' => :tANDOP, '||' => :tOROP, '-@' => :tUMINUS, '+@' => :tUPLUS, '~@' => :tTILDE, '**' => :tPOW, '->' => :tLAMBDA, '=~' => :tMATCH, '!~' => :tNMATCH, '==' => :tEQ, '!=' => :tNEQ, '>' => :tGT, '>>' => :tRSHFT, '>=' => :tGEQ, '<' => :tLT, '<<' => :tLSHFT, '<=' => :tLEQ, '=>' => :tASSOC, '::' => :tCOLON2, '===' => :tEQQ, '<=>' => :tCMP, '[]' => :tAREF, '[]=' => :tASET, '{' => :tLCURLY, '}' => :tRCURLY, '`' => :tBACK_REF2, '!@' => :tBANG, '&.' => :tANDDOT, } PUNCTUATION_BEGIN = { '&' => :tAMPER, '*' => :tSTAR, '**' => :tDSTAR, '+' => :tUPLUS, '-' => :tUMINUS, '::' => :tCOLON3, '(' => :tLPAREN, '{' => :tLBRACE, '[' => :tLBRACK, } KEYWORDS = { 'if' => :kIF_MOD, 'unless' => :kUNLESS_MOD, 'while' => :kWHILE_MOD, 'until' => :kUNTIL_MOD, 'rescue' => :kRESCUE_MOD, 'defined?' => :kDEFINED, 'BEGIN' => :klBEGIN, 'END' => :klEND, } KEYWORDS_BEGIN = { 'if' => :kIF, 'unless' => :kUNLESS, 'while' => :kWHILE, 'until' => :kUNTIL, 'rescue' => :kRESCUE, 'defined?' => :kDEFINED, } %w(class module def undef begin end then elsif else ensure case when for break next redo retry in do return yield super self nil true false and or not alias __FILE__ __LINE__ __ENCODING__).each do |keyword| KEYWORDS_BEGIN[keyword] = KEYWORDS[keyword] = :"k#{keyword.upcase}" end %%{ # % access @; getkey (@source_pts[p] || 0); # === CHARACTER CLASSES === # # Pay close attention to the differences between c_any and any. # c_any does not include EOF and so will cause incorrect behavior # for machine subtraction (any-except rules) and default transitions # for scanners. action do_nl { # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p } c_nl = '\n' $ do_nl; c_space = [ \t\r\f\v]; c_space_nl = c_space | c_nl; c_eof = 0x04 | 0x1a | 0 | zlen; # ^D, ^Z, \0, EOF c_eol = c_nl | c_eof; c_any = any - c_eof; c_nl_zlen = c_nl | zlen; c_line = any - c_nl_zlen; c_unicode = c_any - 0x00..0x7f; c_upper = [A-Z]; c_lower = [a-z_] | c_unicode; c_alpha = c_lower | c_upper; c_alnum = c_alpha | [0-9]; action do_eof { # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. fhold; fbreak; } # # === TOKEN DEFINITIONS === # # All operators are punctuation. There is more to punctuation # than just operators. Operators can be overridden by user; # punctuation can not. # A list of operators which are valid in the function name context, but # have different semantics in others. operator_fname = '[]' | '[]=' | '`' | '-@' | '+@' | '~@' | '!@' ; # A list of operators which can occur within an assignment shortcut (+ → +=). operator_arithmetic = '&' | '|' | '&&' | '||' | '^' | '+' | '-' | '*' | '/' | '**' | '~' | '<<' | '>>' | '%' ; # A list of all user-definable operators not covered by groups above. operator_rest = '=~' | '!~' | '==' | '!=' | '!' | '===' | '<' | '<=' | '>' | '>=' | '<=>' | '=>' ; # Note that `{` and `}` need to be referred to as e_lbrace and e_rbrace, # as they are ambiguous with interpolation `#{}` and should be counted. # These braces are not present in punctuation lists. # A list of punctuation which has different meaning when used at the # beginning of expression. punctuation_begin = '-' | '+' | '::' | '(' | '[' | '*' | '**' | '&' ; # A list of all punctuation except punctuation_begin. punctuation_end = ',' | '=' | '->' | '(' | '[' | ']' | '::' | '?' | ':' | '.' | '..' | '...' ; # A list of keywords which have different meaning at the beginning of expression. keyword_modifier = 'if' | 'unless' | 'while' | 'until' | 'rescue' ; # A list of keywords which accept an argument-like expression, i.e. have the # same post-processing as method calls or commands. Example: `yield 1`, # `yield (1)`, `yield(1)`, are interpreted as if `yield` was a function. keyword_with_arg = 'yield' | 'super' | 'not' | 'defined?' ; # A list of keywords which accept a literal function name as an argument. keyword_with_fname = 'def' | 'undef' | 'alias' ; # A list of keywords which accept an expression after them. keyword_with_value = 'else' | 'case' | 'ensure' | 'module' | 'elsif' | 'then' | 'for' | 'in' | 'do' | 'when' | 'begin' | 'class' | 'and' | 'or' ; # A list of keywords which accept a value, and treat the keywords from # `keyword_modifier` list as modifiers. keyword_with_mid = 'rescue' | 'return' | 'break' | 'next' ; # A list of keywords which do not accept an expression after them. keyword_with_end = 'end' | 'self' | 'true' | 'false' | 'retry' | 'redo' | 'nil' | 'BEGIN' | 'END' | '__FILE__' | '__LINE__' | '__ENCODING__'; # All keywords. keyword = keyword_with_value | keyword_with_mid | keyword_with_end | keyword_with_arg | keyword_with_fname | keyword_modifier ; constant = c_upper c_alnum*; bareword = c_alpha c_alnum*; call_or_var = c_lower c_alnum*; class_var = '@@' bareword; instance_var = '@' bareword; global_var = '$' ( bareword | digit+ | [`'+~*$&?!@/\\;,.=:<>"] # ` | '-' c_alnum ) ; # Ruby accepts (and fails on) variables with leading digit # in literal context, but not in unquoted symbol body. class_var_v = '@@' c_alnum+; instance_var_v = '@' c_alnum+; label = bareword [?!]? ':'; # # === NUMERIC PARSING === # int_hex = ( xdigit+ '_' )* xdigit* '_'? ; int_dec = ( digit+ '_' )* digit* '_'? ; int_bin = ( [01]+ '_' )* [01]* '_'? ; flo_int = [1-9] [0-9]* ( '_' digit+ )* | '0'; flo_frac = '.' ( digit+ '_' )* digit+; flo_pow = [eE] [+\-]? ( digit+ '_' )* digit+; int_suffix = '' % { @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } } | 'r' % { @num_xfrm = lambda { |chars| emit(:tRATIONAL, Rational(chars)) } } | 'i' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, chars)) } } | 'ri' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Rational(chars))) } }; flo_pow_suffix = '' % { @num_xfrm = lambda { |chars| emit(:tFLOAT, Float(chars)) } } | 'i' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Float(chars))) } }; flo_suffix = flo_pow_suffix | 'r' % { @num_xfrm = lambda { |chars| emit(:tRATIONAL, Rational(chars)) } } | 'ri' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Rational(chars))) } }; # # === ESCAPE SEQUENCE PARSING === # # Escape parsing code is a Ragel pattern, not a scanner, and therefore # it shouldn't directly raise errors or perform other actions with side effects. # In reality this would probably just mess up error reporting in pathological # cases, through. # The amount of code required to parse \M\C stuff correctly is ridiculous. escaped_nl = "\\" c_nl; action unicode_points { @escape = "" codepoints = tok(@escape_s + 2, p - 1) codepoint_s = @escape_s + 2 codepoints.split(/[ \t]/).each do |codepoint_str| codepoint = codepoint_str.to_i(16) if codepoint >= 0x110000 diagnostic :error, :unicode_point_too_large, nil, range(codepoint_s, codepoint_s + codepoint_str.length) break end @escape += codepoint.chr(Encoding::UTF_8) codepoint_s += codepoint_str.length + 1 end } action unescape_char { codepoint = @source_pts[p - 1] if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end } action invalid_complex_escape { diagnostic :fatal, :invalid_escape } action slash_c_char { @escape =<EMAIL_ADDRESS>& 0x9f) } action slash_m_char { @escape =<EMAIL_ADDRESS>| 0x80) } maybe_escaped_char = ( '\\' c_any %unescape_char | ( c_any - [\\] ) % { @escape = @source_buffer.slice(p - 1).chr } ); maybe_escaped_ctrl_char = ( # why?! '\\' c_any %unescape_char %slash_c_char | '?' % { @escape = "\x7f" } | ( c_any - [\\?] ) % { @escape = @source_buffer.slice(p - 1).chr } %slash_c_char ); escape = ( # \377 [0-7]{1,3} % { @escape = encode_escape(tok(@escape_s, p).to_i(8) % 0x100) } # \xff | 'x' xdigit{1,2} % { @escape = encode_escape(tok(@escape_s + 1, p).to_i(16)) } # \u263a | 'u' xdigit{4} % { @escape = tok(@escape_s + 1, p).to_i(16).chr(Encoding::UTF_8) } # %q[\x] | 'x' ( c_any - xdigit ) % { diagnostic :fatal, :invalid_hex_escape, nil, range(@escape_s - 1, p + 2) } # %q[\u123] %q[\u{12] | 'u' ( c_any{0,4} - xdigit{4} - # \u1234 is valid ( '{' xdigit{1,3} # \u{1 \u{12 \u{123 are valid | '{' xdigit [ \t}] any? # \u{1. \u{1} are valid | '{' xdigit{2} [ \t}] # \u{12. \u{12} are valid ) ) % { diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) } # \u{123 456} | 'u{' ( xdigit{1,6} [ \t] )* ( xdigit{1,6} '}' %unicode_points | ( xdigit* ( c_any - xdigit - '}' )+ '}' | ( c_any - '}' )* c_eof | xdigit{7,} ) % { diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) } ) # \C-\a \cx | ( 'C-' | 'c' ) escaped_nl? maybe_escaped_ctrl_char # \M-a | 'M-' escaped_nl? maybe_escaped_char %slash_m_char # \C-\M-f \M-\cf \c\M-f | ( ( 'C-' | 'c' ) escaped_nl? '\\M-' | 'M-\\' escaped_nl? ( 'C-' | 'c' ) ) escaped_nl? maybe_escaped_ctrl_char %slash_m_char | 'C' c_any %invalid_complex_escape | 'M' c_any %invalid_complex_escape | ( 'M-\\C' | 'C-\\M' ) c_any %invalid_complex_escape | ( c_any - [0-7xuCMc] ) %unescape_char | c_eof % { diagnostic :fatal, :escape_eof, nil, range(p - 1, p) } ); # Use rules in form of `e_bs escape' when you need to parse a sequence. e_bs = '\\' % { @escape_s = p @escape = nil }; # # === STRING AND HEREDOC PARSING === # # Heredoc parsing is quite a complex topic. First, consider that heredocs # can be arbitrarily nested. For example: # # puts <<CODE # the result is: #{<<RESULT.inspect # i am a heredoc # RESULT # } # CODE # # which, incidentally, evaluates to: # # the result is: " i am a heredoc\n" # # To parse them, lexer refers to two kinds (remember, nested heredocs) # of positions in the input stream, namely heredoc_e # (HEREDOC declaration End) and @herebody_s (HEREdoc BODY line Start). # # heredoc_e is simply contained inside the corresponding Literal, and # when the heredoc is closed, the lexing is restarted from that position. # # @herebody_s is quite more complex. First, @herebody_s changes after each # heredoc line is lexed. This way, at '\n' tok(@herebody_s, @te) always # contains the current line, and also when a heredoc is started, @herebody_s # contains the position from which the heredoc will be lexed. # # Second, as (insanity) there are nested heredocs, we need to maintain a # stack of these positions. Each time #push_literal is called, it saves current # @heredoc_s to literal.saved_herebody_s, and after an interpolation (possibly # containing another heredocs) is closed, the previous value is restored. e_heredoc_nl = c_nl % { # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end }; action extend_string { string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 &&<EMAIL_ADDRESS>lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal fnext expr_labelarg; else fnext *pop_literal; end fbreak; else current_literal.extend_string(string, @ts, @te) end } action extend_string_escaped { current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed. current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end } # Extend a string with a newline or a EOF character. # As heredoc closing line can immediately precede EOF, this action # has to handle such case specially. action extend_string_eol { current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 fnext *pop_literal; fbreak; else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) fnext *pop_literal; fbreak; end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end } action extend_string_space { literal.extend_space @ts, @te } # # === INTERPOLATION PARSING === # # Interpolations with immediate variable names simply call into # the corresponding machine. interp_var = '#' ( global_var | class_var_v | instance_var_v ); action extend_interp_var { current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts fcall expr_variable; } # Interpolations with code blocks must match nested curly braces, as # interpolation ending is ambiguous with a block ending. So, every # opening and closing brace should be matched with e_[lr]brace rules, # which automatically perform the counting. # # Note that interpolations can themselves be nested, so brace balance # is tied to the innermost literal. # # Also note that literals themselves should not use e_[lr]brace rules # when matching their opening and closing delimiters, as the amount of # braces inside the characters of a string literal is independent. interp_code = '#{'; e_lbrace = '{' % { @cond.push(false); @cmdarg.push(false) current_literal = literal if current_literal current_literal.start_interp_brace end }; e_rbrace = '}' % { current_literal = literal if current_literal if current_literal.end_interp_brace_and_try_closing if version?(18, 19) emit(:tRCURLY, '}'.freeze, p - 1, p) else emit(:tSTRING_DEND, '}'.freeze, p - 1, p) end if current_literal.saved_herebody_s @herebody_s = current_literal.saved_herebody_s end fhold; fnext *stack_pop; fbreak; end end }; action extend_interp_code { current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DBEG, '#{'.freeze) if current_literal.heredoc? current_literal.saved_herebody_s = @herebody_s @herebody_s = nil end current_literal.start_interp_brace fcall expr_value; } # Actual string parsers are simply combined from the primitives defined # above. interp_words := |* interp_code => extend_interp_code; interp_var => extend_interp_var; e_bs escape => extend_string_escaped; c_space+ => extend_string_space; c_eol => extend_string_eol; c_any => extend_string; *|; interp_string := |* interp_code => extend_interp_code; interp_var => extend_interp_var; e_bs escape => extend_string_escaped; c_eol => extend_string_eol; c_any => extend_string; *|; plain_words := |* e_bs c_any => extend_string_escaped; c_space+ => extend_string_space; c_eol => extend_string_eol; c_any => extend_string; *|; plain_string := |* '\\' c_nl => extend_string_eol; e_bs c_any => extend_string_escaped; c_eol => extend_string_eol; c_any => extend_string; *|; interp_backslash_delimited := |* interp_code => extend_interp_code; interp_var => extend_interp_var; c_eol => extend_string_eol; c_any => extend_string; *|; plain_backslash_delimited := |* c_eol => extend_string_eol; c_any => extend_string; *|; interp_backslash_delimited_words := |* interp_code => extend_interp_code; interp_var => extend_interp_var; c_space+ => extend_string_space; c_eol => extend_string_eol; c_any => extend_string; *|; plain_backslash_delimited_words := |* c_space+ => extend_string_space; c_eol => extend_string_eol; c_any => extend_string; *|; regexp_modifiers := |* [A-Za-z]+ => { unknown_options = tok.scan(/[^imxouesn]/) if unknown_options.any? diagnostic :error, :regexp_options, { :options => unknown_options.join } end emit(:tREGEXP_OPT) fnext expr_end; fbreak; }; any => { emit(:tREGEXP_OPT, tok(@ts, @te - 1), @ts, @te - 1) fhold; fgoto expr_end; }; *|; # # === WHITESPACE HANDLING === # # Various contexts in Ruby allow various kinds of whitespace # to be used. They are grouped to clarify the lexing machines # and ease collection of comments. # A line of code with inline #comment at end is always equivalent # to a line of code ending with just a newline, so an inline # comment is deemed equivalent to non-newline whitespace # (c_space character class). w_space = c_space+ | '\\' e_heredoc_nl ; w_comment = '#' %{ @sharp_s = p - 1 } # The (p == pe) condition compensates for added "\0" and # the way Ragel handles EOF. c_line* %{ emit_comment(@sharp_s, p == pe ? p - 2 : p) } ; w_space_comment = w_space | w_comment ; # A newline in non-literal context always interoperates with # here document logic and can always be escaped by a backslash, # still interoperating with here document logic in the same way, # yet being invisible to anything else. # # To demonstrate: # # foo = <<FOO \ # bar # FOO # + 2 # # is equivalent to `foo = "bar\n" + 2`. w_newline = e_heredoc_nl; w_any = w_space | w_comment | w_newline ; # # === EXPRESSION PARSING === # # These rules implement a form of manually defined lookahead. # The default longest-match scanning does not work here due # to sheer ambiguity. ambiguous_fid_suffix = # actual parsed [?!] %{ tm = p } | # a? a? [?!]'=' %{ tm = p - 2 } # a!=b a != b ; ambiguous_ident_suffix = # actual parsed ambiguous_fid_suffix | '=' %{ tm = p } | # a= a= '==' %{ tm = p - 2 } | # a==b a == b '=~' %{ tm = p - 2 } | # a=~b a =~ b '=>' %{ tm = p - 2 } | # a=>b a => b '===' %{ tm = p - 3 } # a===b a === b ; ambiguous_symbol_suffix = # actual parsed ambiguous_ident_suffix | '==>' %{ tm = p - 2 } # :a==>b :a= => b ; # Ambiguous with 1.9 hash labels. ambiguous_const_suffix = # actual parsed '::' %{ tm = p - 2 } # A::B A :: B ; # Resolving kDO/kDO_COND/kDO_BLOCK ambiguity requires embedding # @cond/@cmdarg-related code to e_lbrack, e_lparen and e_lbrace. e_lbrack = '[' % { @cond.push(false); @cmdarg.push(false) }; # Ruby 1.9 lambdas require parentheses counting in order to # emit correct opening kDO/tLBRACE. e_lparen = '(' % { @cond.push(false); @cmdarg.push(false) @paren_nest += 1 }; e_rparen = ')' % { @paren_nest -= 1 }; # Ruby is context-sensitive wrt/ local identifiers. action local_ident { emit(:tIDENTIFIER) if<EMAIL_ADDRESS>&& @static_env.declared?(tok) fnext expr_endfn; fbreak; else fnext *arg_or_cmdarg; fbreak; end } # Variable lexing code is accessed from both expressions and # string interpolation related code. # expr_variable := |* global_var => { if tok =~ /^\$([1-9][0-9]*)$/ emit(:tNTH_REF, tok(@ts + 1).to_i) elsif tok =~ /^\$([&`'+])$/ emit(:tBACK_REF) else emit(:tGVAR) end fnext *stack_pop; fbreak; }; class_var_v => { if tok =~ /^@@[0-9]/ diagnostic :error, :cvar_name, { :name => tok } end emit(:tCVAR) fnext *stack_pop; fbreak; }; instance_var_v => { if tok =~ /^@[0-9]/ diagnostic :error, :ivar_name, { :name => tok } end emit(:tIVAR) fnext *stack_pop; fbreak; }; *|; # Literal function name in definition (e.g. `def class`). # Keywords are returned as their respective tokens; this is used # to support singleton def `def self.foo`. Global variables are # returned as `tGVAR`; this is used in global variable alias # statements `alias $a $b`. Symbols are returned verbatim; this # is used in `alias :a :"b#{foo}"` and `undef :a`. # # Transitions to `expr_endfn` afterwards. # expr_fname := |* keyword => { emit_table(KEYWORDS_BEGIN); fnext expr_endfn; fbreak; }; constant => { emit(:tCONSTANT) fnext expr_endfn; fbreak; }; bareword [?=!]? => { emit(:tIDENTIFIER) fnext expr_endfn; fbreak; }; global_var => { p = @ts - 1 fnext expr_end; fcall expr_variable; }; # If the handling was to be delegated to expr_end, # these cases would transition to something else than # expr_endfn, which is incorrect. operator_fname | operator_arithmetic | operator_rest => { emit_table(PUNCTUATION) fnext expr_endfn; fbreak; }; '::' => { fhold; fhold; fgoto expr_end; }; ':' => { fhold; fgoto expr_beg; }; '%s' c_any => { if version?(23) type, delimiter = tok[0..-2], tok[-1].chr fgoto *push_literal(type, delimiter, @ts); else p = @ts - 1 fgoto expr_end; end }; w_any; c_any => { fhold; fgoto expr_end; }; c_eof => do_eof; *|; # After literal function name in definition. Behaves like `expr_end`, # but allows a tLABEL. # # Transitions to `expr_end` afterwards. # expr_endfn := |* label ( any - ':' ) => { emit(:tLABEL, tok(@ts, @te - 2), @ts, @te - 1) fhold; fnext expr_labelarg; fbreak; }; w_space_comment; c_any => { fhold; fgoto expr_end; }; c_eof => do_eof; *|; # Literal function name in method call (e.g. `a.class`). # # Transitions to `expr_arg` afterwards. # expr_dot := |* constant => { emit(:tCONSTANT) fnext *arg_or_cmdarg; fbreak; }; call_or_var => { emit(:tIDENTIFIER) fnext *arg_or_cmdarg; fbreak; }; bareword ambiguous_fid_suffix => { emit(:tFID, tok(@ts, tm), @ts, tm) fnext *arg_or_cmdarg; p = tm - 1; fbreak; }; # See the comment in `expr_fname`. operator_fname | operator_arithmetic | operator_rest => { emit_table(PUNCTUATION) fnext expr_arg; fbreak; }; w_any; c_any => { fhold; fgoto expr_end; }; c_eof => do_eof; *|; # The previous token emitted was a `tIDENTIFIER` or `tFID`; no space # is consumed; the current expression is a command or method call. # expr_arg := |* # # COMMAND MODE SPECIFIC TOKENS # # cmd (1 + 2) # See below the rationale about expr_endarg. w_space+ e_lparen => { if version?(18) emit(:tLPAREN2, '('.freeze, @te - 1, @te) fnext expr_value; fbreak; else emit(:tLPAREN_ARG, '('.freeze, @te - 1, @te) fnext expr_beg; fbreak; end }; # meth(1 + 2) # Regular method call. e_lparen => { emit(:tLPAREN2, '('.freeze) fnext expr_beg; fbreak; }; # meth [...] # Array argument. Compare with indexing `meth[...]`. w_space+ e_lbrack => { emit(:tLBRACK, '['.freeze, @te - 1, @te) fnext expr_beg; fbreak; }; # cmd {} # Command: method call without parentheses. w_space* e_lbrace => { if @lambda_stack.last == @paren_nest p = @ts - 1 fgoto expr_end; else emit(:tLCURLY, '{'.freeze, @te - 1, @te) fnext expr_value; fbreak; end }; # # AMBIGUOUS TOKENS RESOLVED VIA EXPR_BEG # # a?? # Ternary operator '?' c_space_nl => { # Unlike expr_beg as invoked in the next rule, do not warn p = @ts - 1 fgoto expr_end; }; # a ?b, a? ? # Character literal or ternary operator w_space* '?' => { fhold; fgoto expr_beg; }; # a %{1}, a %[1] (but not "a %=1=" or "a % foo") # a /foo/ (but not "a / foo" or "a /=foo") # a <<HEREDOC w_space+ %{ tm = p } ( [%/] ( c_any - c_space_nl - '=' ) # / | '<<' ) => { if tok(tm, tm + 1) == '/'.freeze # Ambiguous regexp literal. diagnostic :warning, :ambiguous_literal, nil, range(tm, tm + 1) end p = tm - 1 fgoto expr_beg; }; # x *1 # Ambiguous splat, kwsplat or block-pass. w_space+ %{ tm = p } ( '+' | '-' | '*' | '&' | '**' ) => { diagnostic :warning, :ambiguous_prefix, { :prefix => tok(tm, @te) }, range(tm, @te) p = tm - 1 fgoto expr_beg; }; # x ::Foo # Ambiguous toplevel constant access. w_space+ '::' => { fhold; fhold; fgoto expr_beg; }; # x:b # Symbol. w_space* ':' => { fhold; fgoto expr_beg; }; w_space+ label => { p = @ts - 1; fgoto expr_beg; }; # # AMBIGUOUS TOKENS RESOLVED VIA EXPR_END # # a ? b # Ternary operator. w_space+ %{ tm = p } '?' c_space_nl => { p = tm - 1; fgoto expr_end; }; # x + 1: Binary operator or operator-assignment. w_space* operator_arithmetic ( '=' | c_space_nl )? | # x rescue y: Modifier keyword. w_space* keyword_modifier | # a &. b: Safe navigation operator. w_space* '&.' | # Miscellanea. w_space* punctuation_end => { p = @ts - 1 fgoto expr_end; }; w_space; w_comment => { fgoto expr_end; }; w_newline => { fhold; fgoto expr_end; }; c_any => { fhold; fgoto expr_beg; }; c_eof => do_eof; *|; # The previous token was an identifier which was seen while in the # command mode (that is, the state at the beginning of #advance was # expr_value). This state is very similar to expr_arg, but disambiguates # two very rare and specific condition: # * In 1.8 mode, "foo (lambda do end)". # * In 1.9+ mode, "f x: -> do foo do end end". expr_cmdarg := |* w_space+ e_lparen => { emit(:tLPAREN_ARG, '('.freeze, @te - 1, @te) if version?(18) fnext expr_value; fbreak; else fnext expr_beg; fbreak; end }; w_space* 'do' => { if @cond.active? emit(:kDO_COND, 'do'.freeze, @te - 2, @te) else emit(:kDO, 'do'.freeze, @te - 2, @te) end fnext expr_value; fbreak; }; c_any | # Disambiguate with the `do' rule above. w_space* bareword | w_space* label => { p = @ts - 1 fgoto expr_arg; }; c_eof => do_eof; *|; # The rationale for this state is pretty complex. Normally, if an argument # is passed to a command and then there is a block (tLCURLY...tRCURLY), # the block is attached to the innermost argument (`f` in `m f {}`), or it # is a parse error (`m 1 {}`). But there is a special case for passing a single # primary expression grouped with parentheses: if you write `m (1) {}` or # (2.0 only) `m () {}`, then the block is attached to `m`. # # Thus, we recognize the opening `(` of a command (remember, a command is # a method call without parens) as a tLPAREN_ARG; then, in parser, we recognize # `tLPAREN_ARG expr rparen` as a `primary_expr` and before rparen, set the # lexer's state to `expr_endarg`, which makes it emit the possibly following # `{` as `tLBRACE_ARG`. # # The default post-`expr_endarg` state is `expr_end`, so this state also handles # `do` (as `kDO_BLOCK` in `expr_beg`). expr_endarg := |* e_lbrace => { if @lambda_stack.last == @paren_nest @lambda_stack.pop emit(:tLAMBEG, '{'.freeze) else emit(:tLBRACE_ARG, '{'.freeze) end fnext expr_value; }; 'do' => { emit_do(true) fnext expr_value; fbreak; }; w_space_comment; c_any => { fhold; fgoto expr_end; }; c_eof => do_eof; *|; # The rationale for this state is that several keywords accept value # (i.e. should transition to `expr_beg`), do not accept it like a command # (i.e. not an `expr_arg`), and must behave like a statement, that is, # accept a modifier if/while/etc. # expr_mid := |* keyword_modifier => { emit_table(KEYWORDS) fnext expr_beg; fbreak; }; bareword => { p = @ts - 1; fgoto expr_beg; }; w_space_comment; w_newline => { fhold; fgoto expr_end; }; c_any => { fhold; fgoto expr_beg; }; c_eof => do_eof; *|; # Beginning of an expression. # # Don't fallthrough to this state from `c_any`; make sure to handle # `c_space* c_nl` and let `expr_end` handle the newline. # Otherwise code like `f\ndef x` gets glued together and the parser # explodes. # expr_beg := |* # +5, -5, - 5 [+\-] w_any* [0-9] => { emit(:tUNARY_NUM, tok(@ts, @ts + 1), @ts, @ts + 1) fhold; fnext expr_end; fbreak; }; # splat *a '*' => { emit(:tSTAR, '*'.freeze) fbreak; }; # # STRING AND REGEXP LITERALS # # /regexp/oui # /=/ (disambiguation with /=) '/' c_any => { type = delimiter = tok[0].chr fhold; fgoto *push_literal(type, delimiter, @ts); }; # %<string> '%' ( any - [A-Za-z] ) => { type, delimiter = @source_buffer.slice(@ts).chr, tok[-1].chr fgoto *push_literal(type, delimiter, @ts); }; # %w(we are the people) '%' [A-Za-z]+ c_any => { type, delimiter = tok[0..-2], tok[-1].chr fgoto *push_literal(type, delimiter, @ts); }; '%' c_eof => { diagnostic :fatal, :string_eof, nil, range(@ts, @ts + 1) }; # Heredoc start. # <<END | <<'END' | <<"END" | <<`END` | # <<-END | <<-'END' | <<-"END" | <<-`END` | # <<~END | <<~'END' | <<~"END" | <<~`END` '<<' [~\-]? ( '"' ( c_line - '"' )* '"' | "'" ( c_line - "'" )* "'" | "`" ( c_line - "`" )* "`" | bareword ) % { heredoc_e = p } c_line* c_nl % { new_herebody_s = p } => { tok(@ts, heredoc_e) =~ /^<<(-?)(~?)(["'`]?)(.*)\3$/ indent = !$1.empty? || !$2.empty? dedent_body = !$2.empty? type = $3.empty? ? '<<"'.freeze : ('<<'.freeze + $3) delimiter = $4 if dedent_body && version?(18, 19, 20, 21, 22) emit(:tLSHFT, '<<'.freeze, @ts, @ts + 2) p = @ts + 1 fnext expr_beg; fbreak; else fnext *push_literal(type, delimiter, @ts, heredoc_e, indent, dedent_body); @herebody_s ||= new_herebody_s p = @herebody_s - 1 end }; # # SYMBOL LITERALS # # :"bar", :'baz' ':' ['"] # ' => { type, delimiter = tok, tok[-1].chr fgoto *push_literal(type, delimiter, @ts); }; ':' bareword ambiguous_symbol_suffix => { emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 fnext expr_end; fbreak; }; ':' ( bareword | global_var | class_var | instance_var | operator_fname | operator_arithmetic | operator_rest ) => { emit(:tSYMBOL, tok(@ts + 1), @ts) fnext expr_end; fbreak; }; # # AMBIGUOUS TERNARY OPERATOR # # Character constant, like ?a, ?\n, ?\u1000, and so on # Don't accept \u escape with multiple codepoints, like \u{1 2 3} '?' ( e_bs ( escape - ( '\u{' (xdigit+ [ \t]+)+ xdigit+ '}' )) | (c_any - c_space_nl - e_bs) % { @escape = nil } ) => { value = @escape || tok(@ts + 1) if version?(18) if defined?(Encoding) emit(:tINTEGER, value.dup.force_encoding(Encoding::BINARY)[0].ord) else emit(:tINTEGER, value[0].ord) end else emit(:tCHARACTER, value) end fnext expr_end; fbreak; }; '?' c_space_nl => { escape = { " " => '\s', "\r" => '\r', "\n" => '\n', "\t" => '\t', "\v" => '\v', "\f" => '\f' }[@source_buffer.slice(@ts + 1)] diagnostic :warning, :invalid_escape_use, { :escape => escape }, range p = @ts - 1 fgoto expr_end; }; '?' c_eof => { diagnostic :fatal, :incomplete_escape, nil, range(@ts, @ts + 1) }; # f ?aa : b: Disambiguate with a character literal. '?' [A-Za-z_] bareword => { p = @ts - 1 fgoto expr_end; }; # # KEYWORDS AND PUNCTUATION # # a({b=>c}) e_lbrace => { if @lambda_stack.last == @paren_nest @lambda_stack.pop emit(:tLAMBEG, '{'.freeze) else emit(:tLBRACE, '{'.freeze) end fbreak; }; # a([1, 2]) e_lbrack => { emit(:tLBRACK, '['.freeze) fbreak; }; # a() e_lparen => { emit(:tLPAREN, '('.freeze) fbreak; }; # a(+b) punctuation_begin => { emit_table(PUNCTUATION_BEGIN) fbreak; }; # rescue Exception => e: Block rescue. # Special because it should transition to expr_mid. 'rescue' %{ tm = p } '=>'? => { emit(:kRESCUE, 'rescue'.freeze, @ts, tm) p = tm - 1 fnext expr_mid; fbreak; }; # if a: Statement if. keyword_modifier => { emit_table(KEYWORDS_BEGIN) fnext expr_value; fbreak; }; # # RUBY 1.9 HASH LABELS # label ( any - ':' ) => { fhold; if version?(18) ident = tok(@ts, @te - 2) emit((@source_buffer.slice(@ts) =~ /[A-Z]/) ? :tCONSTANT : :tIDENTIFIER, ident, @ts, @te - 2) fhold; # continue as a symbol if<EMAIL_ADDRESS>&& @static_env.declared?(ident) fnext expr_end; else fnext *arg_or_cmdarg; end else emit(:tLABEL, tok(@ts, @te - 2), @ts, @te - 1) fnext expr_labelarg; end fbreak; }; # # CONTEXT-DEPENDENT VARIABLE LOOKUP OR COMMAND INVOCATION # # foo= bar: Disambiguate with bareword rule below. bareword ambiguous_ident_suffix | # def foo: Disambiguate with bareword rule below. keyword => { p = @ts - 1 fgoto expr_end; }; # a = 42; a [42]: Indexing. # def a; end; a [42]: Array argument. call_or_var => local_ident; # # WHITESPACE # w_any; e_heredoc_nl '=begin' ( c_space | c_nl_zlen ) => { p = @ts - 1 fgoto line_begin; }; # # DEFAULT TRANSITION # # The following rules match most binary and all unary operators. # Rules for binary operators provide better error reporting. operator_arithmetic '=' | operator_rest | punctuation_end | c_any => { p = @ts - 1; fgoto expr_end; }; c_eof => do_eof; *|; # Special newline handling for "def a b:" # expr_labelarg := |* w_space_comment; w_newline => { if @in_kwarg fhold; fgoto expr_end; else fgoto line_begin; end }; c_any => { fhold; fgoto expr_beg; }; c_eof => do_eof; *|; # Like expr_beg, but no 1.9 label or 2.2 quoted label possible. # expr_value := |* # a:b: a(:b), a::B, A::B label (any - ':') => { p = @ts - 1 fgoto expr_end; }; # "bar", 'baz' ['"] # ' => { fgoto *push_literal(tok, tok, @ts); }; w_space_comment; w_newline => { fgoto line_begin; }; c_any => { fhold; fgoto expr_beg; }; c_eof => do_eof; *|; expr_end := |* # # STABBY LAMBDA # '->' => { emit(:tLAMBDA, '->'.freeze, @ts, @ts + 2) @lambda_stack.push @paren_nest fnext expr_endfn; fbreak; }; e_lbrace | 'do' => { if @lambda_stack.last == @paren_nest @lambda_stack.pop if tok == '{'.freeze emit(:tLAMBEG, '{'.freeze) else # 'do' emit(:kDO_LAMBDA, 'do'.freeze) end else if tok == '{'.freeze emit(:tLCURLY, '{'.freeze) else # 'do' emit_do end end fnext expr_value; fbreak; }; # # KEYWORDS # keyword_with_fname => { emit_table(KEYWORDS) fnext expr_fname; fbreak; }; 'class' w_any* '<<' => { emit(:kCLASS, 'class'.freeze, @ts, @ts + 5) emit(:tLSHFT, '<<'.freeze, @te - 2, @te) fnext expr_value; fbreak; }; # a if b:c: Syntax error. keyword_modifier => { emit_table(KEYWORDS) fnext expr_beg; fbreak; }; # elsif b:c: elsif b(:c) keyword_with_value => { emit_table(KEYWORDS) fnext expr_value; fbreak; }; keyword_with_mid => { emit_table(KEYWORDS) fnext expr_mid; fbreak; }; keyword_with_arg => { emit_table(KEYWORDS) if version?(18) && tok == 'not'.freeze fnext expr_beg; fbreak; else fnext expr_arg; fbreak; end }; '__ENCODING__' => { if version?(18) emit(:tIDENTIFIER) unless<EMAIL_ADDRESS>&& @static_env.declared?(tok) fnext *arg_or_cmdarg; end else emit(:k__ENCODING__, '__ENCODING__'.freeze) end fbreak; }; keyword_with_end => { emit_table(KEYWORDS) fbreak; }; # # NUMERIC LITERALS # ( '0' [Xx] %{ @num_base = 16; @num_digits_s = p } int_hex | '0' [Dd] %{ @num_base = 10; @num_digits_s = p } int_dec | '0' [Oo] %{ @num_base = 8; @num_digits_s = p } int_dec | '0' [Bb] %{ @num_base = 2; @num_digits_s = p } int_bin | [1-9] digit* '_'? %{ @num_base = 10; @num_digits_s = @ts } int_dec | '0' digit* '_'? %{ @num_base = 8; @num_digits_s = @ts } int_dec ) %{ @num_suffix_s = p } int_suffix => { digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end fbreak; }; flo_frac flo_pow? => { diagnostic :error, :no_dot_digit_literal }; flo_int [eE] => { if version?(18, 19, 20) diagnostic :error, :trailing_in_number, { :character => tok(@te - 1, @te) }, range(@te - 1, @te) else emit(:tINTEGER, tok(@ts, @te - 1).to_i, @ts, @te - 1) fhold; fbreak; end }; flo_int flo_frac [eE] => { if version?(18, 19, 20) diagnostic :error, :trailing_in_number, { :character => tok(@te - 1, @te) }, range(@te - 1, @te) else emit(:tFLOAT, tok(@ts, @te - 1).to_f, @ts, @te - 1) fhold; fbreak; end }; flo_int ( flo_frac? flo_pow %{ @num_suffix_s = p } flo_pow_suffix | flo_frac %{ @num_suffix_s = p } flo_suffix ) => { digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end fbreak; }; # # STRING AND XSTRING LITERALS # # `echo foo`, "bar", 'baz' '`' | ['"] # ' => { type, delimiter = tok, tok[-1].chr fgoto *push_literal(type, delimiter, @ts, nil, false, false, true); }; # # CONSTANTS AND VARIABLES # constant => { emit(:tCONSTANT) fnext *arg_or_cmdarg; fbreak; }; constant ambiguous_const_suffix => { emit(:tCONSTANT, tok(@ts, tm), @ts, tm) p = tm - 1; fbreak; }; global_var | class_var_v | instance_var_v => { p = @ts - 1; fcall expr_variable; }; # # METHOD CALLS # '.' | '&.' | '::' => { emit_table(PUNCTUATION) fnext expr_dot; fbreak; }; call_or_var => local_ident; bareword ambiguous_fid_suffix => { if tm == @te # Suffix was consumed, e.g. foo! emit(:tFID) else # Suffix was not consumed, e.g. foo!= emit(:tIDENTIFIER, tok(@ts, tm), @ts, tm) p = tm - 1 end fnext expr_arg; fbreak; }; # # OPERATORS # ( e_lparen | operator_arithmetic | operator_rest ) => { emit_table(PUNCTUATION) fnext expr_beg; fbreak; }; e_rbrace | e_rparen | ']' => { emit_table(PUNCTUATION) @cond.lexpop; @cmdarg.lexpop if RBRACE_OR_RBRACK.include?(tok) fnext expr_endarg; else # ) # fnext expr_endfn; ? end fbreak; }; operator_arithmetic '=' => { emit(:tOP_ASGN, tok(@ts, @te - 1)) fnext expr_beg; fbreak; }; '?' => { emit(:tEH, '?'.freeze) fnext expr_value; fbreak; }; e_lbrack => { emit(:tLBRACK2, '['.freeze) fnext expr_beg; fbreak; }; punctuation_end => { emit_table(PUNCTUATION) fnext expr_beg; fbreak; }; # # WHITESPACE # w_space_comment; w_newline => { fgoto leading_dot; }; ';' => { emit(:tSEMI, ';'.freeze) fnext expr_value; fbreak; }; '\\' c_line { diagnostic :error, :bare_backslash, nil, range(@ts, @ts + 1) fhold; }; c_any => { diagnostic :fatal, :unexpected, { :character => tok.inspect[1..-2] } }; c_eof => do_eof; *|; leading_dot := |* # Insane leading dots: # a #comment # .b: a.b c_space* %{ tm = p } ('.' | '&.') => { p = tm - 1; fgoto expr_end; }; any => { emit(:tNL, nil, @newline_s, @newline_s + 1) fhold; fnext line_begin; fbreak; }; *|; # # === EMBEDDED DOCUMENT (aka BLOCK COMMENT) PARSING === # line_comment := |* '=end' c_line* c_nl_zlen => { emit_comment(@eq_begin_s, @te) fgoto line_begin; }; c_line* c_nl; c_line* zlen => { diagnostic :fatal, :embedded_document, nil, range(@eq_begin_s, @eq_begin_s + '=begin'.length) }; *|; line_begin := |* w_any; '=begin' ( c_space | c_nl_zlen ) => { @eq_begin_s = @ts fgoto line_comment; }; '__END__' ( c_eol - zlen ) => { p = pe - 3 }; c_any => { fhold; fgoto expr_value; }; c_eof => do_eof; *|; }%% # %
end


ABOUT
A two page webpage with spinning windmills.


Prof. Dr. Marco André Argenta - Argenta, M.A.
Civil Construction Department
Post Graduation Program in Civil Construction Engineering
Federal University of Paraná, Brazil
marco.argenta@ufpr.br


My To Do List
This is your task list
- read through notes
- write list
- create app diagram
- 12/11/19
- 13/11/19
- 20/11/19
This is where completed tasks are logged
- last item completed
- penultimate item completed
- second item completed
- first item completed
- 18/11/16
- 26/11/19
- 11/11/19


Two opposite alignment marks are needed to identify unique fix points on the image.
Mark the reference by drag and dop with the mouse or with the coordinates and push "Update Reference".
You can switch between the two reference with "Select Reference".
Don't forget to save your changes with the "Save" button!


About CRISPRts
Application
This tool allows easy design of sgRNA oligos, which contains a 5' T7 promoter and a complementary sequence for PCR amplification with a scaffold oligo. This PCR product is then used as template for in vitro transcription. This tool can be also used to download DNA sequence files from the Ensembl Genome Browser, with annotated exons.
Contact
For questions or suggestions about the CRISPRts app: email Sebastian Eguiguren
For queries about the source code, or app development: email José Eguiguren


Quentin Coldwater
Timeline
- 1993
- c.2000
- 2009
- 2014
- 2015
- unknown
- unknown
- unknown
- unknown
- 2018
- 2018
- Born in Montclair, New Jersey USA.
- Meets Julia Wicker, who introduces him to the children's book series Fillory and Further.
- Hospitalised for the first time due to depression aged 16.
- Graduated Magna Cum Laude from Columbia University with a Bachelor's Degree in Literature.
- Enrols at Brakebills University, New York to study magic.
- Begins a romantic relationship with Alice Quinn.
- Crowned one of the kings of Fillory along with Margo Hanson and Eliot Waugh.
- Kills the God, Ember, resulting in the creators of the universe 'turning off' magic.
- Embarks upon a romantic relationship with Eliot while solving a mosaic puzzle, living out an entire lifetime together in another timeline.
- Discovers (to his disappointment) that his Discipline is Repair of Small Objects.
- Dies to save his friends (and the world) in a controversial and emotional scene during a showdown with Everett Rowe.


PORTFOLIO
Navigation
Home
About Me
Portfolio
Resume
Contact Me
Home
About Me
Resume
Portfolio
Contact Me
Home
About Me
Resume
Portfolio
Contact Me
Portfolio
Portfolio
Portfolio
Portfolio
Developer. Designer. Videographer.
Designer
Developer
Videographer
hi


In total, there are 134 winter trails and 21 summer trails on the panorama mountain. The runs are seperated into 4 different types: easy trails are green circles, intermediate trails are blue squares, hard trails are black diamonds, and very hard trials are double black diamonds! This is a great place to go even if you are new to skiing/snowboarding since there is a bunny hill as well as a run meant for getting used to it. Panorama also offers a service called rk heliski where they put you in a helicopter to fly you up the Purcell mountain to ski down. A similar service is the monster X snowcat where you get on a snowcat shuttle that takes you to the top of the Taynton bowl.
This is what the panorma mountain with all the trails looks like for skiing/snowboarding in winter and biking in summer.


Welcome to our website!
Customers
Search & edit existing customers, plus add new customers. Customers cannot be deleted from the database.
Bookings
Search, edit & delete existing bookings, plus add new bookings. Bookings must be associated with an existing customer. Bookings can be deleted and upon deletion, the associated payment and assignment will also be deleted. When a new booking is created, a new payment must be added. A new assignment will also be added, but the Tour Guide in the relationship can be NULL. This can then be updated/managed from the Tour Guide page.
Assignments
Search, edit, delete & add new assignments. New assignments require only the Booking Id and Tour Guide name. The location Id is take from the booking information as the 3rd foreign key. Assignments manage the M:M relationship between Location and Tour Guide.
Tour Guides
Search, edit & add new tour guides to the database. Tour Guides cannot be deleted from the database.
Locations
Search, edit & add new locations to the database. Locations cannot be deleted from the database.
Ratings
Search, edit, delete & add new locations to the database. Ratings must be associated with a customer and with a location, manageing the M:M relationship between the two.
Payments
Search, edit, delete & add new payments. Payments must be associated with a booking.


Before Change
pending_submission[promise] = plan
submit_satisfied_pending()
// Saturate the pool before we block on a result for maximum processing parallelism.
if len(in_flight) == self._pool_size:
process_one_result()
// Consume the tail of pending submissions and nodes in_flight.
After Change
// 1. Whenever we don"t have enough work to saturate the pool, request more.
// 2. Whenever the pool is not saturated, submit currently pending work.
for step_batch in self._scheduler.schedule(build_request):
if not step_batch:
// A batch should only be empty if all dependency work is currently blocked/running.
if not in_flight and not pending_submission:
raise Exception("Scheduler provided an empty batch while no work is in progress!")
else:
// Submit and wait for work for as long as we"re able to keep the pool saturated.
pending_submission.update(step_batch)
while submit_until(self._pool_size) > 0:
await_one()
// Await at least one entry per scheduling loop.
submit_until(0)
if in_flight:
await_one()


Additional Minor Features
In order to implement brace matching, once the syntax highlighting lexer has been implemented, all that is required is to implement the PairedBraceMatcher interface and to return an array of brace pairs ( BracePair ) for the language. Each brace pair specifies the characters for the opening and closing braces and the lexer token types for these characters. (In principle, it is possible to return multi-character tokens, like “begin” and “end”, as the start and end tokens of a brace pair. The IDE will match such braces, but the highlighting for such braces will not be fully correct.)
Certain types of braces can be marked as structural. Structural braces have higher priority than regular braces: they are matched with each other even if there are unmatched braces of other types between them, and an opening non-structural braces is not matched with a closing one if one of them is inside a pair of matched structural braces and another is outside.
The code folding is controlled by the plugin through the FoldingBuilder interface. The interface returns the list of text ranges which are foldable (as an array of FoldingDescriptor objects), the replacement text which is shown for each range when it is folded, and the default state of each folding region (folded or unfolded).
The Comment Code feature is controlled through the Commenter interface. The interface can return the prefix for the line comment, and the prefix and suffix for the block comment, if such features are supported by the language.
Example: Commenter for Properties language plugin
To support smart/semantic Join Lines see JoinLinesHandlerDelegate.
Smart Enter (e.g. autocomplete missing semicolon/parentheses) can be provided via SmartEnterProcessor.
Naming suggestions for Rename Refactoring can be provided via NameSuggestionProvider.
Semantic highlight usages (e.g. exit points) can be achieved using HighlightUsagesHandlerFactory.
View | Parameter Info is provided via
ParameterInfoHandler
(extension point codeInsight.parameterInfo
).
The To Do view is supported automatically if the plugin provides a correct implementation of the ParserDefinition.getCommentTokens() method.
The View | Context Info feature is supported for custom languages since IntelliJ IDEA 10.5.
In order for it to work, you need to have a structure view implementation based on a
TreeBasedStructureViewBuilder,
and additionally to provide an implementation of
DeclarationRangeHandler
for your language and to register it in the declarationRangeHandler
extension point.
Spellchecking can be provided via EP spellchecker.support
(
SpellcheckingStrategy
) where you can return
Tokenizer
to use, possibly depending on the passed in
PsiElement
(or EMPTY_TOKENIZER
for no spellchecking).
New in IntelliJ IDEA 13: user-configurable reference injections can be provided via referenceInjector
extension point (
ReferenceInjector
) (IntelliLang plugin required).


{{ quote.quoteText + ' - ' + quote.quoteAuthor }}
This quote was created {{ quote.dateCreated|dateCount }} days ago


{% extends 'commercialoperator/emails/base_email.html' %}
{% block content %}
Your Application for a commercial operations licence has been submitted, the application number is {{ proposal.lodgement_number }}
Submitter: {{ proposal.submitter.get_full_name }}
Lodgement date: {{ proposal.lodgement_date }}
It may take up to 2 weeks to process your application.
You will receive a notification email if there is any incomplete information or documents missing from the application.
If you would like to amend the application now please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}}
{% endblock %}


DEFAULT TEMPLATE
This is template example and at the same time default template for all documentation. All possible contributions are welcomed. Current template is far from ideal simply because it was not a main focus of first versions.
This is template example and at the same time default template for all documentation. All possible contributions are welcomed. Current template is far from ideal simply because it was not a main focus of first versions.


The dialog is used as a container to be displayed in response to an action. It is commonly used to collect simple information with a short form, to get confirmation or display contextual information that does not require a page.
Dialogs make use of a singleton service called DialogService
. It provides the ability to
open()
dialog windows.
The open()
method accepts either a TemplateRef
or Component
as dialog
content. In addition, you may also provide a DialogConfig
object to override some
system-default dialog window behaviours.
When a dialog window is opened, the content is positioned in a parent element that is appended to the body.
Importing either BrowserAnimationsModule
or NoopAnimationsModule
is required.
BrowserAnimationsModule
is the standard Angular animation module, it animates content as
expected. NoopAnimationsModule
mocks the animations and does not render them, potentially
increasing performance.


This Week in Rust
Hello and welcome to the seventh issue of This Week in Rust, a weekly overview of Rust and its community. Things are calming down quite a bit, in that nothing extraordinarily exciting is happening. Lots of great work is being done everywhere, and good progress is being made in both bugfixes and cleanup. It has been a good week!
What’s cooking on master?
Issue churn this week was -15. A total of 59 PRs were merged.
Breaking changes
- The semantics of
range_rev
have changed. This will break your code without warning. It is now, to use interval notation,(hi, lo]
rather than[hi, lo)
. pub extern
andpriv extern
have been removed from the language. This matches the previous similar change toimpl
. Place the visibility qualifier (pub
/priv
) on each item in theextern
block instead.&T
(besides&'static T
) is no longer allowed in@T
.- The
ThreadPerCore
spawn mode has been removed, as it doesn’t make sense with the new scheduler. - The
consume
methods of the hash containers has been replaced with an external iterator. The method name is the same, though. - Moved values can no longer be captured twice. This was a blatant soundness issue.
- The
swap_unwrap
method of Option has been renamed totake_unwrap
. debug!
statements generate no code unless you pass--cfg debug
torustc
. This should help keep code size down and make your programs a (tiny bit) faster. Now you don’t have to feel bad about havingdebug!
in hot code.- The
mutate_values
method of HashMap has been removed.
Notable library additions, bugfixes, and cleanup
- An iterator adaptor was added that endlessly repeats the iterator it is called on.
- Generated test runners now have a
-h
/--help
option. - Metric capturing + racheting has been added for benchmarks.
local_data
now has aget_mut
function.extra::semver
has been updated to SemVer 2.0.0.- Consuming iterators have been added for the hash structures.
extra::ringbuf
now implements DoubleEndedIterator.Eq
now has a default implementation ofne
.extra::term
now knows how to handle more attributes.- More containers implement
FromIter. This means you can use
.collect()
to gather the elements from an iterator into those containers. - Task killing, failure, and exit code propagation in the new runtime has been implemented.
Notable compiler additions, bugfixes, and cleanup
syntax::attr
has been modernized.- Tons of debuginfo work from mw this week!
- Trait data structures have been cleaned up, as well as a default method fix.
- Intrinsics now have much better codegen.
- A
no_implicit_prelude
attribute has been added, which prevents prelude injection in the module heirarchy starting at the item which that attribute is added to. - C-style enum variants are now
allowed in
[T, ..n]
expressions. - All language items are now optional. The compiler emits an error if a language item is used but not provided.
- The removal of
spanned<T>
has begun. - Headers have been removed for
~str
and~[T]
whereT
is unmanaged.
Documentation, tools, and other stuff
- rustpkg now works when you don’t give it a package ID. It builds/installs/cleans the package in the current directory, iff the current directory is in a rustpkg workspace.
--quiet
is no longer passed to git during submodule operations, so you can see the progress of the huge LLVM download.- Documentation of the lint-controlling attributes was added.
- rustpkg now handles cloning from local git repos.
- The GtkSourceView highlighting file was improved.
Meetings
The Tuesday meeting discussed nothing at all of importance.


HKVANIT1ES
...
About
Create your Poem
See Poems
Instagram
Your selection
Description
Description
Description
Description
Description
Continue
Reset all
Show as text
Grid:
S
M
L
Description
Description
Description
Description
Description
Description


{{ entry.entry_title }}
{{entry.entry_text|truncatechars:350}} Continue to read
Posted on {{entry.pub_date}} by {{entry.author}}
{{entry.entry_text|truncatechars:350}} Continue to read
Posted on {{entry.pub_date}} by {{entry.author}}
No entries are available.
{% endif %}


BILLY BATHGATE A film review by Mark R. Leeper Copyright 1991 Mark R. Leeper
Capsule review: A film with a nice period feel about a young man rising in Dutch Schultz's organization while Schultz himself is falling. Above average accuracy for a gangster film, but still some mistakes. The film needed a really good performance by Hoffman, who for once just could not muster the power the role needed. Rating: low +2 (-4 to +4).
"Organized" crime was not so organized in the 1920s and early 1930s. Individual gangs built on bootlegging, prostitution, gambling, or other rackets fought each other for turf. Meyer Lansky forged a single government over the major gangs to organize them and to minimize inter-gang warfare. The birth of this syndicate was the death of the last wild gangster. And it was not the FBI or the police who killed him; it is generally assumed to have been fellow gangsters terrified because this loose cannon had just effectively declared war on the United States government. In his fiery temper, Dutch Schultz had announced that he was going to kill government prosecutor Thomas E. Dewey. The new syndicate was trying to bring order. The last thing it wanted was a war with the United States government packaged and delivered by the likes of Dutch Schultz. So Schultz died and true organized crime was born. E. L. Doctorow's novel BILLY BATHGATE tells the story of a young Irish-American rising in Schultz's organization at the same time Schultz's star started descending. Tom Stoppard wrote the screenplay for a film adaptation directed by Robert Benton.
The structure of BILLY BATHGATE's plot parallels that of GOODFELLAS. The story begins with one horrendous crime, flashes back to how things got to this state, and then continues from there into the future. Billy (played by Loren Dean) is on hand to see Schultz (played by Dustin Hoffman) murdering Bo Weinberg (played by Bruce Willis). It is a long ritual involving a tugboat, a tub of cement, and Drew Preston (play by Nicole Kidman), who is Bo's unreliable girlfriend. From there we return to how a teenage Billy, awestruck at Schultz's power and wealth, first accidentally impresses Schultz, then intentionally does it, then connives his way into Schultz's organization. Bathgate begins as mascot and errand boy to the Schultz organization and uses his new-found wealth to impress his girlfriend and his mother, the latter drained from a sweatshop job that pays in a week what Billy spends on one lunch.
There are problems with the script that might also be virtues. This is not a rock 'em, sock 'em, UNTOUCHABLES sort of film. There are scenes with action, but there are not many. There is little to race your pulse. There is not even much dramatic tension. The film is more concerned with questions such as whether Schultz really is exceptional or whether he is just an ordinary man. There is a little bit of inter-gang rivalry, a bit of Billy's risking his life from or for his boss. But Billy's scams are small and short. Like RAGTIME, this is not an adventure film; it is an opportunity to put the viewer in a well-realized historical setting so that the viewer can appreciate the situation. In some cases advancing Billy's story frustratingly takes us away from Schultz's story. There is also a little sex in Billy's story, giving us some visual candy to appease us that we are not seeing Schultz's story.
One problem with the dramatic tension is that Hoffman does not do angry and psychotic very well. Sometimes putting someone mild in a vicious role works extremely well. A case in point might be Alan Arkin in WAIT UNTIL DARK. However, the decision to have the driving power of a film to be the force of Dustin Hoffman's anger is questionable.
"Sorry, Mr. Hoffman, we're looking for someone meaner."
"I can be meaner!"
"We're looking for someone angrier."
"I can be angrier!"
"We want someone scary."
"I can be sceary!"
"We want someone else."
Hoffman kicks the casting director in the bedoobees.
Henry Fonda also was convincing in nice-guy roles but had problems with heavies. Hoffman is not terrible in the role, but he is only okay and much more could have been hope for.
Next we come to the question of historical accuracy. Here, too, the film is flawed, but not terribly. There were some points that were indeed quite accurate. Arthur Flegenheimer did indeed borrow the name Dutch Schultz from another hood. And he was indeed very even-tempered until it came to the question of money. If Schultz thought you were cheating him out of even small money, your life was not worth much. "Legs" Diamond and Vincent "Mad Dog" Coll each died from Schultz's rages over money and they were by no means alone. But the film did not go far enough. It showed Dutch Schultz as a fancy dresser. Schultz was too much of a skinflint ever to dress nicely. Lucky Luciano said, "Dutch was the cheapest guy I ever knew. The guy had a couple of million bucks and he dressed like a pig." The film shows Bo Weinberg being an independent hood murdered before the upstate New York trial. In actual fact, Weinberg worked for Schultz. He had little faith that Schultz would win the upstate New York trial and let Luciano move in on Schultz's rackets while Schultz was pretending to be a good citizen for the trial. Another inaccuracy is in the spoiler section following this review. As a minor aside, incidentally, we see a little of Stephen Hill playing Otto Berman--known as Abbadabba Berman. He was a mathematician who worked out a method to increase the numbers racket take by 10%. He would find out what numbers had been least played. From there he figured how much he had to bet in racetrack pari-mutuel machines to make the low-played numbers come up winners. That part was perfectly legal. The pari-mutuel machine bets would lose, but the right numbers would come up and Schultz would pay out less. The "Abbadabba" nickname was a magic word (corrupted from "Abracadabra"?) indicating that Berman was the magician of the numbers racket.
Overall this is not a perfect portrait of Dutch Schultz and the people around him, and it could use a bit more action, but it is watchable and enjoyable. My rating is a low +2 on the -4 to +4 scale.
*****SPOILER**********SPOILER**********SPOILER**********SPOILER*****
The attack on the Palace Chop House could have been better researched. Charlie "The Bug" Workman (I'm not making this up!) did the hit. To make sure he was not surprised by someone coming out of the restroom, he went there first and shot the heavy-set man washing his hands. He then burst out of the john with a .38 in each hand and gunned down the three men at Schultz's table. Bug then realized the man in the john was Schultz and went back in to rifle Schultz's pockets. This is quite different from the scene in the film. Also, Schultz appears dead in the film. Actually, Schultz raved for about two days before dying. I occasionally get mail from people whose response to having inaccuracies pointed out is "What does it matter?" That is never an easy question to answer. In truth, historical accuracy is its own reward. It only matters if it matters. To me it matters.
Mark R. Leeper att!mtgzy!leeper<EMAIL_ADDRESS>Copyright 1991 Mark R. Leeper .
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


I have written a python script to get the data from emonTx v3 but I am getting weird symbols instead. I have posted my script below
#!/usr/bin/env python
import time
import serial
ser = serial.Serial(
port = '/dev/ttyAMA0',
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=3,
)
ser.open()
response = ser.readlines()
ser.close()
print response
Some of the data I received
['!!!!!\x86\84a\x04\xff']
['!!!!!\x84\84a\x04\xff']
['!!!\xa1!!%!5\xd5']
Re: Reading from Raspberry Pi port
Anybody know where I did wrong?
If only I can understand how emonhub works, I just started learning Python 2 week ago because of this. Haha. I know that emonhub is in the background receiving, parsing, processing, buffering and forwarding the data to emoncms. But I am afraid the process is too complicated for me to understanding at this moment. So I can't hitch hike emonhub and get the output from there. So if someone could point me in some direction which (function/method) to focus on then it would be great.
Since I have no idea on that, I proceed to read the port myself but it seems that it is not so straight forward.
Re: Reading from Raspberry Pi port
I don't know Python at all, but there are very many tutorials available that should point you in the right direction. Try searching for "python read from serial port example". It might be more helpful if you include in your search the platform that you're working on.
I've programmed in many languages and variants of languages, a few points to think about:
Are you trying to read characters one by one or complete lines?
Are you trying to interpret what comes in, or so you just want to see the ASCII code values?
What happens to your script if no data is available - will it wait forever or fail?
Re: Reading from Raspberry Pi port
"So if someone could point me in some direction which (function/method) to focus on then it would be great."
What is it that you wish to do ?
there is a small serial logging script written for debugging on the "emonTH Unreliable reading timing?" thread that may help as it is "just" a basic serial reader.
Paul
Re: Reading from Raspberry Pi port
@Robert Wall
Me too! I am not well verse in Python, I only know C++ and C# well. Which is why I did search for examples and got the above script and edited a little to suits my need.
To answer your questions:
I want to read everything that is passed from the emonTx V3 to the raspberry, I believe the readlines() does that, I will filter out the unwanted stuff after I can get the correct reading. One step at a time.
I have included a Timeout at 3secs, so it will not wait forever for the data, if there is no data then my script will read nothing and still stop. I will use write another crontab ftp script to send the data into my server hosted in my laptop.
@Paul
What I wish to do now is to get everything that is passed into the raspberry. Either by
Both of the above option are not so great for me as I am not well verse in Python, I tried opening up emonhub to read but there are so many files I have no idea where to starts. Which function is the last step where it pass the data into emoncms. Knowing that particular function, I might be able to add in additional functions and pass that data into my own database(so I don't have to use emoncms).
After I got the above working, I will send those data using a crontab ftp script and send those data into my own server hosted in my laptop. But one step at a time, so I need to get the above working first, before I can proceed this ftp script.
Thanks for all your help! :)
Re: Reading from Raspberry Pi port
Any particular reason you want to write it in python? Another option to consider is to just write your program (in the language of your choice) to read from stdin. You can then use stty to configure the serial port as you want it, and when you run your program, simply tell it to read its stdin from the serial port of your choice with something like:
my_prog < /dev/ttyAMA0
Re: Reading from Raspberry Pi port
I would love to help you further but cannot fathom out what you are after, it's clear emoncms and emonhub are not doing what you want but beyond that it's really quite vague what you do want, I have read your various other threads and they all seem follow a common theme but I'm still none the wiser.
You want to read the serial port - emonhub does that and you want to save data to a remote sql database - emoncms can do that. but apparently you do not want either of these softwares, If you want to write your own versions you should, as dBC suggests, do it in a language you do know or if you want emonhub/emoncms to "do something else" you need to explain what that is.
Paul
Re: Reading from Raspberry Pi port
@dBC
Reason being I did not know I can write it in another language! Haha, I always thought raspberry pi run in linux so it can only run Python.
@Paul
For the current system I did now,the data is send from emonTx >> Raspberry(emonhub) >> Emoncms(Remote)
For the current system that I know I can now do, the data is send from emonTx >> Raspberry(emonhub) >> Emoncms(Remote) >> my own MQSQL/MYSQL
For the system I want to develop, the data is send from emonTx >> Raspberry(Any "platform") >> my own MQSQL/MYSQL.
This save me a step of using emoncms(don't really like that apikey thing). And if I can get the data into my own SQL table, I can do analysis using matlab.
Actually, what I want is rather simple. A table with 5 columns. Timestamp, value of CT1, value of CT2, value of CT3, value of CT4. As long as I can get those values in a table in my own database that's good enough for me. :)
Re: Reading from Raspberry Pi port
I think I have a better way to explain myself. In emoncms, there is a function to export into csv(under Feed). What I want is exactly like that. The first column is the timestamp, the second is the value. All these values to be inserted into my own database.
I believe this is exactly what is happening behind emoncms. The timestamp and the CT values. If I got a way to get these data, it will be awesome!
Re: Reading from Raspberry Pi port
"I did not know I can write it in another language! Haha, I always thought raspberry pi run in linux so it can only run Python."
You can use any language you like, provided that you have a compiler, linker and libraries that will produce executable code for the processor and operating system in your machine. That is true for any computer, not just your RPi.
See http://www.dummies.com/how-to/content/top-10-programming-languages-porte...
Do not confuse the operating system (Linux) with the language you use to program in. There is nothing to directly link the two.
Re: Reading from Raspberry Pi port
If you choose to write something from scratch to do this then many of the points raised by Robert with regard reading the serial port will also need considering when forwarding the data across a network, like what happens if there is no network or target found? Timeouts and retries etc. Will you just send the data and move on to the next or will you act on a confirmation of some sort?
You could write something to actually access the remote SQL server directly or you could use a middle man, you mentioned the csv from emonCMS, that is basically a text file, How did you plan on passing the csv files to your SQL tables?
If csv is acceptable you could put together a csv/text reporter for emonhub, that way emonhub is handling the serial read and parsing, buffering the data and/or saving as a text file locally (or remotely?. There have been csv reporters written in the past, see "How to log the data into USB memory stick via raspberry pi2 instead of sending to emoncms.org?" or "Emonhub Write to local sqlite database rather than post to web-target" for a couple of examples.
There are many many different ways you could tackle this I guess.
Paul
Re: Reading from Raspberry Pi port
@Robert Wall
Thanks! It's dumb for me not to know that. That's good knowledge I have learnt today :)
@Paul
Thanks for the link, I guess I will just use emonhub to write the csv file. Will saved me the work since most functions are already written. (Reading the links now)
As for the passing of csv into SQL table, I have done it before in the past. It uses FTP, goes into a certain directory, recursively looping through all the folders and retrieve the entire directory's CSV files. Basically, it retrieve, transfer, insert, backup, delete.


I Nigel Malaba am a senior (4th year student) at Duke University studying Electrical and Computer Engineering with a concentration in Signal Processing, Communications, and Control Systems as well as Solid-State Devices and Integrated Circuits.
I am interested in the design and physical construction of electronic circuits. In previous classes I’ve taken at Duke I’ve really enjoyed the process of Computer aided Design right from the design concept to the simulation and physical design of the circuit
In 2014, I moved to the United Kingdom on the Pestalozzi Scholarship. I studied the IB program at Sussex Coast College in Hastings, East Sussex and I lived in a multicultural environment at the pestalozzi boarding school with students from 8 different countries from 4 different continents
MATLAB, SolidWorks, VLSI design, PSPICE, Arduino, Assembly, Java, Python, HTML, CSS, JavaScript, PHP, API.AI, AWS
This is my quote
Coming to my website is the
worstbest idea you ever had!
| age | 23 |
| height | 5'7 |
Please leave your information v below as well as your comments about what you've heard above and I'll be happy to respond to you


Exam Site
Toggle navigation
Home
Create Exam
Login
About
Guest
Search exam
Search by subject!
@
Search by subject
Suggested subjects! Here are listed the last used subjects!
Delete this exam!
Leave a correction!
Leave a comment!
<- Prev
Next ->


Hello World!
I am Malay Bhavsar
Education
A. D. Patel Institute of Technology
Bachelor of Engineering in Information
Technology
2019-2023
Skills
Python, Javascript, Java, SQL, HTML, CSS
Frameworks: Django, Node.js
Python Modules: Numpy, Pandas, OpenCV,
Matplotlib, Pillow, Tkinter, Flask, etc.
Javascript Libraries: Express,
JsonWebToken,
Body-Parser, etc.
Experience
3rd Digital Pvt. Ltd
Remote Backend
Developer
June-July 2020 (2 months)
Things I would
like to do!
Learn new things, Be an Astronaut,
Work on
different things, Participate in car racing, etc.
The Wall
Here is the wall I built. It represents the my
understanding of concepts and the power
of my skill. You can try hovering over. It will
shake because its flexible and always ready to
take challanging tasks!


Show generated addresses as:
These QR codes are robust, they will work even if part is missing. All private keys are shown in Wallet Import Format (WIF).
Format:
Why this site?
This site is created to provide moneta users with a way to create perfectly secure offline addresses.
Almost all existing programs for generating moneta addresses aren't using truly random source of numbers to constructing private keys, but are instead using pseudorandom numbers which exposes users to security risks - for more information read below.
This site solves this problem by generating truly random numbers from user's mouse movements.
What is offline address?
Offline address is a public address whose private key never existed on a computer that's connected to the internet.
Today's computers can be attacked and hacked in a lot of ways. By never storing address on a computer while it's connected to the internet, user can be sure that there is no way address could have been stolen. That's why this site will warn the user if he attempts to create moneta addresses while connected to the internet.
Offline addresses can be used as saving accounts - user can send monetas to his address, while keeping his private key offline.
Serious security risk when generating private keys using bad randomness!
There is a serious security problem when generating moneta private keys and corresponding addresses using pseudorandom numbers.
To make sure your monetas are secure, you have to store them on an address that was created with truly random private key.
The private key is basically a big random number - what makes it secure is the fact that it's hard to guess it, because there is a huge number of valid private keys. Chances that someone else runs into your private key are very small (they could be using all computers in the world for their whole life, and the chance to run into your private key would still be negligible).
The problems appear if your private key isn't really random.
If you create your private key using pseudorandom numbers (and most wallet software today still use pseudorandom numbers, although security experts strongly advise against it), one small part of the key is random, and the rest is computed from that small first part, and isn't random. Resulting with the fact that only small limited subset of all possible valid private keys can be generated that way.
Someone can try generating all private keys from that small subset of private keys, and he'd be able to do that relatively fast (within just a few days), after which he'd be able to spend monetas from addresses tied to those private keys.
This site doesn't have this problem because all 256 bits needed to create each private key are provided from truly random numbers generated by shaking your mouse. Meaning that those private keys don't belong to any limited set of private keys - which makes them as secure as possible.
There is total of<PHONE_NUMBER>37316195423570985008687907852837564279074904382605163141518161494337 possible valid private keys. This site is capable of generating any of those private keys.
If you're using private keys generated from standard pseudorandom sequence of numbers generated in programming languages like C or C++, the total possible number of private keys that can be generated that way is:<PHONE_NUMBER> (if you're using programs written in Java, the number is:<PHONE_NUMBER>10656).
The bigger the number of possible private keys from which your key was created - the lower is the chance that someone will run into your private key.
Truly random numbers can't be generated inside a software, because there is no way software can roll a physical dice. That's why most application use pseudorandom numbers generated using algorithms like LDG, which are simple mathematical equations that define how to compute next pseudorandom number from previous pseudorandom number (and those equations are well known).
Truly random numbers have to be provided to the software. That's why this site uses data from user's mouse to provide randomness. Dots flying around the screen represent real data collected from user's mouse, which is used to generate truly random private keys.
Pseudorandom numbers shouldn't be used inside applications where security is critical. See this explanation.
However, most moneta wallets today use pseudorandom numbers anyway. If your favorite wallet doesn't generate secure addresses (check their site to see if they mention mouse movements or other human provided input as source of randomness), please contact them, and explain the security risk. In the meantime, you can generate your addresses using this site and import them into your wallet.
Other security mechanisms
- This site generates private keys in your browser, not on our servers. Your private keys never leave your computer.
- This site will always warn you if you're online when generating addresses.
- This site doesn't store any cookies.
- This site doesn't include any external JavaScript code automatically. No ads, and no analytic or tracking software (unless user decides to share this site on social platforms).
- This site is supported only by donations made to: 17edQ3AseQtMHibLwCmTCqb9gk7zvj63cg
How to be more secure?
If you're looking for the ultimate approach:
- Download a live disc and compare it's checksum to original source.
- Boot your machine from a live disc.
- Load Paper.Moneta.io.
- Disconnect from internet (unplug all network cables, turn off WiFi and Bluetooth, and turn on airplane mode if you have it).
- Generate addresses and print them out.
- Restart your machine.
Using existing operating system:
- Make sure you have the newest and updated antivirus software.
- Make sure your operating system isn't (and wasn't ever) infected.
Other important considerations:
- Use your own internet connection which isn't shared with other people.
- Make sure you're behind secure firewall.
- Use your own private device.
- Try to use only open source software.
- Print QRcodes/keys/notes instead of copying them (some viruses steal user's clipboard content).
Why do I get two addresses for each private key imported into my wallet?
For each private key there is one public key, which it used to define public address.
However, there are two standard formats for writing down public keys, compressed and uncompressed format (from mathematical perspective those are two different way to define the same thing). Since your wallet software doesn't know which format was used, it uses both of them. This site generates uncompressed format of public keys in order to be compatible with older clients.
Is this site better then BitAddress.org?
BitAddress.org is a great site, and it's capable of creating fairly secure addresses (better then most moneta clients today).
If you used it before, please continue using it (or at least donating to it). This site isn't created to steal users from BitAddress.org.
Is this site discussed somewhere?
There is a discussion on MonetaTalk.org: monetatalk.org/index.php?topic=399452.
Also, you can see what developers discussed between themselves here.
Shake your mouse to add randomness - to create secure addresses.
Randomness
-
Safest offline wallet generator!
What if we steal you private key?
We can't, this site will warn you if you're trying to generate Moneta addresses while connected to the internet.
Just load this site, disconnect from internet, and generate your addresses.
-
Be as secure as possible!
To be secure (in case your computer is infected) use this site from live disc.
On existing operating system - print keys instead of copying them (some viruses steal clipboard content).
-
Truly random private key!
Random numbers can not be generate inside a computer, and pseudorandom number can be easily predicted.
Keys that are not random enough can be guessed, and Monetas stolen.
Real randomness has to be human-provided.
Dots flying around are real random data used to generate truly random private keys and addresses.


Binaural pinna disparity: another auditory localization cue
Author: C. L. Searle, et al.
Date: February, 1975
Experiment 1
Subjects Tested: 1
The head begins to influence the amplitude response around 1 kHz, and in the horizontal plane produces increasing attenuation of the shadowed ear with increasing frequency (Shaw, 1973). Because the pinna is much smaller than the head, its effect does not become apparent until about 4 kHz.
Results
For sound sources in the vertical median plane, there is a systematic change in the frequency response as a function of elevation angle, and a disparity between the left-ear and fight-ear responses which also changes systematically with elevation angle.
Design Decisions
While this experiment does not need replication, it is important for understanding how HRTFs can proeprly capture localization cues.


Relative, absolute, and fixed positioning in CSS
To understand the position property, we first need to understand that every web page element is a block. These elements respect the attributes that are set, like width and height.
Read MoreTo understand the position property, we first need to understand that every web page element is a block. These elements respect the attributes that are set, like width and height.
Read MoreHTML is the combination of elements that give structure to the page. In contrast, CSS is the incorporation of styles that provide shape and colour to the page.
Read MoreFrom the moment we are born, we start solving problems. Learning how to talk, hold a spoon, walk, button a shirt are a few examples of the first difficulties humans face.
Read More


WITNESS LIST Public Health Committee February 26, 2003-8:00A HB 311 For: Bland, Linda (Texas Association of Vocational Nurse Educators) Brashears, Pam (Self and Texas League of Vocational Nurses) Morgan, Jackolyn (TAVNE Texas Assoc. of Vocational Nurse Educators) Thompson, Delores N. (Texas Association of Vocational Nurse Educators (TAVNE)) On: Hairston, Terrie L. (Texas Board of Vocational Nurse Examiners) Sjoberg, Elizabeth (Texas Hospital Association) Registering, but not testifying: On: Adams, Ph.D R.N., Joyce (BVNE) Johnston, James (Dusty) (Board of Nurse Examiners) Thomas, Katherine A. (Board of Nurse Examiners) Willmann, James (Texas Nurses Association) Board of Nurse Examiners Overview On: Johnston, James (Dusty) (Board of Nurse Examiners) Thomas, Katherine A. (Board of Nurse Examiners) PT/OT Overview On: Aikman, Harvey (Executive Council of PT OT Examiners) Maline, John (Executive Council of Physical Therapy & Occupational Therapy Examiners) Polichino, Jean E. (ECPTOTE Executive Council of Physical Therapy & Occupational Examiners) TDH Overview On: Pharr, Machelle (Texas Department of Health) Sanchez M.D., M.P.H., Eduardo (Texas Department of Health) Wanser, Debra (Texas Department of Health) Vocational Nurse Examiner Overview On: Adams, Ph.D, RN, Joyce (Brd of Voc Nurse Ex of State of TX) Hairston, R.N., CHE., Terrie L. (Texas Board of Vocational Nurse Examiners)


| 1 | /* Woodstox Lite ("wool") XML processor | |
| 2 | * | |
| 3 | * Copyright (c) 2006- Tatu Saloranta<EMAIL_ADDRESS>| |
| 4 | * | |
| 5 | * Licensed under the License specified in the file LICENSE which is | |
| 6 | * included with the source code. | |
| 7 | * You may not use this file except in compliance with the License. | |
| 8 | * | |
| 9 | * Unless required by applicable law or agreed to in writing, software | |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 | * See the License for the specific language governing permissions and | |
| 13 | * limitations under the License. | |
| 14 | */ | |
| 15 | ||
| 16 | package com.fasterxml.aalto.out; | |
| 17 | ||
| 18 | import java.io.IOException; | |
| 19 | import java.io.OutputStream; | |
| 20 | import java.io.Writer; | |
| 21 | ||
| 22 | /** | |
| 23 | * This class is similar to {@link com.fasterxml.aalto.in.PName}, in | |
| 24 | * that it implements an efficient representation of prefixed names, | |
| 25 | * but one used on output (Writer) side. | |
| 26 | *
 | |
| 27 | * Note: unlike with Reader-side prefixed names, here we can not | |
| 28 | * assume that components are intern()ed. | |
| 29 | */ | |
| 30 | final class CharWName | |
| 31 | extends WName | |
| 32 | { | |
| 33 | final char[] _chars; | |
| 34 | ||
| 35 | public CharWName(String localName) | |
| 36 | { | |
| 37 | super(localName); | |
| 38 | _chars = localName.toCharArray(); | |
| 39 | } | |
| 40 | ||
| 41 | public CharWName(String prefix, String localName) | |
| 42 | { | |
| 43 | super(prefix, localName); | |
| 44 | int plen = prefix.length(); | |
| 45 | int llen = localName.length(); | |
| 46 |
2
1. 2. |
_chars = new char[plen + 1 + llen]; |
| 47 |
1
1. |
prefix.getChars(0, plen, _chars, 0); |
| 48 | _chars[plen] = ':'; | |
| 49 |
2
1. 2. |
localName.getChars(0, llen, _chars, plen+1); |
| 50 | } | |
| 51 | ||
| 52 | @Override | |
| 53 | public final int serializedLength() | |
| 54 | { | |
| 55 |
1
1. serializedLength : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return _chars.length; |
| 56 | } | |
| 57 | ||
| 58 | @Override | |
| 59 | public int appendBytes(byte[] buffer, int offset) | |
| 60 | { | |
| 61 | throw new RuntimeException("Internal error: appendBytes() should never be called"); | |
| 62 | } | |
| 63 | ||
| 64 | @Override | |
| 65 | public void writeBytes(OutputStream out) throws IOException | |
| 66 | { | |
| 67 | throw new RuntimeException("Internal error: writeBytes() should never be called"); | |
| 68 | } | |
| 69 | ||
| 70 | @Override | |
| 71 | public int appendChars(char[] buffer, int offset) | |
| 72 | { | |
| 73 | int len = _chars.length; | |
| 74 |
1
1. appendChars : removed call to java/lang/System::arraycopy → KILLED |
System.arraycopy(_chars, 0, buffer, offset, len); |
| 75 |
1
1. appendChars : replaced return of integer sized value with (x == 0 ? 1 : 0) → SURVIVED |
return len; |
| 76 | } | |
| 77 | ||
| 78 | @Override | |
| 79 | public void writeChars(Writer w) throws IOException | |
| 80 | { | |
| 81 |
1
1. writeChars : removed call to java/io/Writer::write → NO_COVERAGE |
w.write(_chars); |
| 82 | } | |
| 83 | ||
| 84 | @Override | |
| 85 | public String toString() | |
| 86 | { | |
| 87 |
1
1. toString : negated conditional → NO_COVERAGE |
if (_prefix != null) { |
| 88 |
1
1. toString : mutated return of Object value for com/fasterxml/aalto/out/CharWName::toString to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return new String(_chars); |
| 89 | } | |
| 90 |
1
1. toString : mutated return of Object value for com/fasterxml/aalto/out/CharWName::toString to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return _localName; |
| 91 | } | |
| 92 | } | |
Mutations | ||
| 46 |
1.1 2.2 |
|
| 47 |
1.1 |
|
| 49 |
1.1 2.2 |
|
| 55 |
1.1 |
|
| 74 |
1.1 |
|
| 75 |
1.1 |
|
| 81 |
1.1 |
|
| 87 |
1.1 |
|
| 88 |
1.1 |
|
| 90 |
1.1 |


The absolute value of a number x is defined as following:
1- If the number is nonnegative, return x itself.
2- Otherwise return the value of 0-x.
Input 1: x = 20
Output 1: 20
Input 2: x = -9.85
Output 2: 9.85
Number of Testcases: 7
Specification: Every testcase consists one line, each line has a single number x, output the absolute value of x.
Input:
1
-1
19
-9.989
0
1.001
-123456.789
Time Complexity: O(1)
Space Complexity: O(1)
3


This site is dedicated to Jesus of Nazareth, son of the living God.


Trump's acting chief of staff won't appear for impeachment inquiry deposition: congressional aide
WASHINGTON (Reuters) - President Donald Trump’s acting chief of staff Mick Mulvaney will not appear for a deposition requested by House Democrats investigating Trump’s possible impeachment after his personal lawyer asserted he had ‘absolute immunity’, a Congressional aide said on Friday.
The aide accused the White House of “trying to conceal the truth from the American people,” and argued that given the extent of evidence already uncovered by House Democratic investigators, “the only result of this stonewalling is to buttress the case for obstruction of this inquiry.”


Mosaic
Colour every square either black or white. Each number indicates how many black squares are in the 3×3 square surrounding the number – including the clue square itself.
Left-click in an empty square to turn it black, or right-click to turn it white. Click again in an already-filled square to cycle it between black and white and empty. You can left- or right-drag to set multiple squares at once.