Tuesday, December 29, 2015

Writing New Year's Resolutions

As time passes, we all become different versions of ourselves, although not necessarily much different. This year, I want to become a better version of myself, and I believe that this requires changing habits.

According to The Power of Habit, each habit has a cue, a routine, and a reward; changing habits often involves changing the routine part for an existing habit; this requires setting specific new habits to replace the old ones.

So, with that min mind, here's what I wish for this new year:

  1. I want to be patient and considerate. Whenever I notice myself become frustrated, I will reflect on why it happened and what a better attitude would have been.
  2. I want to be physically healthy, and be conscious of my eating and exercise habits.
  3. I want to regularly learn new things.
And in work:

  1. I want to be reliable by being systematic in task management.
  2. I want to produce quality work.
  3. I want to take new opportunities.

Monday, December 21, 2015

Simple symbol table with yacc

In the last post about yacc, we got yacc to evaluate expressions and print out the evaluated value.

In programs that involve setting and looking up variable values, there is usually some kind of symbol table. At the top of the yacc file, I've added the following global symbol table and related functions:

%{
#include <stdio.h>

#define TABLE_SIZE 26
#define UNSET -1

int SYMBOL_TABLE[TABLE_SIZE];
int lookup(int symbol_num);
void set(int symbol_num, int value);
void reset_table();

%}

In this example, the table symbol is just big enough to fit one variable per letter of the alphabet. The table is expected to be initialized with a special "unset" value before use.

The rule section of the yacc file has been modified to include an "assignment statement" type expression. When an assignment statement is encountered, the symbol table is modified. When a variable is encountered and is being used for its value, the value of the expression is looked up in the symbol table.

%%

start   : stmt { printf($1 ? "true\n" : "false\n"); }
        | expr { printf($1 ? "true\n" : "false\n"); }
        ;

expr    : NOT expr { $$ = ! $2; }
        | expr AND expr { $$ = ($1 && $3); }
        | expr OR expr { $$ = ($1 || $3); }
        | LPAREN expr RPAREN { $$ = $2; }
        | NAME { $$ = lookup($1); }
        | FALSE { $$ = 0; }
        | TRUE { $$ = 1; }
        ;

stmt    : NAME ASSIGN expr { set($1, $3); $$ = $3; }
        ;

%%

We're using two new tokens, so they have to be included in the lex file rules section:

=   { return ASSIGN; }
[a-z] { yylval = yytext[0] - 'a'; return NAME; }

The set and lookup functions still have to be defined, and they can be defined at the bottom of the yacc file after the rules section:

int lookup(int symbol_num) {
  printf("lookup %d\n", symbol_num);
  if (SYMBOL_TABLE[symbol_num] == UNSET ||
      symbol_num < 0 || symbol_num >= TABLE_SIZE) {
    return 0;  // false by default
  }
  return SYMBOL_TABLE[symbol_num];
}

void set(int symbol_num, int value) {
  printf("set %d %d\n", symbol_num, value);
  if (symbol_num < 0 || symbol_num >= TABLE_SIZE) {
    return;  // do nothing by default
  }
  SYMBOL_TABLE[symbol_num] = value;
}

After this is added, the parser also accepts assignment expressions and looks up variables in a table.

> a = not true      
false
> b = (true and true)
true
> a or b
true
> a and b
false

Sunday, December 13, 2015

Ningbonese Tones

How many tones does Ningbonese (Ningbo dialect) have?

This question is more complicated than it appears, and to explain why, one must go back to the history of tones in Chinese language:

In the beginning (Middle Chinese), there were four tones: level (平), rising (上), departing (去) and checked (入). Then, by Late Middle Chinese, however, each tone split into two, yin (阴) and yang (阳), according to whether the initial consonant is voiced or not.

Because the specific tone contour only depended on which of the four tones a word belongs to, along with the initial consonant, it could still be said that there are four tones, but 8 possible "tone contours". Wu Chinese, including Ningbo Dialect, preserves both the voiced and voiceless distinction as well as the yin and yang distinction -- so it could be said that there are four tones, but more possible tone contours.

So how many "tone contours" are there? First, of all, looking at single characters, according to online sources, the tones are as follows:

Tone nameTone ContourExampleEnglish
阴平 yin level53 High rising刀 tauknife
阳平 yang level24 Mid rising逃 dauescape
阴上 yin rising35 Mid rising岛 tauisland
阳上 yang rising213 Low rising导 daulead
阴去 yin departing44 Mid-high level到 tauarrive
阳去 yang departing213 Low rising道 daupath
阴入 yin checked55 High level得 tahget
阳入 yang checked12 Low rising达 dahreach

Yang rising and yang departing have the same contour above; so, according to this table, for individual syllables, there may be seven tone contours. However, to my untrained ears, I can't tell the difference between several of them, so I can only distinguish 6 tone contours:

Tone contourExamples
Falling
Rising逃岛导道
High
High with stop
Rising with stop

Wu Chinese also has Tone Sandhi, so the actual tone contour of a word depends on the words surrounding it -- and that's a topic for another post!

Sunday, December 6, 2015

Ningbonese Vowels

Wu Chinese exhibits several features which Mandarin doesn’t have -- rounded front vowels (like German schön) and nasal vowels (like French bon). Let's take a look!

Firstly, there are the basic simple vowel sounds found in most languages:

IPAExampleEnglish
aa买 mabuy
ee海 hesea
aeɛ蛋 daeegg
ii天 thiheaven
oo沙 sosand
uu古 kuancient

It's worth noting that the "o" is fairly close to "u". There are also some straightforward diphthongs:

eiɐi对 teicorrect
uaua快 khuafast
iaia爹 tiadad
ioio小 shiosmall

There is also the very short vowel which is also found in the Mandarin reading of words like 子, 次, or 四. And in Ningbo Dialect there is also rounded version of this vowel, found in some words like 水:

yɿ四 syfour
yuʮ水 syuwater

Two vowels which may be easy to confuse are the vowels in 好 and 火; the vowel in 好 is just the open-mid back rounded vowel ɔ, whereas the vowel in 火 sounds more like the sound in house.

auɔ好 haugood
ouəu火 houfire

The vowels in Ningbo Dialect which involve rounding are:

iuy区 chiudistrict
euœʏ头 deuhead
ieu手 shieuhand
oeø短 toeshort

A subset of the vowels can be followed by a nasal consonant -- unlike Mandarin, there is no distinction between front (alveolar) and back (velar) nasal sounds. Note, that for some people oen may rhyme with on.

on东 toneast
enəŋ村 tsenvillage
oenøŋ春 tshoenspring
in冰 pinice

For two of the vowels, instead of being followed by nasal consonants, the vowels themselves can become nasalized! Note that in the Wu Chinese Association's romanization system, these are also spelled with an "n"; there is no ambiguity because for each type of vowel it can either be nasalized or followed by a nasal consonant.

anã生 sanbirth
aonɔ̃汤 thaonsoup

Finally: Wu Chinese preserves the "checked tone" of Old Chinese, where syllables can end with stop consonants. The only stop consonant that words can end with is the glottal stop (ʔ).

ah法 fahlaw
oehøʔ雪 soehsnow
ih笔 pihpen
oh木 mohwood
iuehyəʔ月 yuehmoon
iohyoʔ吃 chioheat

Primary source: the Wu Chinese Association website and this post on Baidu Tieba.