Compiler/syntax analyzer: Difference between revisions

J
m (→‎{{header|Phix}}: added syntax colouring, marked p2js compatible)
(J)
Line 3,301:
;
</pre>
=={{header|J}}==
Implementation:
 
<lang J>
require'format/printf'
 
tkref=: tokenize 'End_of_input*/%+--<<=>>===!=!&&||print=print(if{else}while;print,putc)a""0'
tkref,. (tknames)=: tknames=:;: {{)n
End_of_input 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_and
Op_or Keyword_print Op_assign Keyword_print LeftParen Keyword_if LeftBrace Keyword_else RightBrace
Keyword_while Semicolon Keyword_print Comma Keyword_putc RightParen
Identifier String Integer
}}-.LF
 
tkref,.(tktyp)=:tktyp=:;: {{)n
tkEOI tkMul tkDiv tkMod tkAdd tkSub tkNeg tkLss tkLeq tkGtr tkGeq tkEql
tkNeq tkNot tkAnd tkOr tkPrint tkAssign tkPrint tkLpar tkIf tkLbra tkElse
tkRbra tkWhile tkSemi tkPrint tkComma tkPutc tkRpar tkId tkString tkInt
}}-.LF
 
tkV=: 2 (tkref i.tokenize '*/%+-<<=>>===!=&&||')} (#tktyp)#0
tkV=: 1 (1 0+tkref i.tokenize '-!')} tkV
tkPrec=: 13 13 13 12 12 10 10 10 10 9 9 5 4 (tkref i.tokenize'*/%+-<<=>>==!=&&||')} tkV<._1
tkPrec=: 14 (1 0+tkref i.tokenize'-!')} tkPrec
NB. proofread |:(<"1 tkV,.tkPrec),tktyp,tkref,:tknames
 
ndRef=: tkref
ndRef,.(ndDisp)=: ndDisp=:;:{{)n
Sequence Multiply Divide Mod Add Subtract Negate Less LessEqual Greater
GreaterEqual Equal NotEqual Not And Or Prts Assign Prti x If x x x While
x Prtc x Putc x Identifier String Integer
}}-.LF
NB. proofread |:ndRef,:ndDisp
 
tok_pfx=: {{
if.'tok_'-:4{. y do. y else.'tok_',y end.
}}L:0
 
tok_s=: tok_pfx ;:'ln col name value text type valence precedence display'
tok=: {{
do tok_s{::~tok_s i. boxopen tok_pfx y
:
x{::~tok_s i. boxopen tok_pfx y
}}
 
gettoken=: {{
'tok_ln tok_col'=: (0;ndx){::x
'tok_name tok_value'=: (1;ndx){::x
if. 'Error'-:tok_name do.
error 'invalid word ',":tok_value
end.
ind=. tknames i.<tok_name
tok_text=: ind{::tkref
tok_type=: ind{::tktyp
tok_valence=: ind{::tkV
tok_precedence=: ind{::tkPrec
ndx=:ndx+1
".each tok_s
}}
 
NB. syntax analyzer
 
parse=: {{
ndx=: tok_ln=: tok_col=: 0
gettok=: y&gettoken
gettok''
t=.a:
whilst.-.(a:-:t)+.tok_type-:tkEOI do.
t=. Sequence make_node t stmt''
end.
}}
 
stmt=:{{)v
t=. a:
select.tok_type
case.tkIf do.
s=. stmt e=. paren_expr gettok''
if.tkElse-:tok_type
do. S=. stmt gettok''
else. S=. a: end.
t=. If make_node e If make_node s S
case.tkPutc do.
e=. paren_expr gettok''
t=. Prtc make_node e a:
Putc expect tkSemi
case.tkPrint do.gettok''
'Print' expect tkLpar
while.do.
if.tkString-:tok_type
do. gettok e=. Prts make_node (String make_leaf tok_value) a:
else. e=. Prti make_node (expr 0) a: end.
t=. Sequence make_node t e
if.tkComma-:tok_type
do.Comma expect tkComma
else.break.end.
end.
'Print' expect tkRpar
'Print' expect tkSemi
case.tkSemi do.gettok''
case.tkId do.
gettok v=. Identifier make_leaf tok_value
Assign expect tkAssign
t=. Assign make_node v e=. expr 0
Assign expect tkSemi
case.tkWhile do.
t=. While make_node e s=. stmt e=. paren_expr gettok''
case.tkLbra do.
'LBrace' expect tkLbra
while.-.(<tok_type) e. tkRbra;tkEOI do.
t=. Sequence make_node t stmt''
end.
'Lbrace' expect tkRbra
case.tkEOI do.
case.do. error 'Expecting start of statement, found %s'sprintf<tok_text
end.
t
}}
 
paren_expr=: {{
'paren_expr' expect tkLpar
t=. expr 0
'paren_expr' expect tkRpar
t
}}
 
not_prec=: tkPrec{~tknames i.<Op_not
expr=: {{
select.tok_type
case.tkLpar do.e=. paren_expr''
case.tkAdd do.gettok''
e=. expr not_prec
case.tkSub do.gettok''
e=. Negate make_node (expr not_prec) a:
case.tkNot do.gettok''
e=. Not make_node (expr not_prec) a:
case.tkId do.
gettok e=. Identifier make_leaf tok_value
case.tkInt do.
gettok e=. Integer make_leaf tok_value
case.do. error 'Expecting a primary, found %s'sprintf<tok_text
end.
while.(2=tok_valence)*y<:tok_precedence do.
q=. tok_precedence [ op=. tok_type NB. no right associative operators
gettok''
e=. op make_node e expr q
end.
e
}}
 
expect=: {{
if.y-:tok_type do. gettok'' return.end.
error '%s: Expecting "%s", found "%s"'sprintf x;(tkref{::~tktyp i.<y);tok_text
}}
 
make_leaf=: {{
x;y
}}
 
make_node=: {{
m;n;<y
}}
 
error=: {{
echo 'Error: line %d, column %d: %s\n'sprintf tok_ln;tok_col;y throw.
}}
 
syntax=: {{
;(flatAST parse y),each LF
}}
 
flatAST=: {{
assert.*L.y
select.#y
case.1 do.<';' assert.y-:a:
case.2 do.<;:inv ":each y
case.3 do.({.y),(flatAST 1{::y),flatAST 2{::y
case.do.assert.0
end.
}}
</lang>
 
Task example:
 
<lang J>
primes=: {{)n
/*
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");
}}
 
syntax lex primes
Sequence
Sequence
Sequence
Sequence
Sequence
;
Assign
Identifier count
Integer 1
Assign
Identifier n
Integer 1
Assign
Identifier limit
Integer 100
While
tkLss
Identifier n
Identifier limit
Sequence
Sequence
Sequence
Sequence
Sequence
;
Assign
Identifier k
Integer 3
Assign
Identifier p
Integer 1
Assign
Identifier n
tkAdd
Identifier n
Integer 2
While
tkAnd
tkLeq
tkMul
Identifier k
Identifier k
Identifier n
Identifier p
Sequence
Sequence
;
Assign
Identifier p
tkNeq
tkDiv
Identifier n
tkMul
Identifier k
Identifier k
Identifier n
Assign
Identifier k
tkAdd
Identifier k
Integer 2
If
Identifier p
If
Sequence
Sequence
;
Sequence
Sequence
;
Prti
Identifier n
;
Prts
String " is prime\n"
;
Assign
Identifier count
tkAdd
Identifier count
Integer 1
;
Sequence
Sequence
Sequence
;
Prts
String "Total primes found: "
;
Prti
Identifier count
;
Prts
String "\n"
;
</lang>
 
=={{header|Java}}==
Usage: java Parser infile [>outfile]
6,951

edits