Compiler/lexical analyzer: Difference between revisions

→‎{{header|Perl 6}}: Added Perl 6 solution
m (→‎{{header|Perl}}: One regex simplification, and one work-around for an annoying edge case of the split() function)
(→‎{{header|Perl 6}}: Added Perl 6 solution)
Line 1,521:
20 1 END_OF_INPUT
</pre>
 
=={{header|Perl 6}}==
 
<lang perl6>grammar C_Language {
rule TOP { ^ <all>+ %% \s* };
 
token all {
| '*' { make 'OP_MULTIPLY' }
| '/' { make 'OP_DIVIDE' }
| '+' { make 'OP_ADD' }
| '-' { make 'OP_SUBTRACT' }
| '<=' { make 'OP_LESSEQUAL' }
| '<' { make 'OP_LESS' }
| '>' { make 'OP_GREATER' }
| '!=' { make 'OP_NOTEQUAL' }
| '=' { make 'OP_ASSIGN' }
| '&&' { make 'OP_AND' }
| '(' { make 'LEFT_PAREN' }
| ')' { make 'RIGHT_PAREN' }
| '{' { make 'LEFT_BRACE' }
| '}' { make 'RIGHT_BRACE' }
| ';' { make 'SEMICOLON' }
| ',' { make 'COMMA' }
| 'if' { make 'KEYWORD_IF' }
| 'putc' { make 'KEYWORD_PUTC' }
| 'while' { make 'KEYWORD_WHILE' }
| 'print' { make 'KEYWORD_PRINT' }
| '/*' .*? '*/' { make 'COMMENT' }
| '"' .*? '"' { make 'STRING ' ~ $/.subst("\n", "\\n", :g) }
| "'" .*? "'" { make 'INTEGER ' ~ $/.subst("\\n", "\n").substr(1, *-1).ord }
| <.digit>+ { make 'INTEGER ' ~ $/ }
| <.ident>+ { make 'IDENTIFER ' ~ $/ }
}
}
 
sub parse_it ( $c_code ) {
my @pos = gather for $c_code.lines».chars.kv -> $line, $v {
take [ $line + 1, $_ ] for 1 .. ($v+1); # v+1 for newline
}
 
$/ = C_Language.parse( $c_code )
or warn "Cannot parse";
 
for $/<all>.list.grep(*.ast ne 'COMMENT') -> $m {
say join "\t", @pos[$m.from].fmt('%3d'), $m.ast;
}
 
if $c_code.substr( $/<all>[*-1].to ).trim-trailing -> $unparsed {
say "Leftover: ", $unparsed.perl;
}
}
 
parse_it( slurp('input.txt') );</lang>
 
=={{header|Python}}==
256

edits