File Coverage

blib/lib/Erlang/Parser/Lexer.pm
Criterion Covered Total %
statement 24 24 100.0
branch 6 6 100.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 36 36 100.0


line stmt bran cond sub pod time code
1             # Copyright 2011-2012 Yuki Izumi. ( anneli AT cpan DOT org )
2             # This is free software; you can redistribute it and/or modify it under the
3             # same terms as Perl itself.
4              
5             package Erlang::Parser::Lexer;
6              
7 4     4   361 use strict;
  4         3  
  4         83  
8 4     4   14 use warnings;
  4         3  
  4         86  
9              
10 4     4   1621 use Parse::Lex;
  4         55649  
  4         3614  
11              
12             # NOTE: not re-entrant due to P::L fun.
13             our $lexer_string = '';
14             our $skip_token = 0;
15             our $lex_failed = 0;
16              
17             our ($ATOM, $FLOAT, $INTEGER, $BASE_INTEGER, $LIT, $STRING, $CONTENT);
18             our ($ACONTENT, $ALIT, $AATOM, $OPENATOM);
19             our ($OPENRECORD, $RECORDACCESS);
20             our ($OPENSTRING, $WHITESPACE, $COMMENT, $LPAREN, $RPAREN, $PERIOD, $LARROW, $LDARROW, $RARROW);
21             our ($LISTOPEN, $LISTCLOSE, $DIVIDE, $ADD, $SUBTRACT, $MULTIPLY, $COMMA, $SEMICOLON, $COLON);
22             our ($ERROR, $VARIABLE, $MACRO, $TUPLEOPEN, $TUPLECLOSE, $TODODIRECTIVE, $MATCH);
23             our ($KW_CASE, $KW_RECEIVE, $KW_AFTER, $KW_OF, $KW_END, $KW_FUN, $KW_WHEN, $KW_DIV);
24             our ($OPENBINARY, $CLOSEBINARY, $LISTADD, $LISTSUBTRACT, $EQUAL, $STRICTLY_NOT_EQUAL, $STRICTLY_EQUAL);
25             our ($KW_BSL, $KW_BSR, $KW_BOR, $KW_BAND, $KW_BXOR, $KW_XOR, $KW_REM, $KW_TRY, $KW_CATCH, $LTE, $GTE, $LT, $GT);
26             our ($SEND, $LITERAL, $PIPE, $COMPREHENSION, $CATCH_CLASS, $KW_ANDALSO, $KW_ORELSE, $KW_AND, $KW_OR, $KW_BEGIN);
27             our ($KW_NOT, $KW_BNOT, $KW_IF, $NOT_EQUAL, $NEG);
28              
29             our @tokens = (
30             KW_CASE => q/case(?!\w)/,
31             KW_RECEIVE => q/receive(?!\w)/,
32             KW_AFTER => q/after(?!\w)/,
33             KW_OF => q/of(?!\w)/,
34             KW_END => q/end(?!\w)/,
35             KW_FUN => q/fun(?!\w)/,
36             KW_WHEN => q/when(?!\w)/,
37             KW_DIV => q/div(?!\w)/,
38             KW_BSL => q/bsl(?!\w)/,
39             KW_BSR => q/bsr(?!\w)/,
40             KW_BOR => q/bor(?!\w)/,
41             KW_BAND => q/band(?!\w)/,
42             KW_BXOR => q/bxor(?!\w)/,
43             KW_XOR => q/xor(?!\w)/,
44             KW_REM => q/rem(?!\w)/,
45             KW_TRY => q/try(?!\w)/,
46             KW_CATCH => q/catch(?!\w)/,
47             KW_ANDALSO => q/andalso(?!\w)/,
48             KW_AND => q/and(?!\w)/,
49             KW_ORELSE => q/orelse(?!\w)/,
50             KW_OR => q/or(?!\w)/,
51             KW_BEGIN => q/begin(?!\w)/,
52             KW_NOT => q/not(?!\w)/,
53             KW_BNOT => q/bnot(?!\w)/,
54             KW_IF => q/if(?!\w)/,
55             ATOM => q/[a-z]([\w@.]*\w)?/,
56             VARIABLE => q/[A-Z_]\w*/,
57             MACRO => q/\?(\w+)/,
58             FLOAT => q/\d+\.\d+([eE][+-]?\d+)?/,
59             BASE_INTEGER => q/\d+#[a-zA-Z0-9]+/,
60             INTEGER => q/\d+/,
61             TODODIRECTIVE => [q/-(type|opaque|spec|if|endif)/, q/.*?/, q/\.\s*($|[\r\n])/], sub {
62             $skip_token = 1;
63             },
64             OPENRECORD => q/#/,
65             RECORDACCESS => q/\.(\w+)/,
66              
67             'sqatom:ALIT' => q/\\\\./, sub {
68             $lexer_string .= substr($_[1], 1);
69             $skip_token = 1;
70             },
71             'sqatom:AATOM' => q/'/, sub {
72             $_[0]->lexer->end('sqatom');
73             $_[0]->lexer->setToken($ATOM);
74             $lexer_string;
75             },
76             'sqatom:ACONTENT' => q/[^'\\\\]+/, sub {
77             $lexer_string .= $_[1];
78             $skip_token = 1;
79             },
80             OPENATOM => q/'/, sub {
81             $_[0]->lexer->start('sqatom');
82             $lexer_string = '';
83             $skip_token = 1;
84             },
85              
86             'dqstr:LIT' => q/\\\\./, sub {
87             $lexer_string .= substr($_[1], 1);
88             $skip_token = 1;
89             },
90             'dqstr:STRING' => q/"/, sub {
91             $_[0]->lexer->end('dqstr');
92             $lexer_string;
93             },
94             'dqstr:CONTENT' => q/[^"\\\\]+/, sub {
95             $lexer_string .= $_[1];
96             $skip_token = 1;
97             },
98             OPENSTRING => q/"/, sub {
99             $_[0]->lexer->start('dqstr');
100             $lexer_string = '';
101             $skip_token = 1;
102             },
103              
104             WHITESPACE => q/\s/, sub { $skip_token = 1 },
105             COMMENT => q/%.*/, sub { $skip_token = 1 },
106              
107             LPAREN => q/\(/,
108             RPAREN => q/\)/,
109             PERIOD => q/\./,
110             LARROW => q/<-/,
111             RARROW => q/->/,
112             LDARROW => q/<=/,
113             LTE => q/=</,
114             GTE => q/>=/,
115             LISTOPEN => q/\[/,
116             LISTCLOSE => q/\]/,
117             TUPLEOPEN => q/{/,
118             TUPLECLOSE => q/}/,
119             LISTSUBTRACT => q/--/,
120             LISTADD => q/\+\+/,
121             EQUAL => q/==/,
122             STRICTLY_EQUAL => q/=:=/,
123             NOT_EQUAL => q/\/=/,
124             STRICTLY_NOT_EQUAL => q/=\/=/,
125             MATCH => q/=/,
126             DIVIDE => q/\//,
127             ADD => q/\+/,
128             SUBTRACT => q/-/,
129             MULTIPLY => q/\*/,
130             COMMA => q/,/,
131             SEMICOLON => q/;/,
132             COLON => q/:/,
133             OPENBINARY => q/<</,
134             CLOSEBINARY => q/>>/,
135             LT => q/</,
136             GT => q/>/,
137             COMPREHENSION => q/\|\|/,
138             PIPE => q/\|/,
139             SEND => q/!/,
140             LITERAL => q/\$(\\\\.|(?s:.))/,
141             ERROR => q/.*/, sub { $lex_failed = $_[1]; },
142             );
143              
144             Parse::Lex->exclusive(qw(dqstr sqatom));
145             our $lex = Parse::Lex->new(@tokens);
146             local $.;
147              
148             sub lex {
149 4     4 1 21 my $class = shift;
150 4         43 $lex->from(@_);
151              
152             sub {
153 141650     141650   3143958 my $token;
154              
155 141650         154994 $skip_token = 0;
156 141650         107294 $lex_failed = '';
157              
158 141650         93474 LOOP:while (1) {
159 173923         307298 $token = $lex->next;
160              
161 173923 100       14737563 if ($lex->eoi) {
    100          
    100          
162 2         15 return ('', undef);
163             } elsif ($lex_failed) {
164 1         152 print STDERR "can't analyse: \"", $lex_failed, "\"\n";
165 1         6 return ('', undef);
166             } elsif (not $skip_token) {
167 141647         580960 last LOOP;
168             }
169 32273         133004 $skip_token = 0;
170             }
171              
172             # print STDERR $token->name, "(", $token->text, ") ";
173 141647         256144 return ($token->name, $token->text);
174             }
175 4         136608 }
176              
177             =over 4
178              
179             =item C<lex>
180              
181             Returns an anonymous subroutine that returns a token type/content pair on each
182             invocation, and C<('', undef)> when there's no more.
183              
184             =back
185              
186             =cut
187              
188             1;
189              
190             # vim: set sw=4 ts=4: