diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/chapter17b/17-grammar.ja.md | 123 | ||||
| -rw-r--r-- | docs/chapter17b/17-grammar.md | 123 | ||||
| -rw-r--r-- | docs/chapter17b/Makefile | 12 | ||||
| -rw-r--r-- | docs/chapter17b/README.ja.md | 94 | ||||
| -rw-r--r-- | docs/chapter17b/README.md | 115 |
5 files changed, 467 insertions, 0 deletions
diff --git a/docs/chapter17b/17-grammar.ja.md b/docs/chapter17b/17-grammar.ja.md new file mode 100644 index 00000000..284a3de3 --- /dev/null +++ b/docs/chapter17b/17-grammar.ja.md @@ -0,0 +1,123 @@ +# 第17b章の文法 + +[English](17-grammar.md) | 日本語 + +```antlrv4 +grammar SimpleLanguage; + +// Name lookup, assignable operands, type compatibility, and access permissions +// are checked by the compiler in addition to these syntax rules. +program : statement* EOF ; + +block : '{' statement* '}' ; + +statement + : block + | returnStatement + | ifStatement + | whileStatement + | forStatement + | breakStatement + | continueStatement + | structDeclaration + | declaration ';' + | assignment ';' + | ';' + ; + +returnStatement : 'return' assignment ';' ; +ifStatement : 'if' '(' assignment ')' statement ('else' statement)? ; +whileStatement : 'while' '(' assignment ')' statement ; +breakStatement : 'break' ';' ; +continueStatement : 'continue' ';' ; + +forStatement + : 'for' '(' (declaration | assignment)? ';' assignment? ';' assignment? ')' statement + ; + +structDeclaration : 'struct' IDENTIFIER block ';' ; + +declaration : declarationType binding (',' binding)* ; +declarationType : type | 'var' | 'val' ; +binding : bindingModifier? IDENTIFIER ('=' initializer)? ; +bindingModifier : '!' | '~' ; +initializer : assignment ; + +// The prefix qualifies the named struct reference, not an enclosing array. +// Each [] / [~] suffix qualifies its own array layer. ? requires a reference. +type + : primitiveType typeSuffix* + | accessModifier? typeName typeSuffix* + ; +accessModifier : '!' | '~' ; +typeSuffix : '?' | '[]' | '[~]' ; +typeName : IDENTIFIER ; + +primitiveType + : 'int' | 'i8' | 'i16' | 'i32' | 'i64' + | 'u1' | 'u8' | 'u16' | 'u32' | 'byte' | 'bool' + | 'flt' | 'f32' | 'f64' + ; + +assignment : expression (assignmentOperator assignment)? ; +assignmentOperator + : '=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' + | '<<=' | '>>=' | '>>>=' + ; + +expression : bitwiseExpression ('?' assignment (':' assignment)?)? ; + +bitwiseExpression + : comparisonExpression (('&' | '|' | '^') comparisonExpression)* + ; + +comparisonExpression + : shiftExpression (('==' | '!=' | '<' | '<=' | '>' | '>=') shiftExpression)* + ; + +shiftExpression + : additiveExpression (('<<' | '>>' | '>>>') additiveExpression)* + ; + +additiveExpression + : multiplicativeExpression (('+' | '-') multiplicativeExpression)* + ; + +multiplicativeExpression + : unaryExpression (('*' | '/') unaryExpression)* + ; + +unaryExpression + : ('-' | '!') unaryExpression + | updateOperator IDENTIFIER + | postfixExpression + ; + +// Prefix updates require a local name; postfix updates also allow fields +// and array elements. All updates require an assignable operand. +updateOperator : '++' | '--' ; +postfixExpression : primaryExpression postfixSuffix* updateOperator? ; +postfixSuffix : '.' IDENTIFIER | '[' assignment ']' | '#' ; + +primaryExpression + : INTEGER_LITERAL + | FLOAT_LITERAL + | 'true' + | 'false' + | 'null' + | IDENTIFIER + | '(' assignment ')' + | newExpression + ; + +// Struct initialization uses a block; array allocation supplies a length. +newExpression : 'new' type ('[' assignment ']' | block)? ; + +INTEGER_LITERAL : '0' | [1-9] DIGIT* ; +FLOAT_LITERAL : DIGIT+ ('.' DIGIT* ('e' DIGIT+)? | 'e' DIGIT+) ; +IDENTIFIER : NON_DIGIT (NON_DIGIT | DIGIT)* ; +fragment NON_DIGIT : [a-zA-Z_] ; +fragment DIGIT : [0-9] ; +WHITESPACE : [ \t\r\n]+ -> skip ; +LINE_COMMENT : '//' ~[\r\n]* -> skip ; +``` diff --git a/docs/chapter17b/17-grammar.md b/docs/chapter17b/17-grammar.md new file mode 100644 index 00000000..88f6fc93 --- /dev/null +++ b/docs/chapter17b/17-grammar.md @@ -0,0 +1,123 @@ +# Grammar for Chapter 17b + +English | [日本語](17-grammar.ja.md) + +```antlrv4 +grammar SimpleLanguage; + +// Name lookup, assignable operands, type compatibility, and access permissions +// are checked by the compiler in addition to these syntax rules. +program : statement* EOF ; + +block : '{' statement* '}' ; + +statement + : block + | returnStatement + | ifStatement + | whileStatement + | forStatement + | breakStatement + | continueStatement + | structDeclaration + | declaration ';' + | assignment ';' + | ';' + ; + +returnStatement : 'return' assignment ';' ; +ifStatement : 'if' '(' assignment ')' statement ('else' statement)? ; +whileStatement : 'while' '(' assignment ')' statement ; +breakStatement : 'break' ';' ; +continueStatement : 'continue' ';' ; + +forStatement + : 'for' '(' (declaration | assignment)? ';' assignment? ';' assignment? ')' statement + ; + +structDeclaration : 'struct' IDENTIFIER block ';' ; + +declaration : declarationType binding (',' binding)* ; +declarationType : type | 'var' | 'val' ; +binding : bindingModifier? IDENTIFIER ('=' initializer)? ; +bindingModifier : '!' | '~' ; +initializer : assignment ; + +// The prefix qualifies the named struct reference, not an enclosing array. +// Each [] / [~] suffix qualifies its own array layer. ? requires a reference. +type + : primitiveType typeSuffix* + | accessModifier? typeName typeSuffix* + ; +accessModifier : '!' | '~' ; +typeSuffix : '?' | '[]' | '[~]' ; +typeName : IDENTIFIER ; + +primitiveType + : 'int' | 'i8' | 'i16' | 'i32' | 'i64' + | 'u1' | 'u8' | 'u16' | 'u32' | 'byte' | 'bool' + | 'flt' | 'f32' | 'f64' + ; + +assignment : expression (assignmentOperator assignment)? ; +assignmentOperator + : '=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' + | '<<=' | '>>=' | '>>>=' + ; + +expression : bitwiseExpression ('?' assignment (':' assignment)?)? ; + +bitwiseExpression + : comparisonExpression (('&' | '|' | '^') comparisonExpression)* + ; + +comparisonExpression + : shiftExpression (('==' | '!=' | '<' | '<=' | '>' | '>=') shiftExpression)* + ; + +shiftExpression + : additiveExpression (('<<' | '>>' | '>>>') additiveExpression)* + ; + +additiveExpression + : multiplicativeExpression (('+' | '-') multiplicativeExpression)* + ; + +multiplicativeExpression + : unaryExpression (('*' | '/') unaryExpression)* + ; + +unaryExpression + : ('-' | '!') unaryExpression + | updateOperator IDENTIFIER + | postfixExpression + ; + +// Prefix updates require a local name; postfix updates also allow fields +// and array elements. All updates require an assignable operand. +updateOperator : '++' | '--' ; +postfixExpression : primaryExpression postfixSuffix* updateOperator? ; +postfixSuffix : '.' IDENTIFIER | '[' assignment ']' | '#' ; + +primaryExpression + : INTEGER_LITERAL + | FLOAT_LITERAL + | 'true' + | 'false' + | 'null' + | IDENTIFIER + | '(' assignment ')' + | newExpression + ; + +// Struct initialization uses a block; array allocation supplies a length. +newExpression : 'new' type ('[' assignment ']' | block)? ; + +INTEGER_LITERAL : '0' | [1-9] DIGIT* ; +FLOAT_LITERAL : DIGIT+ ('.' DIGIT* ('e' DIGIT+)? | 'e' DIGIT+) ; +IDENTIFIER : NON_DIGIT (NON_DIGIT | DIGIT)* ; +fragment NON_DIGIT : [a-zA-Z_] ; +fragment DIGIT : [0-9] ; +WHITESPACE : [ \t\r\n]+ -> skip ; +LINE_COMMENT : '//' ~[\r\n]* -> skip ; +``` diff --git a/docs/chapter17b/Makefile b/docs/chapter17b/Makefile new file mode 100644 index 00000000..12659b8f --- /dev/null +++ b/docs/chapter17b/Makefile @@ -0,0 +1,12 @@ +GV := $(wildcard *.gv) +SVG := $(patsubst %.gv,%.svg,$(GV)) + +.PHONY: all +all: $(SVG) + +%.svg: %.gv + dot -Tsvg $< > $@ + +.PHONY: clean +clean: + @rm -f $(SVG) diff --git a/docs/chapter17b/README.ja.md b/docs/chapter17b/README.ja.md new file mode 100644 index 00000000..8bb3d952 --- /dev/null +++ b/docs/chapter17b/README.ja.md @@ -0,0 +1,94 @@ +# 第17b章: 糖衣構文 + +[English](README.md) | 日本語 + +[前: 第17a章](../chapter17a/README.ja.md) | +[次: 第18章](../chapter18/README.ja.md) + +この文書は [原文](README.md) の日本語訳です。 + +この章の[完全な言語文法](17-grammar.ja.md)はこちらです。 + +## 目次 + +1. [前置・後置インクリメント](#前置後置インクリメント) +2. [複合代入](#複合代入) +3. [var/val](#var-と-val) +4. [三項演算](#三項演算) +5. [for ループ](#for-ループ) + +第17a章では、代入で確認する権限を確立しました。この章ではその権限を変えずに、代入と制御フローを短く書く方法を追加します。その後、第18章で関数と呼び出しを導入します。 + +## 前置・後置インクリメント + +`arg++` と `arg--` を、通常の意味で許します。値を更新し、式の値は更新前の値になります。最長一致を使うので、`arg---arg` は `(arg--)-arg` としてパースします。 + +`s.fld++` と `ary[idx]++`、それらの `--` 版も許します。 + +前置インクリメントは、今のところ識別子についてだけ許します。例は `--pc` です。 + +## 複合代入 + +後置インクリメントと同じ方向で、局所変数への `op=` 代入も、ほかの言語に似た意味論で許すようになります。サポートする演算子は `+=`、`-=`、`*=`、`/=`、`&=`、`|=`、`^=`、`<<=`、`>>=`、`>>>=` です。ビット演算とシフトの代入には整数オペランドが必要です。`>>=` は符号を保持し、`>>>=` はゼロを入れます。代入は右辺を1回評価し、結果を変数の型に狭めて格納し、その格納値を式の結果とします。代入は、`x |= y <<= 2` のように右から左に結合します。 + +## var と val + +`var` と `val` は変数を宣言し、その型を推論します。`var` は再代入可能な束縛、`val` は固定の束縛を推論します。両方とも初期化式のアクセス権限を保ちます。どちらも、書き込み可能なオブジェクトを読み取り専用にはしません。この2つの独立した権限は[第17a章](../chapter17a/README.ja.md)から来ています。 + +```cpp +struct Point { int x; }; +val p = new Point; // Fixed binding to a writable new object +p.x = 3; // Allowed +// p = new Point; // Error: fixed binding +Point view = p; // Explicit read-only view +var q = view; // Reassignable binding, still read-only access +// q.x = 4; // Error: cannot restore write permission by inference +``` + +型推論には初期化子が必須です。プリミティブでは広い数値型(`int` または `flt`)を推論し、参照ではアクセス権限を保持します。再代入可能な推論された参照は、後で空の値を保持できるように null を許容します。明示的な型は、宣言された幅と null 許容性を維持します。関数パラメータには依然として明示的な型が必要です。 + +## 三項演算 + +`pred ? e_true : e_false` を許します。`pred ? e_true` も許し、この場合の false の結果は true の結果のゼロ型版です。 + +## for ループ + +C/C++ 形式の `for` ループを許します。 + +`for( init; test; next ) body` + +例: + +```cpp +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return sum; +``` + +`init`、`test`、`next` のどれも空にできます。`init` には新しい変数の宣言を許し、そのスコープは `for` 式に限定されます。 + +```cpp +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return i; // ERROR: Undefined name 'i' +``` + +誤った `find` 呼び出し: + +```cpp +for( int i=0; i<ary#; i++ ) + if( ary[i]==e ) + break; +do_stuff(i); // ERROR: undefined name 'i' +``` + +`find` 呼び出しの例: + +```cpp +for( int i=0; i<ary#; i++ ) + if( ary[i]==e ) + return i; +return -1; +``` diff --git a/docs/chapter17b/README.md b/docs/chapter17b/README.md new file mode 100644 index 00000000..2d6cf387 --- /dev/null +++ b/docs/chapter17b/README.md @@ -0,0 +1,115 @@ +# Chapter 17b: Syntax Sugar + +English | [日本語](README.ja.md) + +[Previous: Chapter 17a](../chapter17a/README.md) | +[Next: Chapter 18](../chapter18/README.md) + + +Here is the [complete language grammar](17-grammar.md) for this chapter. + +## Table of Contents + +1. [Pre/Post-increment](#prepost-increment) +2. [Operator assignment](#operator-assignment) +3. [var/val](#var--val) +4. [Trinary](#trinary) +5. [For Loops](#for-loops) + +Chapter 17a established the permissions checked by assignments. This chapter +adds shorter ways to write assignments and control flow without changing those +permissions. Chapter 18 then introduces functions and calls. + +## Pre/Post-increment + +Allow `arg++` and `arg--` with the usual meanings; the value is updated and the +expression is the pre-update value. Greedy match is used so `arg---arg` parses +as `(arg--)-arg`. + +Also allows `s.fld++` and `ary[idx]++`, and their `--` variants. + +Allow pre-increment for identifiers only, for now: `--pc`. + + +## Operator assignment + +Along the same lines as post-increment, we now allow `op=` assignment +on local variables with semantics similar to other languages. The supported +operators are `+=`, `-=`, `*=`, `/=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, and `>>>=`. +Bitwise and shift assignments require integer operands; `>>=` preserves the sign +while `>>>=` shifts in zeros. The assignment evaluates its right-hand side once, +stores the result narrowed to the variable's type, and yields that stored value. +Assignments associate right-to-left, as in `x |= y <<= 2`. + + + +## var & val + +`var` and `val` declare variables and infer their types; `var` infers a +reassignable binding while `val` infers a fixed binding. Both preserve access +permissions from the initializing expression. Neither makes a writable object +read-only. The two independent permissions come from [Chapter +17a](../chapter17a/README.md). + +```cpp +struct Point { int x; }; +val p = new Point; // Fixed binding to a writable new object +p.x = 3; // Allowed +// p = new Point; // Error: fixed binding +Point view = p; // Explicit read-only view +var q = view; // Reassignable binding, still read-only access +// q.x = 4; // Error: cannot restore write permission by inference +``` + +The initializer is required for type inference. Primitives infer their broad +numeric type (`int` or `flt`); references retain their access permissions. A +reassignable inferred reference allows null so it can later hold the empty +value. Explicit types retain their declared width and nullability. Function +parameters still require explicit types. + +## Trinary + +Allow `pred ? e_true : e_false`. Also allow `pred ? e_true`, where the false result +is the zero type version of the true result. + + +## For Loops + +Allow C/C++ style `for` loops: + +`for( init; test; next ) body` + +Example: + +```cpp +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return sum; +``` + +Any of `init`, `test` and `next` can be empty. `init` allows for declaration +of a new variable, with scope limited to the `for` expression. + +```cpp +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return i; // ERROR: Undefined name 'i' +``` + +A broken `find` call: +```cpp +for( int i=0; i<ary#; i++ ) + if( ary[i]==e ) + break; +do_stuff(i); // ERROR: undefined name 'i' +``` + +An example `find` call: +```cpp +for( int i=0; i<ary#; i++ ) + if( ary[i]==e ) + return i; +return -1; +``` |
