Compiler/Verifying syntax: Difference between revisions

m
(Added Wren)
m (→‎{{header|Wren}}: Minor tidy)
 
(6 intermediate revisions by 2 users not shown)
Line 47:
=={{header|ALGOL W}}==
Includes the test cases from the Go sample. Note, strings are limited to 256 characters in Algol W.
<langsyntaxhighlight lang="algolw">begin
% verify expressions match expected syntax %
procedure stmt ( string(256) value text ) ; begin
Line 224:
stmt( "j & k" );
stmt( "l or _m" )
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 263:
 
=={{header|C}}==
<langsyntaxhighlight Clang="c">// cverifyingsyntaxrosetta.c
// http://www.rosettacode.org/wiki/Compiler/_Verifying_Syntax
 
Line 367:
{
for( int i = 0; i < sizeof(tests)/sizeof(*tests); i++ ) parse(tests[i]);
}</langsyntaxhighlight>
{{out}}
<pre>
Line 418:
 
In particular, after substitutions, "= not", "+ not" etc. would be allowed by the Go parser so we need to exclude them. Curiously, the Go parser allows something like "2 < 3 < 4" even though it doesn't compile. We need therefore to exclude that also (see Talk page).
<langsyntaxhighlight lang="go">package main
 
import (
Line 519:
fmt.Println()
}
}</langsyntaxhighlight>
 
{{out}}
Line 622:
"false" -> identifier cannot begin with an underscore
</pre>
 
=={{header|jq}}==
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''
 
This entry uses the PEG (Parsing Expression Grammar) formalism
to transform the given grammar to a jq verification program
by a simple process that amounts to transcription.
 
For example, in the rule for `primary`, the alternation
 
Identifier | Integer
 
becomes the jq expression:
 
Identifer // Integer
 
The transcription process is not completely trivial as
jq requires definitions be ordered and perhaps nested
to satisfy a "define-before-use" rule. In the present case,
since `primary` and `expr` are defined circularly,
we define `primary` as an inner function of `expr`.
 
This PEG-to-jq transcription process is
described in detail at
[https://github.com/stedolan/jq/wiki/Parsing-Expression-Grammars].
 
The following presentation uses jq's support for regular expressions
for the sake of simplicity, brevity and efficiency.
For example, the grammar rule:
 
Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
 
becomes the jq program:
 
def Digit: parse("[0-9]");
 
where `parse` is a utility function defined in the library
of PEG-oriented functions in the first subsection below.
 
The jq program presented here works on character strings and textual files, and hence
the use of `ws` (for whitespace) in the program. Since `ws` is defined here
to make whitespace optional, it might be desirable to modify the program
to require whitespace (e.g. using the utility function `_`) in certain places instead.
</syntaxhighlight>
====Generic PEG Library====
The jq module at [[:Category:Jq/peg.jq]] can be included by copying it to a file,
and adding an `include` statement to top of the main program, e.g. as follows:
<syntaxhighlight lang=jq>
include "peg" {search: "."};
</syntaxhighlight>
 
====The Grammar====
<syntaxhighlight lang=jq>
def expr:
def Digit : parse("[0-9]");
def Letter : parse("[a-zA-Z]");
def Identifier : Letter | star(Letter // Digit // literal("_"));
def Integer : plus(Digit);
def primary : ws
| (Identifier
// Integer
// (literal("(") | expr | literal(")"))
// literal("true")
// literal("false"))
| ws;
def expr_level_6 : primary | star((literal("*") // literal("/")) | primary) ;
def expr_level_5 : expr_level_6 | star((literal("+") // literal("-")) | expr_level_6) ;
def expr_level_4 : ws | optional(literal("not")) | expr_level_5 | optional(parse("[=<]") | expr_level_5) ;
def expr_level_3 : expr_level_4 | star(literal("and") | expr_level_4) ;
def expr_level_2 : expr_level_3 | star(literal("or") | expr_level_3) ;
 
ws | expr_level_2 | ws;
 
def stmt:
{remainder: .} | expr | eos;
</syntaxhighlight>
====The Go examples====
<syntaxhighlight lang=jq>
def go: [
"$",
"one",
"either or both",
"a + 1",
"a + b < c",
"a = b",
"a or b = c",
"3 + not 5",
"3 + (not 5)",
"(42 + 3",
"(42 + 3)",
" not 3 < 4 or (true or 3 / 4 + 8 * 5 - 5 * 2 < 56) and 4 * 3 < 12 or not true",
" and 3 < 2",
"not 7 < 2",
"2 < 3 < 4",
"2 < (3 < 4)",
"2 < foobar - 3 < 4",
"2 < foobar and 3 < 4",
"4 * (32 - 16) + 9 = 73",
"235 76 + 1",
"true or false = not true",
"true or false = (not true)",
"not true or false = false",
"not true = false",
"a + b = not c and false",
"a + b = (not c) and false",
"a + b = (not c and false)",
"ab_c / bd2 or < e_f7",
"g not = h",
"été = false",
"i++",
"j & k",
"l or _m"
];
 
# For ease of comparison with the Go output, simply emit `true` or `false`
go[]
| (stmt | true) // false
</syntaxhighlight>
 
'''Invocation''': jq -nr -f compiler-verifying-syntax.jq
{{output}}
The same sequence of `true` and `false` values as at [[#Go|Go]].
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">function substituteinnerparentheses(s, subs)
((i = findlast('(', s)) == nothing) && return (s, false)
((j = findfirst(')', s[i:end])) == nothing) && return (s, false)
Line 676 ⟶ 804:
println("The compiler parses the statement { $s } and outputs: ", okparse(s))
end
</langsyntaxhighlight>{{out}}
<pre>
The compiler parses the statement { not 3 < 4 or (true or 3 / 4 + 8 * 5 - 5 * 2 < 56) and 4 * 3 < 12 or not true } and outputs: true
Line 689 ⟶ 817:
 
=={{header|Nim}}==
<langsyntaxhighlight Nimlang="nim">import strutils, tables
 
type
Line 903 ⟶ 1,031:
let ok = checkStmt(lex)
echo test, " → ", ok
if not ok: echo "*** Error at position $1. $2 ".format(lex.pos, lex.error)</langsyntaxhighlight>
 
{{out}}
Line 962 ⟶ 1,090:
Added 'not' and non-assoc fixes.
Cooler output.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # http://www.rosettacode.org/wiki/Compiler/_Verifying_Syntax
Line 1,019 ⟶ 1,147:
j & k
l or _m
UPPER_cAsE_aNd_letter_and_12345_test</langsyntaxhighlight>
{{out}}
<pre>
Line 1,059 ⟶ 1,187:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Compiler\Verify_Syntax.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
Line 1,252 ⟶ 1,380:
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</langsyntaxhighlight>-->
{{out}}
Note that "= not c" fails, whereas "= (not c)" passes, see talk page. (Arguably the task definition should be fixed.)
Line 1,293 ⟶ 1,421:
=={{header|Raku}}==
Format of task grammar is changed from EBNF to ABNF to cater for the Grammar::ABNF module and testing data is taken from the Perl entry.
<syntaxhighlight lang="raku" perl6line># 20200511 Raku programming solution
 
use Grammar::ABNF;
Line 1,344 ⟶ 1,472:
DATA
 
say $g.parse($_).Bool, "\t", $_ for DATA.lines</langsyntaxhighlight>
{{out}}
<pre>False 3 + not 5
Line 1,373 ⟶ 1,501:
{{libheader|Wren-dynamic}}
{{libheader|Wren-str}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Enum
import "./str" for Char
 
var Token = Enum.create(
Line 1,586 ⟶ 1,714:
System.print("*** Error at position %(lex.pos). %(lex.error)\n")
}
}</langsyntaxhighlight>
 
{{out}}
9,483

edits