Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,260 +0,0 @@
|
|||
with Ada.Text_IO, Ada.Streams.Stream_IO, Ada.Strings.Unbounded, Ada.Command_Line,
|
||||
Ada.Exceptions;
|
||||
use Ada.Strings, Ada.Strings.Unbounded, Ada.Streams, Ada.Exceptions;
|
||||
|
||||
procedure Main is
|
||||
package IO renames Ada.Text_IO;
|
||||
|
||||
package Lexer is
|
||||
type Token is (Op_multiply, Op_divide, Op_mod, Op_add, Op_subtract, Op_negate,
|
||||
Op_less, Op_lessequal, Op_greater, Op_greaterequal, Op_equal,
|
||||
Op_notequal, Op_not, Op_assign, Op_and, Op_or,
|
||||
|
||||
LeftParen, RightParen, LeftBrace, RightBrace, Semicolon, Comma,
|
||||
|
||||
Keyword_if, Keyword_else, Keyword_while, Keyword_print, Keyword_putc,
|
||||
Identifier, Token_Integer, Token_String, End_of_input,
|
||||
|
||||
Empty_Char_Error, Invalid_Escape_Error, Multi_Char_Error, EOF_Comment_Error,
|
||||
EOF_String_Error, EOL_String_Error, Invalid_Char_Error, Invalid_Num_Error
|
||||
);
|
||||
|
||||
subtype Operator is Token range Op_multiply .. Op_or;
|
||||
subtype Symbol is Token range Token'Succ(Operator'Last) .. Comma;
|
||||
subtype Keyword is Token range Token'Succ(Symbol'Last) .. Keyword_putc;
|
||||
subtype Error is Token range Empty_Char_Error .. Invalid_Num_Error;
|
||||
subtype Operator_or_Error is Token
|
||||
with Static_Predicate => Operator_or_Error in Operator | Error;
|
||||
|
||||
subtype Whitespace is Character
|
||||
with Static_Predicate => Whitespace in ' ' | ASCII.HT | ASCII.CR | ASCII.LF;
|
||||
|
||||
Lexer_Error : exception;
|
||||
Invalid_Escape_Code : constant Character := ASCII.NUL;
|
||||
|
||||
procedure run(input : Stream_IO.File_Type);
|
||||
end Lexer;
|
||||
|
||||
package body Lexer is
|
||||
use type Stream_IO.Count;
|
||||
|
||||
procedure run(input : Stream_IO.File_Type) is
|
||||
type State is (State_Start, State_Identifier, State_Integer, State_Char, State_String,
|
||||
State_Comment);
|
||||
curr_state : State := State_Start;
|
||||
curr_char : Character;
|
||||
curr_col, curr_row, token_col, token_row : Positive := 1;
|
||||
token_text : Unbounded_String := Unbounded.Null_Unbounded_String;
|
||||
|
||||
function look_ahead return Character is
|
||||
next_char : Character := ASCII.LF;
|
||||
begin
|
||||
if not Stream_IO.End_Of_File(input) then
|
||||
next_char := Character'Input(Stream_IO.Stream(input));
|
||||
Stream_IO.Set_Index(input, Stream_IO.Index(input) - 1);
|
||||
end if;
|
||||
return next_char;
|
||||
end look_ahead;
|
||||
|
||||
procedure next_char is
|
||||
next : Character := Character'Input(Stream_IO.Stream(input));
|
||||
begin
|
||||
curr_col := curr_col + 1;
|
||||
if curr_char = ASCII.LF then
|
||||
curr_row := curr_row + 1;
|
||||
curr_col := 1;
|
||||
end if;
|
||||
curr_char := next;
|
||||
end next_char;
|
||||
|
||||
procedure print_token(tok : Token; text : String := "") is
|
||||
procedure raise_error(text : String) is
|
||||
begin
|
||||
raise Lexer_Error with "Error: " & text;
|
||||
end;
|
||||
begin
|
||||
IO.Put(token_row'Image & ASCII.HT & token_col'Image & ASCII.HT);
|
||||
case tok is
|
||||
when Operator | Symbol | Keyword | End_of_input => IO.Put_Line(tok'Image);
|
||||
when Token_Integer => IO.Put_Line("INTEGER" & ASCII.HT & text);
|
||||
when Token_String => IO.Put_Line("STRING" & ASCII.HT & ASCII.Quotation & text & ASCII.Quotation);
|
||||
when Identifier => IO.Put_Line(tok'Image & ASCII.HT & text);
|
||||
when Empty_Char_Error => raise_error("empty character constant");
|
||||
when Invalid_Escape_Error => raise_error("unknown escape sequence: " & text);
|
||||
when Multi_Char_Error => raise_error("multi-character constant: " & text);
|
||||
when EOF_Comment_Error => raise_error("EOF in comment");
|
||||
when EOF_String_Error => raise_error("EOF in string");
|
||||
when EOL_String_Error => raise_error("EOL in string");
|
||||
when Invalid_Char_Error => raise_error("invalid character: " & curr_char);
|
||||
when Invalid_Num_Error => raise_error("invalid number: " & text);
|
||||
end case;
|
||||
end print_token;
|
||||
|
||||
procedure lookahead_choose(determiner : Character; a, b : Operator_or_Error) is
|
||||
begin
|
||||
if look_ahead = determiner then
|
||||
print_token(a);
|
||||
next_char;
|
||||
else
|
||||
print_token(b);
|
||||
end if;
|
||||
end lookahead_choose;
|
||||
|
||||
function to_escape_code(c : Character) return Character is
|
||||
begin
|
||||
case c is
|
||||
when 'n' => return ASCII.LF;
|
||||
when '\' => return '\';
|
||||
when others =>
|
||||
print_token(Invalid_Escape_Error, ASCII.Back_Slash & c);
|
||||
return Invalid_Escape_Code;
|
||||
end case;
|
||||
end to_escape_code;
|
||||
begin
|
||||
curr_char := Character'Input(Stream_IO.Stream(input));
|
||||
loop
|
||||
case curr_state is
|
||||
when State_Start =>
|
||||
token_col := curr_col;
|
||||
token_row := curr_row;
|
||||
case curr_char is
|
||||
when '*' => print_token(Op_multiply);
|
||||
when '/' =>
|
||||
if look_ahead = '*' then
|
||||
next_char;
|
||||
curr_state := State_Comment;
|
||||
else
|
||||
print_token(Op_divide);
|
||||
end if;
|
||||
when '%' => print_token(Op_mod);
|
||||
when '+' => print_token(Op_add);
|
||||
when '-' => print_token(Op_subtract);
|
||||
when '(' => print_token(LeftParen);
|
||||
when ')' => print_token(RightParen);
|
||||
when '{' => print_token(LeftBrace);
|
||||
when '}' => print_token(RightBrace);
|
||||
when ';' => print_token(Semicolon);
|
||||
when ',' => print_token(Comma);
|
||||
when '<' => lookahead_choose('=', Op_lessequal, Op_less);
|
||||
when '>' => lookahead_choose('=', Op_greaterequal, Op_greater);
|
||||
when '!' => lookahead_choose('=', Op_notequal, Op_not);
|
||||
when '=' => lookahead_choose('=', Op_equal, Op_assign);
|
||||
when '&' => lookahead_choose('&', Op_and, Invalid_Char_Error);
|
||||
when '|' => lookahead_choose('|', Op_or, Invalid_Char_Error);
|
||||
when 'a' .. 'z' | 'A' .. 'Z' | '_' =>
|
||||
Unbounded.Append(token_text, curr_char);
|
||||
curr_state := State_Identifier;
|
||||
when '0' .. '9' =>
|
||||
Unbounded.Append(token_text, curr_char);
|
||||
curr_state := State_Integer;
|
||||
when ''' => curr_state := State_Char;
|
||||
when ASCII.Quotation => curr_state := State_String;
|
||||
when Whitespace => null;
|
||||
when others => null;
|
||||
end case;
|
||||
next_char;
|
||||
|
||||
when State_Identifier =>
|
||||
case curr_char is
|
||||
when 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' =>
|
||||
Unbounded.Append(token_text, curr_char);
|
||||
next_char;
|
||||
when others =>
|
||||
if token_text = "if" then
|
||||
print_token(Keyword_if);
|
||||
elsif token_text = "else" then
|
||||
print_token(Keyword_else);
|
||||
elsif token_text = "while" then
|
||||
print_token(Keyword_while);
|
||||
elsif token_text = "print" then
|
||||
print_token(Keyword_print);
|
||||
elsif token_text = "putc" then
|
||||
print_token(Keyword_putc);
|
||||
else
|
||||
print_token(Identifier, To_String(token_text));
|
||||
end if;
|
||||
Unbounded.Set_Unbounded_String(token_text, "");
|
||||
curr_state := State_Start;
|
||||
end case;
|
||||
|
||||
when State_Integer =>
|
||||
case curr_char is
|
||||
when '0' .. '9' =>
|
||||
Unbounded.Append(token_text, curr_char);
|
||||
next_char;
|
||||
when 'a' .. 'z' | 'A' .. 'Z' | '_' =>
|
||||
print_token(Invalid_Num_Error, To_String(token_text));
|
||||
when others =>
|
||||
print_token(Token_Integer, To_String(token_text));
|
||||
Unbounded.Set_Unbounded_String(token_text, "");
|
||||
curr_state := State_Start;
|
||||
end case;
|
||||
|
||||
when State_Char =>
|
||||
case curr_char is
|
||||
when ''' =>
|
||||
if Unbounded.Length(token_text) = 0 then
|
||||
print_token(Empty_Char_Error);
|
||||
elsif Unbounded.Length(token_text) = 1 then
|
||||
print_token(Token_Integer, Character'Pos(Element(token_text, 1))'Image);
|
||||
else
|
||||
print_token(Multi_Char_Error, To_String(token_text));
|
||||
end if;
|
||||
Set_Unbounded_String(token_text, "");
|
||||
curr_state := State_Start;
|
||||
when '\' =>
|
||||
Unbounded.Append(token_text, to_escape_code(look_ahead));
|
||||
next_char;
|
||||
when others => Unbounded.Append(token_text, curr_char);
|
||||
end case;
|
||||
next_char;
|
||||
|
||||
when State_String =>
|
||||
case curr_char is
|
||||
when ASCII.Quotation =>
|
||||
print_token(Token_String, To_String(token_text));
|
||||
Set_Unbounded_String(token_text, "");
|
||||
curr_state := State_Start;
|
||||
when '\' =>
|
||||
if to_escape_code(look_ahead) /= Invalid_Escape_Code then
|
||||
Unbounded.Append(token_text, curr_char);
|
||||
end if;
|
||||
when ASCII.LF | ASCII.CR => print_token(EOL_String_Error);
|
||||
when others => Unbounded.Append(token_text, curr_char);
|
||||
end case;
|
||||
next_char;
|
||||
|
||||
when State_Comment =>
|
||||
case curr_char is
|
||||
when '*' =>
|
||||
if look_ahead = '/' then
|
||||
next_char;
|
||||
curr_state := State_Start;
|
||||
end if;
|
||||
when others => null;
|
||||
end case;
|
||||
next_char;
|
||||
end case;
|
||||
end loop;
|
||||
exception
|
||||
when error : Stream_IO.End_Error =>
|
||||
if curr_state = State_String then
|
||||
print_token(EOF_String_Error);
|
||||
else
|
||||
print_token(End_of_input);
|
||||
end if;
|
||||
when error : Lexer.Lexer_Error => IO.Put_Line(Exception_Message(error));
|
||||
end run;
|
||||
end Lexer;
|
||||
|
||||
source_file : Stream_IO.File_Type;
|
||||
begin
|
||||
if Ada.Command_Line.Argument_Count < 1 then
|
||||
IO.Put_Line("usage: lex [filename]");
|
||||
return;
|
||||
end if;
|
||||
Stream_IO.Open(source_file, Stream_IO.In_File, Ada.Command_Line.Argument(1));
|
||||
Lexer.run(source_file);
|
||||
exception
|
||||
when error : others => IO.Put_Line("Error: " & Exception_Message(error));
|
||||
end Main;
|
||||
|
|
@ -1,407 +0,0 @@
|
|||
>>SOURCE FORMAT IS FREE
|
||||
*> this code is dedicated to the public domain
|
||||
*> (GnuCOBOL) 2.3-dev.0
|
||||
identification division.
|
||||
program-id. lexer.
|
||||
environment division.
|
||||
configuration section.
|
||||
repository. function all intrinsic.
|
||||
input-output section.
|
||||
file-control.
|
||||
select input-file assign using input-name
|
||||
status input-status
|
||||
organization line sequential.
|
||||
data division.
|
||||
|
||||
file section.
|
||||
fd input-file.
|
||||
01 input-record pic x(98).
|
||||
|
||||
working-storage section.
|
||||
01 input-name pic x(32).
|
||||
01 input-status pic xx.
|
||||
01 input-length pic 99.
|
||||
|
||||
01 output-name pic x(32) value spaces.
|
||||
01 output-status pic xx.
|
||||
01 output-record pic x(64).
|
||||
|
||||
01 line-no pic 999 value 0.
|
||||
01 col-no pic 99.
|
||||
01 col-no-max pic 99.
|
||||
01 col-increment pic 9 value 1.
|
||||
01 start-col pic 99.
|
||||
01 outx pic 99.
|
||||
01 out-lim pic 99 value 48.
|
||||
|
||||
01 output-line value spaces.
|
||||
03 out-line pic zzzz9.
|
||||
03 out-column pic zzzzzz9.
|
||||
03 message-area.
|
||||
05 filler pic xxx.
|
||||
05 token pic x(16).
|
||||
05 out-value pic x(48).
|
||||
05 out-integer redefines out-value pic zzzzz9.
|
||||
05 out-integer1 redefines out-value pic zzzzzz9. *> to match the python lexer
|
||||
|
||||
01 error-record.
|
||||
03 error-line pic zzzz9 value 0.
|
||||
03 error-col pic zzzzzz9 value 0.
|
||||
03 error-message pic x(68) value spaces.
|
||||
|
||||
01 scan-state pic x(16) value spaces.
|
||||
01 current-character pic x.
|
||||
01 previous-character pic x.
|
||||
|
||||
procedure division chaining input-name.
|
||||
start-lexer.
|
||||
if input-name <> spaces
|
||||
open input input-file
|
||||
if input-status = '35'
|
||||
string 'in lexer ' trim(input-name) ' not found' into error-message
|
||||
perform report-error
|
||||
end-if
|
||||
end-if
|
||||
perform read-input-file
|
||||
perform until input-status <> '00'
|
||||
add 1 to line-no
|
||||
move line-no to out-line
|
||||
move length(trim(input-record,trailing)) to col-no-max
|
||||
move 1 to col-no
|
||||
move space to previous-character
|
||||
perform until col-no > col-no-max
|
||||
move col-no to out-column
|
||||
move input-record(col-no:1) to current-character
|
||||
evaluate scan-state
|
||||
|
||||
when 'identifier'
|
||||
if current-character >= 'A' and <= 'Z'
|
||||
or (current-character >= 'a' and <= 'z')
|
||||
or (current-character >= '0' and <= '9')
|
||||
or current-character = '_'
|
||||
perform increment-outx
|
||||
move current-character to out-value(outx:1)
|
||||
if col-no = col-no-max
|
||||
perform process-identifier
|
||||
end-if
|
||||
else
|
||||
perform process-identifier
|
||||
if current-character <> space
|
||||
move 0 to col-increment
|
||||
end-if
|
||||
end-if
|
||||
|
||||
when 'integer'
|
||||
evaluate true
|
||||
when current-character >= '0' and <= '9'
|
||||
perform increment-outx
|
||||
move current-character to out-value(outx:1)
|
||||
if col-no = col-no-max
|
||||
move numval(out-value) to out-integer
|
||||
move 'Integer' to token
|
||||
end-if
|
||||
when current-character >= 'A' and <= 'Z'
|
||||
when current-character >= 'a' and <= 'z'
|
||||
move 'in lexer invalid integer' to error-message
|
||||
perform report-error
|
||||
when other
|
||||
if outx > 5
|
||||
move numval(out-value) to out-integer1 *> to match the python lexer
|
||||
else
|
||||
move numval(out-value) to out-integer
|
||||
end-if
|
||||
move 'Integer' to token
|
||||
if current-character <> space
|
||||
move 0 to col-increment
|
||||
end-if
|
||||
end-evaluate
|
||||
|
||||
when 'comment'
|
||||
if previous-character = '*' and current-character = '/'
|
||||
move 'comment' to token
|
||||
end-if
|
||||
|
||||
when 'quote'
|
||||
evaluate current-character also outx
|
||||
when '"' also 0
|
||||
string 'in lexer empty string' into error-message
|
||||
perform report-error
|
||||
when '"' also any
|
||||
perform increment-outx
|
||||
move current-character to out-value(outx:1)
|
||||
move 'String' to token
|
||||
when other
|
||||
if col-no = col-no-max
|
||||
string 'in lexer missing close quote' into error-message
|
||||
perform report-error
|
||||
else
|
||||
perform increment-outx
|
||||
move current-character to out-value(outx:1)
|
||||
end-if
|
||||
end-evaluate
|
||||
|
||||
when 'character'
|
||||
evaluate current-character also outx
|
||||
when "'" also 0
|
||||
string 'in lexer empty character constant' into error-message
|
||||
perform report-error
|
||||
when "'" also 1
|
||||
subtract 1 from ord(out-value(1:1)) giving out-integer
|
||||
move 'Integer' to token
|
||||
when "'" also 2
|
||||
evaluate true
|
||||
when out-value(1:2) = '\n'
|
||||
move 10 to out-integer
|
||||
when out-value(1:2) = '\\'
|
||||
subtract 1 from ord('\') giving out-integer *> ' (workaround a Rosetta Code highlighter problem)
|
||||
when other
|
||||
string 'in lexer unknown escape sequence ' out-value(1:2)
|
||||
into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
move 'Integer' to token
|
||||
when "'" also any
|
||||
string 'in lexer multicharacter constant' into error-message
|
||||
perform report-error
|
||||
when other
|
||||
if col-no = col-no-max
|
||||
string 'in lexer missing close quote' into error-message
|
||||
perform report-error
|
||||
end-if
|
||||
perform increment-outx
|
||||
move current-character to out-value(outx:1)
|
||||
end-evaluate
|
||||
|
||||
when 'and'
|
||||
evaluate previous-character also current-character
|
||||
when '&' also '&'
|
||||
move 'Op_and' to token
|
||||
when other
|
||||
string 'in lexer AND error' into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
|
||||
when 'or'
|
||||
evaluate previous-character also current-character
|
||||
when '|' also '|'
|
||||
move 'Op_or' to token
|
||||
when other
|
||||
string 'in lexer OR error' into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
|
||||
when 'ambiguous'
|
||||
evaluate previous-character also current-character
|
||||
when '/' also '*'
|
||||
move 'comment' to scan-state
|
||||
subtract 1 from col-no giving start-col
|
||||
when '/' also any
|
||||
move 'Op_divide' to token
|
||||
move 0 to col-increment
|
||||
|
||||
when '=' also '='
|
||||
move 'Op_equal' to token
|
||||
when '=' also any
|
||||
move 'Op_assign' to token
|
||||
move 0 to col-increment
|
||||
|
||||
when '<' also '='
|
||||
move 'Op_lessequal' to token
|
||||
when '<' also any
|
||||
move 'Op_less' to token
|
||||
move 0 to col-increment
|
||||
|
||||
when '>' also '='
|
||||
move 'Op_greaterequal' to token
|
||||
when '>'also any
|
||||
move 'Op_greater' to token
|
||||
move 0 to col-increment
|
||||
|
||||
when '!' also '='
|
||||
move 'Op_notequal' to token
|
||||
when '!' also any
|
||||
move 'Op_not' to token
|
||||
move 0 to col-increment
|
||||
|
||||
when other
|
||||
display input-record
|
||||
string 'in lexer ' trim(scan-state)
|
||||
' unknown character "' current-character '"'
|
||||
' with previous character "' previous-character '"'
|
||||
into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
|
||||
when other
|
||||
move col-no to start-col
|
||||
evaluate current-character
|
||||
when space
|
||||
continue
|
||||
when >= 'A' and <= 'Z'
|
||||
when >= 'a' and <= 'z'
|
||||
move 'identifier' to scan-state
|
||||
move 1 to outx
|
||||
move current-character to out-value
|
||||
when >= '0' and <= '9'
|
||||
move 'integer' to scan-state
|
||||
move 1 to outx
|
||||
move current-character to out-value
|
||||
when '&'
|
||||
move 'and' to scan-state
|
||||
when '|'
|
||||
move 'or' to scan-state
|
||||
when '"'
|
||||
move 'quote' to scan-state
|
||||
move 1 to outx
|
||||
move current-character to out-value
|
||||
when "'"
|
||||
move 'character' to scan-state
|
||||
move 0 to outx
|
||||
when '{'
|
||||
move 'LeftBrace' to token
|
||||
when '}'
|
||||
move 'RightBrace' to token
|
||||
when '('
|
||||
move 'LeftParen' to token
|
||||
when ')'
|
||||
move 'RightParen' to token
|
||||
when '+'
|
||||
move 'Op_add' to token
|
||||
when '-'
|
||||
move 'Op_subtract' to token
|
||||
when '*'
|
||||
move 'Op_multiply' to token
|
||||
when '%'
|
||||
move 'Op_mod' to token
|
||||
when ';'
|
||||
move 'Semicolon' to token
|
||||
when ','
|
||||
move 'Comma' to token
|
||||
when '/'
|
||||
when '<'
|
||||
when '>'
|
||||
when '='
|
||||
when '='
|
||||
when '<'
|
||||
when '>'
|
||||
when '!'
|
||||
move 'ambiguous' to scan-state
|
||||
when other
|
||||
string 'in lexer unknown character "' current-character '"'
|
||||
into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
end-evaluate
|
||||
|
||||
if token <> spaces
|
||||
perform process-token
|
||||
end-if
|
||||
|
||||
move current-character to previous-character
|
||||
add col-increment to col-no
|
||||
move 1 to col-increment
|
||||
end-perform
|
||||
if scan-state = 'ambiguous'
|
||||
evaluate previous-character
|
||||
when '/'
|
||||
move 'Op_divide' to token
|
||||
perform process-token
|
||||
|
||||
when '='
|
||||
move 'Op_assign' to token
|
||||
perform process-token
|
||||
|
||||
when '<'
|
||||
move 'Op_less' to token
|
||||
perform process-token
|
||||
|
||||
when '>'
|
||||
move 'Op_greater' to token
|
||||
perform process-token
|
||||
|
||||
when '!'
|
||||
move 'Op_not' to token
|
||||
perform process-token
|
||||
|
||||
when other
|
||||
string 'in lexer unresolved ambiguous
|
||||
"' previous-character '" at end of line'
|
||||
into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
end-if
|
||||
perform read-input-file
|
||||
end-perform
|
||||
|
||||
evaluate true
|
||||
when input-status <> '10'
|
||||
string 'in lexer ' trim(input-name) ' invalid input status ' input-status
|
||||
into error-message
|
||||
perform report-error
|
||||
when scan-state = 'comment'
|
||||
string 'in lexer unclosed comment at end of input' into error-message
|
||||
perform report-error
|
||||
end-evaluate
|
||||
|
||||
move 'End_of_input' to token
|
||||
move 1 to out-column
|
||||
move 1 to start-col
|
||||
add 1 to line-no
|
||||
perform process-token
|
||||
|
||||
close input-file
|
||||
stop run
|
||||
.
|
||||
process-identifier.
|
||||
evaluate true
|
||||
when out-value = 'print'
|
||||
move 'Keyword_print' to token
|
||||
move spaces to out-value
|
||||
when out-value = 'while'
|
||||
move 'Keyword_while' to token
|
||||
move spaces to out-value
|
||||
when out-value = 'if'
|
||||
move 'Keyword_if' to token
|
||||
move spaces to out-value
|
||||
when out-value = 'else'
|
||||
move 'Keyword_else' to token
|
||||
move spaces to out-value
|
||||
when out-value = 'putc'
|
||||
move 'Keyword_putc' to token
|
||||
move spaces to out-value
|
||||
when other
|
||||
move 'Identifier' to token
|
||||
end-evaluate
|
||||
.
|
||||
increment-outx.
|
||||
if outx >= out-lim
|
||||
string 'in lexer token value length exceeds ' out-lim into error-message
|
||||
perform report-error
|
||||
end-if
|
||||
add 1 to outx
|
||||
.
|
||||
process-token.
|
||||
if token <> 'comment'
|
||||
move start-col to out-column
|
||||
move line-no to out-line
|
||||
display output-line
|
||||
end-if
|
||||
move 0 to start-col
|
||||
move spaces to scan-state message-area
|
||||
.
|
||||
report-error.
|
||||
move line-no to error-line
|
||||
move start-col to error-col
|
||||
display error-record
|
||||
close input-file
|
||||
stop run with error status -1
|
||||
.
|
||||
read-input-file.
|
||||
if input-name = spaces
|
||||
move '00' to input-status
|
||||
accept input-record on exception move '10' to input-status end-accept
|
||||
else
|
||||
read input-file
|
||||
end-if
|
||||
.
|
||||
end program lexer.
|
||||
|
|
@ -1,419 +0,0 @@
|
|||
#!/usr/bin/emacs --script
|
||||
;;
|
||||
;; The Rosetta Code lexical analyzer in GNU Emacs Lisp.
|
||||
;;
|
||||
;; Migrated from the ATS. However, Emacs Lisp is not friendly to the
|
||||
;; functional style of the ATS implementation; therefore the
|
||||
;; differences are vast.
|
||||
;;
|
||||
;; (A Scheme migration could easily, on the other hand, have been
|
||||
;; almost exact. It is interesting to contrast Lisp dialects and see
|
||||
;; how huge the differences are.)
|
||||
;;
|
||||
;; The script currently takes input only from standard input and
|
||||
;; writes the token stream only to standard output.
|
||||
;;
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
;;; The type of a character, consisting of its code point and where it
|
||||
;;; occurred in the text.
|
||||
(cl-defstruct (ch_t (:constructor make-ch (ichar line-no column-no)))
|
||||
ichar line-no column-no)
|
||||
|
||||
(defun ch-ichar (ch)
|
||||
(ch_t-ichar ch))
|
||||
|
||||
(defun ch-line-no (ch)
|
||||
(ch_t-line-no ch))
|
||||
|
||||
(defun ch-column-no (ch)
|
||||
(ch_t-column-no ch))
|
||||
|
||||
;;; The type of an "inputter", consisting of an open file for the
|
||||
;;; text, a pushback buffer (which is an indefinitely deep stack of
|
||||
;;; ch_t), an input buffer for the current line, and a position in the
|
||||
;;; text.
|
||||
(cl-defstruct inp_t file pushback line line-no column-no)
|
||||
|
||||
(defun make-inp (file)
|
||||
"Initialize a new inp_t."
|
||||
(make-inp_t :file file
|
||||
:pushback '()
|
||||
:line ""
|
||||
:line-no 0
|
||||
:column-no 0))
|
||||
|
||||
(defvar inp (make-inp t)
|
||||
"A global inp_t.")
|
||||
|
||||
(defun get-ch ()
|
||||
"Get a ch_t, either from the pushback buffer or from the input."
|
||||
(pcase (inp_t-pushback inp)
|
||||
(`(,ch . ,tail)
|
||||
;; Emacs Lisp has only single value return, so the results come
|
||||
;; back as a list rather than multiple values.
|
||||
(setq inp (make-inp_t :file (inp_t-file inp)
|
||||
:pushback tail
|
||||
:line (inp_t-line inp)
|
||||
:line-no (inp_t-line-no inp)
|
||||
:column-no (inp_t-column-no inp)))
|
||||
ch)
|
||||
('()
|
||||
(let ((line (inp_t-line inp))
|
||||
(line-no (inp_t-line-no inp))
|
||||
(column-no (inp_t-column-no inp)))
|
||||
(when (string= line "")
|
||||
;; Refill the buffer.
|
||||
(let ((text
|
||||
(condition-case nil (read-string "")
|
||||
nil (error 'eoi))))
|
||||
(if (eq text 'eoi)
|
||||
(setq line 'eoi)
|
||||
(setq line (format "%s%c" text ?\n)))
|
||||
(setq line-no (1+ line-no))
|
||||
(setq column-no 1)))
|
||||
(if (eq line 'eoi)
|
||||
(progn
|
||||
(setq inp (make-inp_t :file (inp_t-file inp)
|
||||
:pushback (inp_t-pushback inp)
|
||||
:line line
|
||||
:line-no line-no
|
||||
:column-no column-no))
|
||||
(make-ch 'eoi line-no column-no))
|
||||
(let ((c (elt line 0))
|
||||
(line (substring line 1)))
|
||||
(setq inp (make-inp_t :file (inp_t-file inp)
|
||||
:pushback (inp_t-pushback inp)
|
||||
:line line
|
||||
:line-no line-no
|
||||
:column-no (1+ column-no)))
|
||||
(make-ch c line-no column-no)))))))
|
||||
|
||||
(defun get-new-line (file)
|
||||
;; Currently "file" is ignored and the input must be from stdin.
|
||||
(read-from-minibuffer "" :default 'eoi))
|
||||
|
||||
(defun push-back (ch)
|
||||
"Push back a ch_t."
|
||||
(setq inp (make-inp_t :file (inp_t-file inp)
|
||||
:pushback (cons ch (inp_t-pushback inp))
|
||||
:line (inp_t-line inp)
|
||||
:line-no (inp_t-line-no inp)
|
||||
:column-no (inp_t-column-no inp))))
|
||||
|
||||
(defun get-position ()
|
||||
"Return the line-no and column-no of the next ch_t to be
|
||||
returned by get-ch, assuming there are no more pushbacks
|
||||
beforehand."
|
||||
(let* ((ch (get-ch))
|
||||
(line-no (ch-line-no ch))
|
||||
(column-no (ch-column-no ch)))
|
||||
(push-back ch)
|
||||
(list line-no column-no)))
|
||||
|
||||
(defun scan-text (outf)
|
||||
"The main loop."
|
||||
(cl-loop for toktup = (get-next-token)
|
||||
do (print-token outf toktup)
|
||||
until (string= (elt toktup 0) "End_of_input")))
|
||||
|
||||
(defun print-token (outf toktup)
|
||||
"Print a token, along with its position and possibly an
|
||||
argument."
|
||||
;; Currently outf is ignored, and the output goes to stdout.
|
||||
(pcase toktup
|
||||
(`(,tok ,arg ,line-no ,column-no)
|
||||
(princ (format "%5d %5d %s" line-no column-no tok))
|
||||
(pcase tok
|
||||
("Identifier" (princ (format " %s\n" arg)))
|
||||
("Integer" (princ (format " %s\n" arg)))
|
||||
("String" (princ (format " %s\n" arg)))
|
||||
(_ (princ "\n"))))))
|
||||
|
||||
(defun get-next-token ()
|
||||
"The token dispatcher. Returns the next token, as a list along
|
||||
with its argument and text position."
|
||||
(skip-spaces-and-comments)
|
||||
(let* ((ch (get-ch))
|
||||
(ln (ch-line-no ch))
|
||||
(cn (ch-column-no ch)))
|
||||
(pcase (ch-ichar ch)
|
||||
('eoi (list "End_of_input" "" ln cn))
|
||||
(?, (list "Comma" "," ln cn))
|
||||
(?\N{SEMICOLON} (list "Semicolon" ";" ln cn))
|
||||
(?\N{LEFT PARENTHESIS} (list "LeftParen" "(" ln cn))
|
||||
(?\N{RIGHT PARENTHESIS} (list "RightParen" ")" ln cn))
|
||||
(?{ (list "LeftBrace" "{" ln cn))
|
||||
(?} (list "RightBrace" "}" ln cn))
|
||||
(?* (list "Op_multiply" "*" ln cn))
|
||||
(?/ (list "Op_divide" "/" ln cn))
|
||||
(?% (list "Op_mod" "%" ln cn))
|
||||
(?+ (list "Op_add" "+" ln cn))
|
||||
(?- (list "Op_subtract" "-" ln cn))
|
||||
(?< (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?= (list "Op_lessequal" "<=" ln cn))
|
||||
(_ (push-back ch1)
|
||||
(list "Op_less" "<" ln cn)))))
|
||||
(?> (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?= (list "Op_greaterequal" ">=" ln cn))
|
||||
(_ (push-back ch1)
|
||||
(list "Op_greater" ">" ln cn)))))
|
||||
(?= (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?= (list "Op_equal" "==" ln cn))
|
||||
(_ (push-back ch1)
|
||||
(list "Op_assign" "=" ln cn)))))
|
||||
(?! (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?= (list "Op_notequal" "!=" ln cn))
|
||||
(_ (push-back ch1)
|
||||
(list "Op_not" "!" ln cn)))))
|
||||
(?& (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?& (list "Op_and" "&&" ln cn))
|
||||
(_ (unexpected-character ln cn (get-ichar ch))))))
|
||||
(?| (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?| (list "Op_or" "||" ln cn))
|
||||
(_ (unexpected-character ln cn (get-ichar ch))))))
|
||||
(?\N{QUOTATION MARK} (push-back ch) (scan-string-literal))
|
||||
(?\N{APOSTROPHE} (push-back ch) (scan-character-literal))
|
||||
((pred digitp) (push-back ch) (scan-integer-literal))
|
||||
((pred identifier-start-p)
|
||||
(progn
|
||||
(push-back ch)
|
||||
(scan-identifier-or-reserved-word)))
|
||||
(c (unexpected-character ln cn c)))))
|
||||
|
||||
(defun skip-spaces-and-comments ()
|
||||
"Skip spaces and comments. A comment is treated as equivalent
|
||||
to a run of spaces."
|
||||
(cl-loop for ch = (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?/ (let* ((ch2 (get-ch))
|
||||
(line-no (ch-line-no ch1))
|
||||
(column-no (ch-column-no ch1))
|
||||
(position `(,line-no ,column-no)))
|
||||
(pcase (ch-ichar ch2)
|
||||
(?* (scan-comment position)
|
||||
(get-ch))
|
||||
(_ (push-back ch2)
|
||||
ch1))))
|
||||
(_ ch1)))
|
||||
while (spacep (ch-ichar ch))
|
||||
finally do (push-back ch)))
|
||||
|
||||
(defun scan-comment (position)
|
||||
(cl-loop for ch = (get-ch)
|
||||
for done = (comment-done-p ch position)
|
||||
until done))
|
||||
|
||||
(defun comment-done-p (ch position)
|
||||
(pcase (ch-ichar ch)
|
||||
('eoi (apply 'unterminated-comment position))
|
||||
(?* (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
('eoi (apply 'unterminated-comment position))
|
||||
(?/ t)
|
||||
(_ nil))))
|
||||
(_ nil)))
|
||||
|
||||
(defun scan-integer-literal ()
|
||||
"Scan an integer literal, on the assumption that a digit has
|
||||
been seen and pushed back."
|
||||
(let* ((position (get-position))
|
||||
(lst (scan-word))
|
||||
(s (list-to-string lst)))
|
||||
(if (all-digits-p lst)
|
||||
`("Integer" ,s . ,position)
|
||||
(apply 'illegal-integer-literal `(,@position , s)))))
|
||||
|
||||
(defun scan-identifier-or-reserved-word ()
|
||||
"Scan an identifier or reserved word, on the assumption that a
|
||||
legal first character (for an identifier) has been seen and
|
||||
pushed back."
|
||||
(let* ((position (get-position))
|
||||
(lst (scan-word))
|
||||
(s (list-to-string lst))
|
||||
(tok (pcase s
|
||||
("else" "Keyword_else")
|
||||
("if" "Keyword_if")
|
||||
("while" "Keyword_while")
|
||||
("print" "Keyword_print")
|
||||
("putc" "Keyword_putc")
|
||||
(_ "Identifier"))))
|
||||
`(,tok ,s . ,position)))
|
||||
|
||||
(defun scan-word ()
|
||||
(cl-loop for ch = (get-ch)
|
||||
while (identifier-continuation-p (ch-ichar ch))
|
||||
collect (ch-ichar ch)
|
||||
finally do (push-back ch)))
|
||||
|
||||
(defun scan-string-literal ()
|
||||
"Scan a string literal, on the assumption that a double quote
|
||||
has been seen and pushed back."
|
||||
(let* ((ch (get-ch))
|
||||
(_ (cl-assert (= (ch-ichar ch) ?\N{QUOTATION MARK})))
|
||||
(line-no (ch-line-no ch))
|
||||
(column-no (ch-column-no ch))
|
||||
(position `(,line-no ,column-no))
|
||||
(lst (scan-str-lit position))
|
||||
(lst `(?\N{QUOTATION MARK} ,@lst ?\N{QUOTATION MARK})))
|
||||
`("String" ,(list-to-string lst) . ,position)))
|
||||
|
||||
(defun scan-str-lit (position)
|
||||
(flatten
|
||||
(cl-loop for ch = (get-ch)
|
||||
until (= (ch-ichar ch) ?\N{QUOTATION MARK})
|
||||
collect (process-str-lit-character
|
||||
(ch-ichar ch) position))))
|
||||
|
||||
(defun process-str-lit-character (c position)
|
||||
;; NOTE: This script might insert a newline before any eoi, so that
|
||||
;; "end-of-input-in-string-literal" never actually occurs. It is a
|
||||
;; peculiarity of the script's input mechanism.
|
||||
(pcase c
|
||||
('eoi (apply 'end-of-input-in-string-literal position))
|
||||
(?\n (apply 'end-of-line-in-string-literal position))
|
||||
(?\\ (let ((ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
(?n '(?\\ ?n))
|
||||
(?\\ '(?\\ ?\\))
|
||||
(c (unsupported-escape (ch-line-no ch1)
|
||||
(ch-column-no ch1)
|
||||
c)))))
|
||||
(c c)))
|
||||
|
||||
(defun scan-character-literal ()
|
||||
"Scan a character literal, on the assumption that an ASCII
|
||||
single quote (that is, a Unicode APOSTROPHE) has been seen and
|
||||
pushed back."
|
||||
(let* ((toktup (scan-character-literal-without-checking-end))
|
||||
(line-no (elt toktup 2))
|
||||
(column-no (elt toktup 3))
|
||||
(position (list line-no column-no)))
|
||||
(check-char-lit-end position)
|
||||
toktup))
|
||||
|
||||
(defun check-char-lit-end (position)
|
||||
(let ((ch (get-ch)))
|
||||
(unless (and (integerp (ch-ichar ch))
|
||||
(= (ch-ichar ch) ?\N{APOSTROPHE}))
|
||||
(push-back ch)
|
||||
(loop-to-char-lit-end position))))
|
||||
|
||||
(defun loop-to-char-lit-end (position)
|
||||
(cl-loop for ch = (get-ch)
|
||||
until (or (eq (ch-ichar ch) 'eoi)
|
||||
(= (ch-ichar ch) ?\N{APOSTROPHE}))
|
||||
finally do (if (eq (ch-ichar ch) 'eoi)
|
||||
(apply 'unterminated-character-literal
|
||||
position)
|
||||
(apply 'multicharacter-literal position))))
|
||||
|
||||
(defun scan-character-literal-without-checking-end ()
|
||||
(let* ((ch (get-ch))
|
||||
(_ (cl-assert (= (ch-ichar ch) ?\N{APOSTROPHE})))
|
||||
(line-no (ch-line-no ch))
|
||||
(column-no (ch-column-no ch))
|
||||
(position (list line-no column-no))
|
||||
(ch1 (get-ch)))
|
||||
(pcase (ch-ichar ch1)
|
||||
('eoi (apply 'unterminated-character-literal position))
|
||||
(?\\ (let ((ch2 (get-ch)))
|
||||
(pcase (ch-ichar ch2)
|
||||
('eoi (apply 'unterminated-character-literal position))
|
||||
(?n `("Integer" ,(format "%d" ?\n) . ,position))
|
||||
(?\\ `("Integer" ,(format "%d" ?\\) . ,position))
|
||||
(c (unsupported-escape (ch-line-no ch1)
|
||||
(ch-column-no ch1)
|
||||
c)))))
|
||||
(c `("Integer" ,(format "%d" c) . ,position)))))
|
||||
|
||||
(defun spacep (c)
|
||||
(and (integerp c) (or (= c ?\N{SPACE})
|
||||
(and (<= 9 c) (<= c 13)))))
|
||||
|
||||
(defun digitp (c)
|
||||
(and (integerp c) (<= ?0 c) (<= c ?9)))
|
||||
|
||||
(defun lowerp (c)
|
||||
;; Warning: in EBCDIC, this kind of test for "alphabetic" is no
|
||||
;; good. The letters are not contiguous.
|
||||
(and (integerp c) (<= ?a c) (<= c ?z)))
|
||||
|
||||
(defun upperp (c)
|
||||
;; Warning: in EBCDIC, this kind of test for "alphabetic" is no
|
||||
;; good. The letters are not contiguous.
|
||||
(and (integerp c) (<= ?A c) (<= c ?Z)))
|
||||
|
||||
(defun alphap (c)
|
||||
(or (lowerp c) (upperp c)))
|
||||
|
||||
(defun identifier-start-p (c)
|
||||
(and (integerp c) (or (alphap c) (= c ?_))))
|
||||
|
||||
(defun identifier-continuation-p (c)
|
||||
(and (integerp c) (or (alphap c) (= c ?_) (digitp c))))
|
||||
|
||||
(defun all-digits-p (thing)
|
||||
(cl-loop for c in thing
|
||||
if (not (digitp c)) return nil
|
||||
finally return t))
|
||||
|
||||
(defun list-to-string (lst)
|
||||
"Convert a list of characters to a string."
|
||||
(apply 'string lst))
|
||||
|
||||
(defun flatten (lst)
|
||||
"Flatten nested lists. (The implementation is recursive and not
|
||||
for very long lists.)"
|
||||
(pcase lst
|
||||
('() '())
|
||||
(`(,head . ,tail)
|
||||
(if (listp head)
|
||||
(append (flatten head) (flatten tail))
|
||||
(cons head (flatten tail))))))
|
||||
|
||||
(defun unexpected-character (line-no column-no c)
|
||||
(error (format "unexpected character '%c' at %d:%d"
|
||||
c line-no column-no)))
|
||||
|
||||
(defun unsupported-escape (line-no column-no c)
|
||||
(error (format "unsupported escape \\%c at %d:%d"
|
||||
c line-no column-no)))
|
||||
|
||||
(defun illegal-integer-literal (line-no column-no s)
|
||||
(error (format "illegal integer literal \"%s\" at %d:%d"
|
||||
s line-no column-no)))
|
||||
|
||||
(defun unterminated-character-literal (line-no column-no)
|
||||
(error (format "unterminated character literal starting at %d:%d"
|
||||
line-no column-no)))
|
||||
|
||||
(defun multicharacter-literal (line-no column-no)
|
||||
(error (format
|
||||
"unsupported multicharacter literal starting at %d:%d"
|
||||
line-no column-no)))
|
||||
|
||||
(defun end-of-input-in-string-literal (line-no column-no)
|
||||
(error (format "end of input in string literal starting at %d:%d"
|
||||
line-no column-no)))
|
||||
|
||||
(defun end-of-line-in-string-literal (line-no column-no)
|
||||
(error (format "end of line in string literal starting at %d:%d"
|
||||
line-no column-no)))
|
||||
|
||||
(defun unterminated-comment (line-no column-no)
|
||||
(error (format "unterminated comment starting at %d:%d"
|
||||
line-no column-no)))
|
||||
|
||||
(defun main ()
|
||||
(setq inp (make-inp t))
|
||||
(scan-text t))
|
||||
|
||||
(main)
|
||||
|
|
@ -1,226 +0,0 @@
|
|||
include std/io.e
|
||||
include std/map.e
|
||||
include std/types.e
|
||||
include std/convert.e
|
||||
|
||||
constant true = 1, false = 0, EOF = -1
|
||||
|
||||
enum tk_EOI, tk_Mul, tk_Div, tk_Mod, tk_Add, tk_Sub, tk_Negate, tk_Not, tk_Lss, tk_Leq,
|
||||
tk_Gtr, tk_Geq, tk_Eq, tk_Neq, tk_Assign, tk_And, tk_Or, tk_If, tk_Else, tk_While,
|
||||
tk_Print, tk_Putc, tk_Lparen, tk_Rparen, tk_Lbrace, tk_Rbrace, tk_Semi, tk_Comma,
|
||||
tk_Ident, tk_Integer, tk_String
|
||||
|
||||
constant all_syms = {"End_of_input", "Op_multiply", "Op_divide", "Op_mod", "Op_add",
|
||||
"Op_subtract", "Op_negate", "Op_not", "Op_less", "Op_lessequal", "Op_greater",
|
||||
"Op_greaterequal", "Op_equal", "Op_notequal", "Op_assign", "Op_and", "Op_or",
|
||||
"Keyword_if", "Keyword_else", "Keyword_while", "Keyword_print", "Keyword_putc",
|
||||
"LeftParen", "RightParen", "LeftBrace", "RightBrace", "Semicolon", "Comma",
|
||||
"Identifier", "Integer", "String"}
|
||||
|
||||
integer input_file, the_ch = ' ', the_col = 0, the_line = 1
|
||||
sequence symbols
|
||||
map key_words = new()
|
||||
|
||||
procedure error(sequence format, sequence data)
|
||||
printf(STDOUT, format, data)
|
||||
abort(1)
|
||||
end procedure
|
||||
|
||||
-- get the next character from the input
|
||||
function next_ch()
|
||||
the_ch = getc(input_file)
|
||||
the_col += 1
|
||||
if the_ch = '\n' then
|
||||
the_line += 1
|
||||
the_col = 0
|
||||
end if
|
||||
return the_ch
|
||||
end function
|
||||
|
||||
-- 'x' - character constants
|
||||
function char_lit(integer err_line, integer err_col)
|
||||
integer n = next_ch() -- skip opening quote
|
||||
if the_ch = '\'' then
|
||||
error("%d %d empty character constant", {err_line, err_col})
|
||||
elsif the_ch = '\\' then
|
||||
next_ch()
|
||||
if the_ch = 'n' then
|
||||
n = 10
|
||||
elsif the_ch = '\\' then
|
||||
n = '\\'
|
||||
else
|
||||
error("%d %d unknown escape sequence \\%c", {err_line, err_col, the_ch})
|
||||
end if
|
||||
end if
|
||||
if next_ch() != '\'' then
|
||||
error("%d %d multi-character constant", {err_line, err_col})
|
||||
end if
|
||||
next_ch()
|
||||
return {tk_Integer, err_line, err_col, n}
|
||||
end function
|
||||
|
||||
-- process divide or comments
|
||||
function div_or_cmt(integer err_line, integer err_col)
|
||||
if next_ch() != '*' then
|
||||
return {tk_Div, err_line, err_col}
|
||||
end if
|
||||
|
||||
-- comment found
|
||||
next_ch()
|
||||
while true do
|
||||
if the_ch = '*' then
|
||||
if next_ch() = '/' then
|
||||
next_ch()
|
||||
return get_tok()
|
||||
end if
|
||||
elsif the_ch = EOF then
|
||||
error("%d %d EOF in comment", {err_line, err_col})
|
||||
else
|
||||
next_ch()
|
||||
end if
|
||||
end while
|
||||
end function
|
||||
|
||||
-- "string"
|
||||
function string_lit(integer start, integer err_line, integer err_col)
|
||||
string text = ""
|
||||
|
||||
while next_ch() != start do
|
||||
if the_ch = EOF then
|
||||
error("%d %d EOF while scanning string literal", {err_line, err_col})
|
||||
end if
|
||||
if the_ch = '\n' then
|
||||
error("%d %d EOL while scanning string literal", {err_line, err_col})
|
||||
end if
|
||||
text &= the_ch
|
||||
end while
|
||||
|
||||
next_ch()
|
||||
return {tk_String, err_line, err_col, text}
|
||||
end function
|
||||
|
||||
-- handle identifiers and integers
|
||||
function ident_or_int(integer err_line, integer err_col)
|
||||
integer n, is_number = true
|
||||
string text = ""
|
||||
|
||||
while t_alnum(the_ch) or the_ch = '_' do
|
||||
text &= the_ch
|
||||
if not t_digit(the_ch) then
|
||||
is_number = false
|
||||
end if
|
||||
next_ch()
|
||||
end while
|
||||
|
||||
if length(text) = 0 then
|
||||
error("%d %d ident_or_int: unrecognized character: (%d) '%s'", {err_line, err_col, the_ch, the_ch})
|
||||
end if
|
||||
|
||||
if t_digit(text[1]) then
|
||||
if not is_number then
|
||||
error("%d %d invalid number: %s", {err_line, err_col, text})
|
||||
end if
|
||||
n = to_integer(text)
|
||||
return {tk_Integer, err_line, err_col, n}
|
||||
end if
|
||||
|
||||
if has(key_words, text) then
|
||||
return {get(key_words, text), err_line, err_col}
|
||||
end if
|
||||
|
||||
return {tk_Ident, err_line, err_col, text}
|
||||
end function
|
||||
|
||||
-- look ahead for '>=', etc.
|
||||
function follow(integer expect, integer ifyes, integer ifno, integer err_line, integer err_col)
|
||||
if next_ch() = expect then
|
||||
next_ch()
|
||||
return {ifyes, err_line, err_col}
|
||||
end if
|
||||
|
||||
if ifno = tk_EOI then
|
||||
error("%d %d follow: unrecognized character: (%d)", {err_line, err_col, the_ch})
|
||||
end if
|
||||
|
||||
return {ifno, err_line, err_col}
|
||||
end function
|
||||
|
||||
-- return the next token type
|
||||
function get_tok()
|
||||
while t_space(the_ch) do
|
||||
next_ch()
|
||||
end while
|
||||
|
||||
integer err_line = the_line
|
||||
integer err_col = the_col
|
||||
|
||||
switch the_ch do
|
||||
case EOF then return {tk_EOI, err_line, err_col}
|
||||
case '/' then return div_or_cmt(err_line, err_col)
|
||||
case '\'' then return char_lit(err_line, err_col)
|
||||
|
||||
case '<' then return follow('=', tk_Leq, tk_Lss, err_line, err_col)
|
||||
case '>' then return follow('=', tk_Geq, tk_Gtr, err_line, err_col)
|
||||
case '=' then return follow('=', tk_Eq, tk_Assign, err_line, err_col)
|
||||
case '!' then return follow('=', tk_Neq, tk_Not, err_line, err_col)
|
||||
case '&' then return follow('&', tk_And, tk_EOI, err_line, err_col)
|
||||
case '|' then return follow('|', tk_Or, tk_EOI, err_line, err_col)
|
||||
|
||||
case '"' then return string_lit(the_ch, err_line, err_col)
|
||||
case else
|
||||
integer sym = symbols[the_ch]
|
||||
if sym != tk_EOI then
|
||||
next_ch()
|
||||
return {sym, err_line, err_col}
|
||||
end if
|
||||
return ident_or_int(err_line, err_col)
|
||||
end switch
|
||||
end function
|
||||
|
||||
procedure init()
|
||||
put(key_words, "else", tk_Else)
|
||||
put(key_words, "if", tk_If)
|
||||
put(key_words, "print", tk_Print)
|
||||
put(key_words, "putc", tk_Putc)
|
||||
put(key_words, "while", tk_While)
|
||||
|
||||
symbols = repeat(tk_EOI, 256)
|
||||
symbols['{'] = tk_Lbrace
|
||||
symbols['}'] = tk_Rbrace
|
||||
symbols['('] = tk_Lparen
|
||||
symbols[')'] = tk_Rparen
|
||||
symbols['+'] = tk_Add
|
||||
symbols['-'] = tk_Sub
|
||||
symbols['*'] = tk_Mul
|
||||
symbols['%'] = tk_Mod
|
||||
symbols[';'] = tk_Semi
|
||||
symbols[','] = tk_Comma
|
||||
end procedure
|
||||
|
||||
procedure main(sequence cl)
|
||||
sequence file_name
|
||||
|
||||
input_file = STDIN
|
||||
if length(cl) > 2 then
|
||||
file_name = cl[3]
|
||||
input_file = open(file_name, "r")
|
||||
if input_file = -1 then
|
||||
error("Could not open %s", {file_name})
|
||||
end if
|
||||
end if
|
||||
init()
|
||||
sequence t
|
||||
loop do
|
||||
t = get_tok()
|
||||
printf(STDOUT, "%5d %5d %-8s", {t[2], t[3], all_syms[t[1]]})
|
||||
switch t[1] do
|
||||
case tk_Integer then printf(STDOUT, " %5d\n", {t[4]})
|
||||
case tk_Ident then printf(STDOUT, " %s\n", {t[4]})
|
||||
case tk_String then printf(STDOUT, " \"%s\"\n", {t[4]})
|
||||
case else printf(STDOUT, "\n")
|
||||
end switch
|
||||
until t[1] = tk_EOI
|
||||
end loop
|
||||
end procedure
|
||||
|
||||
main(command_line())
|
||||
|
|
@ -1,161 +1,155 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- demo\rosetta\Compiler\core.e
|
||||
-- ============================
|
||||
--
|
||||
-- Standard declarations and routines used by lex.exw, parse.exw, cgen.exw, and interp.exw
|
||||
-- (included in distribution as above, which contains some additional sanity checks)
|
||||
--</span>
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">EOF</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STDIN</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STDOUT</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
-- demo\rosetta\Compiler\core.e
|
||||
-- Standard declarations and routines used by lex.exw, parse.exw, cgen.exw, and interp.exw
|
||||
-- (included in distribution as above, which contains some additional sanity checks)
|
||||
with javascript_semantics
|
||||
global constant EOF = -1, STDIN = 0, STDOUT = 1
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">enum</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">UNARY</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span>
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">type</span> <span style="color: #000000;">nary</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">NONE</span> <span style="color: #008080;">or</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">UNARY</span> <span style="color: #008080;">or</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">BINARY</span> <span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
|
||||
global enum NONE=0, UNARY=1, BINARY=2
|
||||
global type nary(integer n) return n=NONE or n=UNARY or n=BINARY end type
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">tkNames</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- eg/ie {"Op_multiply","Op_divide",..}</span>
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">precedences</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">narys</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- NONE/UNARY/BINARY</span>
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">operators</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- eg/ie {"*","/","+","-","<","<=",..}</span>
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">opcodes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- idx to tkNames, matching operators</span>
|
||||
global sequence tkNames = {} -- eg/ie {"Op_multiply","Op_divide",..}
|
||||
global sequence precedences = {}
|
||||
global sequence narys = {} -- NONE/UNARY/BINARY
|
||||
global sequence operators = {} -- eg/ie {"*","/","+","-","<","<=",..}
|
||||
global sequence opcodes = {} -- idx to tkNames, matching operators
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">KEYWORDS</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- eg/ie {"if"=>idx to tkNames}</span>
|
||||
global constant KEYWORDS = new_dict() -- eg/ie {"if"=>idx to tkNames}
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">enum</span> <span style="color: #000000;">OPERATOR</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DIGIT</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LETTER</span> <span style="color: #000080;font-style:italic;">-- character classes</span>
|
||||
global enum OPERATOR=1, DIGIT, LETTER -- character classes
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">charmap</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">255</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">..</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">DIGIT</span>
|
||||
<span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">..</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">LETTER</span>
|
||||
<span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">..</span><span style="color: #008000;">'z'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">LETTER</span>
|
||||
<span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'_'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">LETTER</span>
|
||||
global sequence charmap = repeat(0,255)
|
||||
charmap['0'..'9'] = DIGIT
|
||||
charmap['A'..'Z'] = LETTER
|
||||
charmap['a'..'z'] = LETTER
|
||||
charmap['_'] = LETTER
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nary</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">precedence</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">tkNames</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tkNames</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">narys</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">narys</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">precedences</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">precedences</span><span style="color: #0000FF;">,</span><span style="color: #000000;">precedence</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tkNames</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function tkName(string s, nary n = NONE, integer precedence = -1)
|
||||
tkNames = append(tkNames,s)
|
||||
narys = append(narys,n)
|
||||
precedences = append(precedences,precedence)
|
||||
return length(tkNames)
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nary</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">precedence</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">precedence</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">operators</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">opcodes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opcodes</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #000000;">op</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">OPERATOR</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function tkOp(string s, string op, nary n, integer precedence)
|
||||
integer res = tkName(s, n, precedence)
|
||||
operators = append(operators,op)
|
||||
opcodes = append(opcodes,res)
|
||||
for i=1 to length(op) do
|
||||
charmap[op[i]] = OPERATOR
|
||||
end for
|
||||
return res
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">tkKw</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">keyword</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">putd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">keyword</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">KEYWORDS</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function tkKw(string s, string keyword)
|
||||
integer res = tkName(s)
|
||||
putd(keyword, res, KEYWORDS)
|
||||
return res
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span>
|
||||
<span style="color: #000000;">tk_EOI</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"End_of_input"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--1</span>
|
||||
<span style="color: #000000;">tk_mul</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_multiply"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--2</span>
|
||||
<span style="color: #000000;">tk_div</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_divide"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"/"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--3</span>
|
||||
<span style="color: #000000;">tk_mod</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_mod"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"%"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--4</span>
|
||||
<span style="color: #000000;">tk_add</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_add"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--5</span>
|
||||
<span style="color: #000000;">tk_sub</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_subtract"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--6</span>
|
||||
<span style="color: #000000;">tk_neg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_negate"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">UNARY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--7</span>
|
||||
<span style="color: #000000;">tk_not</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_not"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"!"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">UNARY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--8</span>
|
||||
<span style="color: #000000;">tk_lt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_less"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"<"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--9</span>
|
||||
<span style="color: #000000;">tk_le</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_lessequal"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"<="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--10</span>
|
||||
<span style="color: #000000;">tk_gt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_greater"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">">"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--11</span>
|
||||
<span style="color: #000000;">tk_ge</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_greaterequal"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">">="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--12</span>
|
||||
<span style="color: #000000;">tk_eq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_equal"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"=="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--13</span>
|
||||
<span style="color: #000000;">tk_ne</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_notequal"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"!="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--14</span>
|
||||
<span style="color: #000000;">tk_assign</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_assign"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"="</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--15</span>
|
||||
<span style="color: #000000;">tk_and</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_and"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"&&"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--16</span>
|
||||
<span style="color: #000000;">tk_or</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Op_or"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"||"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BINARY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--17</span>
|
||||
<span style="color: #000000;">tk_if</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkKw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Keyword_if"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"if"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--18</span>
|
||||
<span style="color: #000000;">tk_else</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkKw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Keyword_else"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"else"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--19</span>
|
||||
<span style="color: #000000;">tk_while</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkKw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Keyword_while"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"while"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--20</span>
|
||||
<span style="color: #000000;">tk_print</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkKw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Keyword_print"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"print"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--21</span>
|
||||
<span style="color: #000000;">tk_putc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkKw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Keyword_putc"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"putc"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--22</span>
|
||||
<span style="color: #000000;">tk_LeftParen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"LeftParen"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"("</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--23</span>
|
||||
<span style="color: #000000;">tk_RightParen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RightParen"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">")"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--24</span>
|
||||
<span style="color: #000000;">tk_LeftBrace</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"LeftBrace"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"{"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--25</span>
|
||||
<span style="color: #000000;">tk_RightBrace</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RightBrace"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"}"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--26</span>
|
||||
<span style="color: #000000;">tk_Semicolon</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Semicolon"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">";"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--27</span>
|
||||
<span style="color: #000000;">tk_Comma</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Comma"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">","</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NONE</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--28</span>
|
||||
<span style="color: #000000;">tk_Identifier</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Identifier"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--29</span>
|
||||
<span style="color: #000000;">tk_Integer</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Integer"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--30</span>
|
||||
<span style="color: #000000;">tk_String</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"String"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--31</span>
|
||||
<span style="color: #000000;">tk_Sequence</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Sequence"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--32</span>
|
||||
<span style="color: #000000;">tk_Prints</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"tk_Prints"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">--33</span>
|
||||
<span style="color: #000000;">tk_Printi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tkName</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"tk_Printi"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">--34</span>
|
||||
global constant
|
||||
tk_EOI = tkName("End_of_input"), --1
|
||||
tk_mul = tkOp("Op_multiply", "*", BINARY,13), --2
|
||||
tk_div = tkOp("Op_divide", "/", BINARY,13), --3
|
||||
tk_mod = tkOp("Op_mod", "%", BINARY,13), --4
|
||||
tk_add = tkOp("Op_add", "+", BINARY,12), --5
|
||||
tk_sub = tkOp("Op_subtract", "-", BINARY,12), --6
|
||||
tk_neg = tkName("Op_negate", UNARY, 14), --7
|
||||
tk_not = tkOp("Op_not", "!", UNARY, 14), --8
|
||||
tk_lt = tkOp("Op_less", "<", BINARY,10), --9
|
||||
tk_le = tkOp("Op_lessequal", "<=",BINARY,10), --10
|
||||
tk_gt = tkOp("Op_greater", ">", BINARY,10), --11
|
||||
tk_ge = tkOp("Op_greaterequal", ">=",BINARY,10), --12
|
||||
tk_eq = tkOp("Op_equal", "==",BINARY, 9), --13
|
||||
tk_ne = tkOp("Op_notequal", "!=",BINARY, 9), --14
|
||||
tk_assign = tkOp("Op_assign", "=", NONE, -1), --15
|
||||
tk_and = tkOp("Op_and", "&&",BINARY, 5), --16
|
||||
tk_or = tkOp("Op_or", "||",BINARY, 4), --17
|
||||
tk_if = tkKw("Keyword_if", "if"), --18
|
||||
tk_else = tkKw("Keyword_else", "else"), --19
|
||||
tk_while = tkKw("Keyword_while","while"), --20
|
||||
tk_print = tkKw("Keyword_print","print"), --21
|
||||
tk_putc = tkKw("Keyword_putc", "putc"), --22
|
||||
tk_LeftParen = tkOp("LeftParen", "(", NONE, -1), --23
|
||||
tk_RightParen = tkOp("RightParen", ")", NONE, -1), --24
|
||||
tk_LeftBrace = tkOp("LeftBrace", "{", NONE, -1), --25
|
||||
tk_RightBrace = tkOp("RightBrace", "}", NONE, -1), --26
|
||||
tk_Semicolon = tkOp("Semicolon", ";", NONE, -1), --27
|
||||
tk_Comma = tkOp("Comma", ",", NONE, -1), --28
|
||||
tk_Identifier = tkName("Identifier"), --29
|
||||
tk_Integer = tkName("Integer"), --30
|
||||
tk_String = tkName("String"), --31
|
||||
tk_Sequence = tkName("Sequence"), --32
|
||||
tk_Prints = tkName("tk_Prints"), --33
|
||||
tk_Printi = tkName("tk_Printi") --34
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">input_file</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">STDIN</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">output_file</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">STDOUT</span>
|
||||
global integer input_file = STDIN,
|
||||
output_file = STDOUT
|
||||
|
||||
<span style="color: #008080;">type</span> <span style="color: #000000;">strint</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
|
||||
type strint(object o)
|
||||
return string(o) or integer(o)
|
||||
end type
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #000000;">strint</span> <span style="color: #000000;">tok_line</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- save of line/col at the start of</span>
|
||||
<span style="color: #000000;">tok_col</span> <span style="color: #000080;font-style:italic;">-- token/comment, for result/errors</span>
|
||||
global strint tok_line, -- save of line/col at the start of
|
||||
tok_col -- token/comment, for result/errors
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #004080;">object</span> <span style="color: #000000;">oneline</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
global object oneline = ""
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">errfmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Line %s column %s:\n%s%s"</span>
|
||||
constant errfmt = "Line %s column %s:\n%s%s"
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">errline</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">oneline</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">oneline</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\r\n"</span><span style="color: #0000FF;">),</span><span style="color: #008000;">'\t'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">padding</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%s\n%s^ "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">oneline</span><span style="color: #0000FF;">,</span><span style="color: #000000;">padding</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function errline()
|
||||
oneline = substitute(trim(oneline,"\r\n"),'\t',' ')
|
||||
string padding = repeat(' ',tok_col)
|
||||
return sprintf("%s\n%s^ ",{oneline,padding})
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">args</span><span style="color: #0000FF;">={})</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">args</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">,</span><span style="color: #000000;">args</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">el</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">oneline</span><span style="color: #0000FF;">)?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #000000;">errline</span><span style="color: #0000FF;">())</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tok_line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">tok_line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">tok_col</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">STDOUT</span><span style="color: #0000FF;">,</span><span style="color: #000000;">errfmt</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tok_line</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">,</span><span style="color: #000000;">el</span><span style="color: #0000FF;">,</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
global procedure error(sequence msg, sequence args={})
|
||||
if length(args) then
|
||||
msg = sprintf(msg,args)
|
||||
end if
|
||||
string el = iff(atom(oneline)?"":errline())
|
||||
if integer(tok_line) then tok_line = sprintf("%d",tok_line) end if
|
||||
if integer(tok_col) then tok_col = sprintf("%d",tok_col) end if
|
||||
printf(STDOUT,errfmt,{tok_line,tok_col,el,msg})
|
||||
{} = wait_key()
|
||||
abort(1)
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">include</span> <span style="color: #000000;">js_io</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- fake file i/o for running under pwa/p2js</span>
|
||||
include js_io.e -- fake file i/o for running under pwa/p2js
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">open_file</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">file_name</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">js_open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">file_name</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">:</span><span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">file_name</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">STDOUT</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Could not open %s"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">file_name</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">fn</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function open_file(string file_name, string mode)
|
||||
integer fn = iff(platform()=JS?js_open(file_name)
|
||||
:open(file_name, mode))
|
||||
if fn<=0 then
|
||||
printf(STDOUT, "Could not open %s", {file_name})
|
||||
{} = wait_key()
|
||||
abort(1)
|
||||
end if
|
||||
return fn
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">open_files</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">cl</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)></span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">input_file</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"r"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)></span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">output_file</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"w"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
global procedure open_files(sequence cl)
|
||||
if length(cl)>2 then
|
||||
input_file = open_file(cl[3],"r")
|
||||
if length(cl)>3 then
|
||||
output_file = open_file(cl[4],"w")
|
||||
end if
|
||||
end if
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">close_files</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">input_file</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">STDIN</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input_file</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">output_file</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">STDOUT</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">output_file</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
global procedure close_files()
|
||||
if platform()!=JS then
|
||||
if input_file!=STDIN then close(input_file) end if
|
||||
if output_file!=STDOUT then close(output_file) end if
|
||||
end if
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">enquote</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`"%s"`</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\\n"</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
global function enquote(string s)
|
||||
return sprintf(`"%s"`,substitute(s,"\n","\\n"))
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">unquote</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'\"'</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[$]!=</span><span style="color: #008000;">'\"'</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"\\n"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
<!--
|
||||
global function unquote(string s)
|
||||
if s[1]!='\"' then ?9/0 end if
|
||||
if s[$]!='\"' then ?9/0 end if
|
||||
s = substitute(s[2..-2],"\\n","\n")
|
||||
return s
|
||||
end function
|
||||
|
|
|
|||
|
|
@ -1,103 +1,97 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- demo\rosetta\Compiler\js_io.e
|
||||
-- =============================
|
||||
--
|
||||
-- Fake file i/o for running under pwa/p2js in a browser
|
||||
-- Does not cover the human readable reload parts of extra.e
|
||||
--</span>
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">known_files</span><span style="color: #0000FF;">,</span><span style="color: #000000;">kfc</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"test3.c"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
|
||||
/*
|
||||
All lexical tokens - not syntactically correct, but that will
|
||||
have to wait until syntax analysis
|
||||
*/
|
||||
/* Print */ print /* Sub */ -
|
||||
/* Putc */ putc /* Lss */ <
|
||||
/* If */ if /* Gtr */ >
|
||||
/* Else */ else /* Leq */ <=
|
||||
/* While */ while /* Geq */ >=
|
||||
/* Lbrace */ { /* Eq */ ==
|
||||
/* Rbrace */ } /* Neq */ !=
|
||||
/* Lparen */ ( /* And */ &&
|
||||
/* Rparen */ ) /* Or */ ||
|
||||
/* Uminus */ - /* Semi */ ;
|
||||
/* Not */ ! /* Comma */ ,
|
||||
/* Mul */ * /* Assign */ =
|
||||
/* Div */ / /* Integer */ 42
|
||||
/* Mod */ % /* String */ "String literal"
|
||||
/* Add */ + /* Ident */ variable_name
|
||||
/* character literal */ '\n'
|
||||
/* character literal **/ '\\'
|
||||
/* character literal */ ' '
|
||||
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"test4.c"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
|
||||
/*** test printing, embedded \n and comments with lots of '*' ***/
|
||||
print(42);
|
||||
print("\nHello World\nGood Bye\nok\n");
|
||||
print("Print a slash n - \\n.\n");
|
||||
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"primes.c"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
|
||||
/*
|
||||
Simple prime number generator
|
||||
*/
|
||||
count = 1;
|
||||
n = 1;
|
||||
limit = 100;
|
||||
while (n < limit) {
|
||||
k=3;
|
||||
p=1;
|
||||
n=n+2;
|
||||
while ((k*k<=n) && (p)) {
|
||||
p=n/k*k!=n;
|
||||
k=k+2;
|
||||
}
|
||||
if (p) {
|
||||
print(n, " is prime\n");
|
||||
count = count + 1;
|
||||
}
|
||||
}
|
||||
print("Total primes found: ", count, "\n");
|
||||
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"gcd.c"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
|
||||
/* Compute the gcd of 1071, 1029: 21 */
|
||||
-- demo\rosetta\Compiler\js_io.e
|
||||
-- Fake file i/o for running under pwa/p2js in a browser
|
||||
-- Does not cover the human readable reload parts of extra.e
|
||||
with javascript_semantics
|
||||
sequence {known_files,kfc} = columnize({
|
||||
{"test3.c",split(`
|
||||
/*
|
||||
All lexical tokens - not syntactically correct, but that will
|
||||
have to wait until syntax analysis
|
||||
*/
|
||||
/* Print */ print /* Sub */ -
|
||||
/* Putc */ putc /* Lss */ <
|
||||
/* If */ if /* Gtr */ >
|
||||
/* Else */ else /* Leq */ <=
|
||||
/* While */ while /* Geq */ >=
|
||||
/* Lbrace */ { /* Eq */ ==
|
||||
/* Rbrace */ } /* Neq */ !=
|
||||
/* Lparen */ ( /* And */ &&
|
||||
/* Rparen */ ) /* Or */ ||
|
||||
/* Uminus */ - /* Semi */ ;
|
||||
/* Not */ ! /* Comma */ ,
|
||||
/* Mul */ * /* Assign */ =
|
||||
/* Div */ / /* Integer */ 42
|
||||
/* Mod */ % /* String */ "String literal"
|
||||
/* Add */ + /* Ident */ variable_name
|
||||
/* character literal */ '\n'
|
||||
/* character literal **/ '\\'
|
||||
/* character literal */ ' '
|
||||
`,"\n")},
|
||||
{"test4.c",split(`
|
||||
/*** test printing, embedded \n and comments with lots of '*' ***/
|
||||
print(42);
|
||||
print("\nHello World\nGood Bye\nok\n");
|
||||
print("Print a slash n - \\n.\n");
|
||||
`,"\n")},
|
||||
{"primes.c",split(`
|
||||
/*
|
||||
Simple prime number generator
|
||||
*/
|
||||
count = 1;
|
||||
n = 1;
|
||||
limit = 100;
|
||||
while (n < limit) {
|
||||
k=3;
|
||||
p=1;
|
||||
n=n+2;
|
||||
while ((k*k<=n) && (p)) {
|
||||
p=n/k*k!=n;
|
||||
k=k+2;
|
||||
}
|
||||
if (p) {
|
||||
print(n, " is prime\n");
|
||||
count = count + 1;
|
||||
}
|
||||
}
|
||||
print("Total primes found: ", count, "\n");
|
||||
`,"\n")},
|
||||
{"gcd.c",split(`
|
||||
/* Compute the gcd of 1071, 1029: 21 */
|
||||
|
||||
a = 1071;
|
||||
b = 1029;
|
||||
a = 1071;
|
||||
b = 1029;
|
||||
|
||||
while (b != 0) {
|
||||
new_a = b;
|
||||
b = a % b;
|
||||
a = new_a;
|
||||
}
|
||||
print(a);
|
||||
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Header.h"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
|
||||
#define area(h, w) h * w
|
||||
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Source.t"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
|
||||
#include "Header.h"
|
||||
#define width 5
|
||||
#define height 6
|
||||
area = #area(height, width)#;
|
||||
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)}})</span>
|
||||
while (b != 0) {
|
||||
new_a = b;
|
||||
b = a % b;
|
||||
a = new_a;
|
||||
}
|
||||
print(a);
|
||||
`,"\n")},
|
||||
{"Header.h",split(`
|
||||
#define area(h, w) h * w
|
||||
`,"\n")},
|
||||
{"Source.t",split(`
|
||||
#include "Header.h"
|
||||
#define width 5
|
||||
#define height 6
|
||||
area = #area(height, width)#;
|
||||
`,"\n")}})
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">linenos</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">known_files</span><span style="color: #0000FF;">))</span>
|
||||
sequence linenos = repeat(-1,length(known_files))
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">js_open</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">known_files</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">linenos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">fn</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
global function js_open(string filename)
|
||||
integer fn = find(filename,known_files)
|
||||
assert(fn!=0)
|
||||
linenos[fn] = 0
|
||||
return fn
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">js_gets</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">lineno</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">linenos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">lineno</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">kfc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">linenos</span><span style="color: #0000FF;">[</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lineno</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">kfc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">][</span><span style="color: #000000;">lineno</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">EOF</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
<!--
|
||||
global function js_gets(integer fn)
|
||||
integer lineno = linenos[fn]+1
|
||||
if lineno<=length(kfc[fn]) then
|
||||
linenos[fn] = lineno
|
||||
return kfc[fn][lineno]
|
||||
end if
|
||||
return EOF
|
||||
end function
|
||||
|
|
|
|||
|
|
@ -1,188 +1,182 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- demo\\rosetta\\Compiler\\lex.e
|
||||
-- ==============================
|
||||
--
|
||||
-- The reusable part of lex.exw
|
||||
-- This is only kept separate from core.e for consistency with later modules.</span>
|
||||
-- demo\\rosetta\\Compiler\\lex.e
|
||||
-- The reusable part of lex.exw
|
||||
-- This is only kept separate from core.e for consistency with later modules.
|
||||
with javascript_semantics
|
||||
include core.e
|
||||
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">include</span> <span style="color: #000000;">core</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
|
||||
integer ch = ' ',
|
||||
line = 0,
|
||||
col = 0
|
||||
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">col</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
procedure eof(string s)
|
||||
error("%s in %s literal",{iff(ch=EOF?"EOF":"EOL"),s})
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">eof</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%s in %s literal"</span><span style="color: #0000FF;">,{</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">EOF</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"EOF"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"EOL"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">s</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
function next_ch()
|
||||
while 1 do
|
||||
col += 1
|
||||
if oneline=EOF then
|
||||
ch = EOF
|
||||
exit
|
||||
elsif col>length(oneline) then
|
||||
line += 1
|
||||
col = 0
|
||||
oneline = iff(platform()=JS?js_gets(input_file)
|
||||
:gets(input_file))
|
||||
else
|
||||
ch = oneline[col]
|
||||
exit
|
||||
end if
|
||||
end while
|
||||
return ch
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">col</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">oneline</span><span style="color: #0000FF;">=</span><span style="color: #000000;">EOF</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">EOF</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">col</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">oneline</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">line</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">col</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #000000;">oneline</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">js_gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input_file</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">:</span><span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input_file</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">oneline</span><span style="color: #0000FF;">[</span><span style="color: #000000;">col</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
-- for pwa/p2js (JavaScript *really* dislikes tabs in strings):
|
||||
--constant whitespace = " \t\r\n\x0B\xA0"
|
||||
constant whitespace = {' ','\t','\r','\n',#0B,#A0}
|
||||
-- (0x0B is Vertical Tab, 0xA0 is Non-breaking space)
|
||||
|
||||
<span style="color: #000080;font-style:italic;">-- for pwa/p2js (JavaScript *really* dislikes tabs in strings):
|
||||
--constant whitespace = " \t\r\n\x0B\xA0"</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">whitespace</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\t'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\r'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#0B</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#A0</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #000080;font-style:italic;">-- (0x0B is Vertical Tab, 0xA0 is Non-breaking space)</span>
|
||||
procedure skipspacesandcomments()
|
||||
while 1 do
|
||||
if not find(ch,whitespace) then
|
||||
if ch='/' and col<length(oneline) and oneline[col+1]='*' then
|
||||
tok_line = line -- (in case of EOF error)
|
||||
tok_col = col
|
||||
ch = next_ch() -- (can be EOF)
|
||||
ch = next_ch() -- ( "" )
|
||||
while 1 do
|
||||
if ch='*' then
|
||||
ch = next_ch()
|
||||
if ch='/' then exit end if
|
||||
elsif ch=EOF then
|
||||
error("EOF in comment")
|
||||
else
|
||||
ch = next_ch()
|
||||
end if
|
||||
end while
|
||||
else
|
||||
exit
|
||||
end if
|
||||
end if
|
||||
ch = next_ch()
|
||||
end while
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">skipspacesandcomments</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">whitespace</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'/'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">col</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">oneline</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">oneline</span><span style="color: #0000FF;">[</span><span style="color: #000000;">col</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'*'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">tok_line</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">line</span> <span style="color: #000080;font-style:italic;">-- (in case of EOF error)</span>
|
||||
<span style="color: #000000;">tok_col</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">col</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- (can be EOF)</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- ( "" )</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'*'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'/'</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">EOF</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"EOF in comment"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
function escape_char(string s)
|
||||
ch = next_ch() -- (discard the '\\')
|
||||
if ch='n' then
|
||||
ch = '\n'
|
||||
elsif ch='\\' then
|
||||
ch = '\\'
|
||||
elsif ch=EOF
|
||||
or ch='\n' then
|
||||
eof(s)
|
||||
else
|
||||
error(`unknown escape sequence \%c`, {ch})
|
||||
end if
|
||||
return ch
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">escape_char</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- (discard the '\\')</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'n'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'\n'</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\\'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'\\'</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">EOF</span>
|
||||
<span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\n'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">eof</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`unknown escape sequence \%c`</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function char_lit()
|
||||
integer startch = ch,
|
||||
res = next_ch() -- (skip opening quote, save res)
|
||||
if ch=startch then
|
||||
error("empty character constant")
|
||||
elsif ch='\\' then
|
||||
res = escape_char("character")
|
||||
end if
|
||||
ch = next_ch()
|
||||
if ch=EOF
|
||||
or ch='\n' then
|
||||
eof("character")
|
||||
elsif ch!=startch then
|
||||
error("multi-character constant")
|
||||
end if
|
||||
ch = next_ch()
|
||||
return {tk_Integer, res}
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">char_lit</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">startch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- (skip opening quote, save res)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">startch</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"empty character constant"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\\'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">escape_char</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"character"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">EOF</span>
|
||||
<span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\n'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">eof</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"character"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">startch</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"multi-character constant"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tk_Integer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function string_lit()
|
||||
integer startch = ch
|
||||
string text = ""
|
||||
while next_ch()!=startch do
|
||||
if ch=EOF
|
||||
or ch='\n' then
|
||||
eof("string")
|
||||
elsif ch='\\' then
|
||||
ch = escape_char("string")
|
||||
end if
|
||||
text &= ch
|
||||
end while
|
||||
ch = next_ch()
|
||||
return {tk_String, text}
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">string_lit</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">startch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()!=</span><span style="color: #000000;">startch</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">EOF</span>
|
||||
<span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\n'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">eof</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"string"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\\'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">escape_char</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"string"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">text</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tk_String</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function get_op()
|
||||
-- sequence operator = {ch}
|
||||
string operator = ""&ch
|
||||
ch = next_ch()
|
||||
while charmap[ch]=OPERATOR
|
||||
and find(operator&ch,operators) do
|
||||
-- (^ ie/eg merge ">=", but not ");")
|
||||
operator &= ch
|
||||
ch = next_ch()
|
||||
end while
|
||||
integer k = find(operator,operators)
|
||||
if k=0 then error("unknown operator") end if
|
||||
return {opcodes[k], 0} -- (0 unused)
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_op</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000080;font-style:italic;">-- sequence operator = {ch}</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">operator</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">&</span><span style="color: #000000;">ch</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">OPERATOR</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">operator</span><span style="color: #0000FF;">&</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000080;font-style:italic;">-- (^ ie/eg merge ">=", but not ");")</span>
|
||||
<span style="color: #000000;">operator</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">operator</span><span style="color: #0000FF;">,</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"unknown operator"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">opcodes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- (0 unused)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function get_int()
|
||||
integer i = 0
|
||||
while charmap[ch]=DIGIT do
|
||||
i = i*10 + (ch-'0')
|
||||
ch = next_ch()
|
||||
end while
|
||||
if charmap[ch]=LETTER then
|
||||
error("invalid number")
|
||||
end if
|
||||
return {tk_Integer, i}
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_int</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">DIGIT</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span> <span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">LETTER</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"invalid number"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tk_Integer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function get_ident()
|
||||
string text = ""
|
||||
while find(charmap[ch],{LETTER,DIGIT}) do
|
||||
text &= ch
|
||||
ch = next_ch()
|
||||
end while
|
||||
integer keyword = getd(text,KEYWORDS)
|
||||
if keyword!=NULL then
|
||||
return {keyword, 0} -- (0 unused)
|
||||
end if
|
||||
return {tk_Identifier, text}
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_ident</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">LETTER</span><span style="color: #0000FF;">,</span><span style="color: #000000;">DIGIT</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">text</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next_ch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">keyword</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #000000;">KEYWORDS</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">keyword</span><span style="color: #0000FF;">!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">keyword</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- (0 unused)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tk_Identifier</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
function get_token()
|
||||
skipspacesandcomments()
|
||||
tok_line = line
|
||||
tok_col = col
|
||||
switch ch do
|
||||
case EOF then return {tk_EOI, 0} -- (0 unused)
|
||||
case '\'' then return char_lit()
|
||||
case '"' then return string_lit()
|
||||
else
|
||||
switch charmap[ch] do
|
||||
case OPERATOR then return get_op()
|
||||
case DIGIT then return get_int()
|
||||
case LETTER then return get_ident()
|
||||
else error("unrecognized character: (%d)", {ch})
|
||||
end switch
|
||||
end switch
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">skipspacesandcomments</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">tok_line</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">line</span>
|
||||
<span style="color: #000000;">tok_col</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">col</span>
|
||||
<span style="color: #008080;">switch</span> <span style="color: #000000;">ch</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">EOF</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tk_EOI</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- (0 unused)</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #008000;"><nowiki>'\''</nowiki></span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">char_lit</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #008000;">'"'</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">string_lit</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">switch</span> <span style="color: #000000;">charmap</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">OPERATOR</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">get_op</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">DIGIT</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">get_int</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">LETTER</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">get_ident</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">else</span> <span style="color: #000000;">error</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"unrecognized character: (%d)"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">lex</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">toks</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">tok</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">v</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">tok</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">tk_EOI</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">toks</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">toks</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tok_line</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">toks</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
<!--
|
||||
global function lex()
|
||||
sequence toks = {}
|
||||
integer tok = -1
|
||||
object v
|
||||
while tok!=tk_EOI do
|
||||
{tok,v} = get_token()
|
||||
toks = append(toks,{tok_line,tok_col,tok,v})
|
||||
end while
|
||||
return toks
|
||||
end function
|
||||
|
|
|
|||
|
|
@ -1,54 +1,48 @@
|
|||
-->
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- demo\rosetta\Compiler\extra.e
|
||||
-- =============================
|
||||
--
|
||||
-- Routines to reload human-readable files (deviation from task requirement)
|
||||
--</span>
|
||||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)
|
||||
-- demo\rosetta\Compiler\extra.e
|
||||
-- Routines to reload human-readable files (deviation from task requirement)
|
||||
without js -- (file i/o)
|
||||
|
||||
--The following can be used to load .lex files, as created by lex.exw:
|
||||
-- (in place of the existing get_tok() in parse.e)</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_tok</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input_file</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tok</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">,</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">limit</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">no_empty</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">],</span><span style="color: #000000;">tkNames</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">tok</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">tok</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
--The following can be used to load .lex files, as created by lex.exw:
|
||||
-- (in place of the existing get_tok() in parse.e)
|
||||
function get_tok()
|
||||
string line = trim(gets(input_file))
|
||||
sequence tok = split(line,' ',limit:=4,no_empty:=1)
|
||||
integer k = find(tok[3],tkNames)
|
||||
if k=0 then ?9/0 end if
|
||||
tok[3] = k
|
||||
return tok
|
||||
end function
|
||||
|
||||
|
||||
<span style="color: #000080;font-style:italic;">--The following can be used to load .ast files, as created by parse.exw:
|
||||
-- (in place of the existing lex()/parse() pairs in cgen.exw and interp.exw)</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">load_ast</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input_file</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #000080;font-style:italic;">-- Each line has at least one token</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">,</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">limit</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">no_empty</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
--The following can be used to load .ast files, as created by parse.exw:
|
||||
-- (in place of the existing lex()/parse() pairs in cgen.exw and interp.exw)
|
||||
function load_ast()
|
||||
string line = trim(gets(input_file))
|
||||
-- Each line has at least one token
|
||||
sequence node = split(line,' ',limit:=2,no_empty:=1)
|
||||
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">node_type</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
string node_type = node[1]
|
||||
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">node_type</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">";"</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- a terminal node</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">NULL</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
if node_type == ";" then -- a terminal node
|
||||
return NULL
|
||||
end if
|
||||
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">n_type</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node_type</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tkNames</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">n_type</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
integer n_type = find(node_type,tkNames)
|
||||
if n_type=0 then ?9/0 end if
|
||||
|
||||
<span style="color: #000080;font-style:italic;">-- A line with two tokens is a leaf node
|
||||
-- Leaf nodes are: Identifier, Integer, String
|
||||
-- The 2nd token is the value</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n_type</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">n_type</span><span style="color: #0000FF;">=</span><span style="color: #000000;">tk_Integer</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">n_type</span><span style="color: #0000FF;">=</span><span style="color: #000000;">tk_String</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">unquote</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">node</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">left</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">load_ast</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">right</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">load_ast</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n_type</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">right</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
<!--
|
||||
-- A line with two tokens is a leaf node
|
||||
-- Leaf nodes are: Identifier, Integer, String
|
||||
-- The 2nd token is the value
|
||||
if length(node)>1 then
|
||||
node[1] = n_type
|
||||
if n_type=tk_Integer then
|
||||
node[2] = to_integer(node[2])
|
||||
elsif n_type=tk_String then
|
||||
node[2] = unquote(node[2])
|
||||
end if
|
||||
return node
|
||||
end if
|
||||
object left = load_ast()
|
||||
object right = load_ast()
|
||||
return {n_type, left, right}
|
||||
end function
|
||||
|
|
|
|||
|
|
@ -1,29 +1,24 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- demo\rosetta\Compiler\lex.exw
|
||||
-- =============================
|
||||
--</span>
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">include</span> <span style="color: #000000;">lex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
|
||||
-- demo\rosetta\Compiler\lex.exw
|
||||
with javascript_semantics
|
||||
include lex.e
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">cl</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">open_files</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">toks</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lex</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">tok</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">v</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">toks</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">tok_line</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">toks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">switch</span> <span style="color: #000000;">tok</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">tk_Identifier</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" %s"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">tk_Integer</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" %5d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">tk_String</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" %s"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">enquote</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">else</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">output_file</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"%5d %5d %-10s%s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tok_line</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tok_col</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tkNames</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">],</span><span style="color: #000000;">v</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #000000;">close_files</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure main(sequence cl)
|
||||
open_files(cl)
|
||||
sequence toks = lex()
|
||||
integer tok
|
||||
object v
|
||||
for i=1 to length(toks) do
|
||||
{tok_line,tok_col,tok,v} = toks[i]
|
||||
switch tok do
|
||||
case tk_Identifier: v = sprintf(" %s",v)
|
||||
case tk_Integer: v = sprintf(" %5d",v)
|
||||
case tk_String: v = sprintf(" %s",enquote(v))
|
||||
else v = ""
|
||||
end switch
|
||||
printf(output_file, "%5d %5d %-10s%s\n", {tok_line,tok_col,tkNames[tok],v})
|
||||
end for
|
||||
close_files()
|
||||
end procedure
|
||||
|
||||
<span style="color: #000080;font-style:italic;">--main(command_line())</span>
|
||||
<span style="color: #000000;">main</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"test4.c"</span><span style="color: #0000FF;">})</span>
|
||||
<!--
|
||||
--main(command_line())
|
||||
main({0,0,"test4.c"})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue